This commit is contained in:
Coleen Phillimore 2017-11-08 16:03:35 -05:00
commit a68609ede5
568 changed files with 14570 additions and 15321 deletions

View File

@ -454,3 +454,4 @@ e5357aa85dadacc6562175ff74714fecfb4470cf jdk-10+22
b87d7b5d5dedc1185e5929470f945b7378cdb3ad jdk-10+27
92f08900cb3c0d694e5c529a676c1c9e5909193f jdk-10+28
a6e591e12f122768f675428e1e5a838fd0e9c7ec jdk-10+29
8fee80b92e65149f7414250fd5e34b6f35d417b4 jdk-10+30

View File

@ -67,6 +67,7 @@ ifeq ($(INCLUDE_GRAAL), true)
$(SRC_DIR)/org.graalvm.compiler.phases.common/src \
$(SRC_DIR)/org.graalvm.compiler.serviceprovider/src \
$(SRC_DIR)/org.graalvm.compiler.virtual/src \
$(SRC_DIR)/org.graalvm.graphio/src \
$(SRC_DIR)/org.graalvm.util/src \
$(VM_CI_SRC_DIR)/jdk.vm.ci.code/src \
$(VM_CI_SRC_DIR)/jdk.vm.ci.common/src \
@ -125,6 +126,7 @@ ifeq ($(INCLUDE_GRAAL), true)
$(SRC_DIR)/org.graalvm.compiler.nodeinfo/src \
$(SRC_DIR)/org.graalvm.compiler.options/src \
$(SRC_DIR)/org.graalvm.compiler.serviceprovider/src \
$(SRC_DIR)/org.graalvm.graphio/src \
$(SRC_DIR)/org.graalvm.util/src \
$(VM_CI_SRC_DIR)/jdk.vm.ci.code/src \
$(VM_CI_SRC_DIR)/jdk.vm.ci.common/src \

View File

@ -639,6 +639,14 @@ AC_DEFUN_ONCE([BASIC_SETUP_DEVKIT],
elif test -d "$DEVKIT_ROOT/$host/sys-root"; then
SYSROOT="$DEVKIT_ROOT/$host/sys-root"
fi
if test "x$DEVKIT_ROOT" != x; then
DEVKIT_LIB_DIR="$DEVKIT_ROOT/lib"
if test "x$OPENJDK_TARGET_CPU_BITS" = x64; then
DEVKIT_LIB_DIR="$DEVKIT_ROOT/lib64"
fi
AC_SUBST(DEVKIT_LIB_DIR)
fi
]
)

View File

@ -1,5 +1,5 @@
SRC#
# Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
# Copyright (c) 2011, 2017, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@ -203,6 +203,9 @@ FLAGS_SETUP_COMPILER_FLAGS_MISC
JDKOPT_SETUP_DEBUG_SYMBOLS
JDKOPT_SETUP_CODE_COVERAGE
# AddressSanitizer
JDKOPT_SETUP_ADDRESS_SANITIZER
# Need toolchain to setup dtrace
HOTSPOT_SETUP_DTRACE
HOTSPOT_ENABLE_DISABLE_AOT

View File

@ -690,6 +690,7 @@ FREETYPE_LICENSE
FREETYPE_BUNDLE_LIB_PATH
FREETYPE_LIBS
FREETYPE_CFLAGS
FONTCONFIG_CFLAGS
CUPS_CFLAGS
X_EXTRA_LIBS
X_LIBS
@ -704,6 +705,7 @@ FIXPATH
BUILD_GTEST
ENABLE_CDS
ENABLE_AOT
ASAN_ENABLED
GCOV_ENABLED
ZIP_EXTERNAL_DEBUG_SYMBOLS
COPY_DEBUG_SYMBOLS
@ -958,6 +960,7 @@ CONF_NAME
SPEC
SDKROOT
XCODEBUILD
DEVKIT_LIB_DIR
JVM_VARIANT_MAIN
VALID_JVM_VARIANTS
JVM_VARIANTS
@ -1171,6 +1174,7 @@ with_native_debug_symbols
enable_debug_symbols
enable_zip_debug_info
enable_native_coverage
enable_asan
enable_dtrace
enable_aot
enable_cds
@ -1181,6 +1185,8 @@ with_msvcp_dll
with_x
with_cups
with_cups_include
with_fontconfig
with_fontconfig_include
with_freetype
with_freetype_include
with_freetype_lib
@ -1976,6 +1982,7 @@ Optional Features:
--enable-native-coverage
enable native compilation with code coverage
data[disabled]
--enable-asan enable AddressSanitizer if possible [disabled]
--enable-dtrace[=yes/no/auto]
enable dtrace. Default is auto, where dtrace is
enabled if all dependencies are present.
@ -2109,6 +2116,10 @@ Optional Packages:
--with-cups specify prefix directory for the cups package
(expecting the headers under PATH/include)
--with-cups-include specify directory for the cups include files
--with-fontconfig specify prefix directory for the fontconfig package
(expecting the headers under PATH/include)
--with-fontconfig-include
specify directory for the fontconfig include files
--with-freetype specify prefix directory for the freetype package
(expecting the libraries under PATH/lib and the
headers under PATH/include)
@ -4166,6 +4177,8 @@ apt_help() {
PKGHANDLER_COMMAND="sudo apt-get install libasound2-dev" ;;
cups)
PKGHANDLER_COMMAND="sudo apt-get install libcups2-dev" ;;
fontconfig)
PKGHANDLER_COMMAND="sudo apt-get install libfontconfig1-dev" ;;
freetype)
PKGHANDLER_COMMAND="sudo apt-get install libfreetype6-dev" ;;
ffi)
@ -4189,6 +4202,8 @@ yum_help() {
PKGHANDLER_COMMAND="sudo yum install alsa-lib-devel" ;;
cups)
PKGHANDLER_COMMAND="sudo yum install cups-devel" ;;
fontconfig)
PKGHANDLER_COMMAND="sudo yum install fontconfig-devel" ;;
freetype)
PKGHANDLER_COMMAND="sudo yum install freetype-devel" ;;
x11)
@ -4403,6 +4418,12 @@ VALID_JVM_VARIANTS="server client minimal core zero zeroshark custom"
#
###############################################################################
#
# AddressSanitizer
#
################################################################################
#
# Static build support. When enabled will generate static
@ -4746,6 +4767,36 @@ VALID_JVM_VARIANTS="server client minimal core zero zeroshark custom"
################################################################################
#
# Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License version 2 only, as
# published by the Free Software Foundation. Oracle designates this
# particular file as subject to the "Classpath" exception as provided
# by Oracle in the LICENSE file that accompanied this code.
#
# This code is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
# version 2 for more details (a copy is included in the LICENSE file that
# accompanied this code).
#
# You should have received a copy of the GNU General Public License version
# 2 along with this work; if not, write to the Free Software Foundation,
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
#
# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
# or visit www.oracle.com if you need additional information or have any
# questions.
#
################################################################################
# Setup fontconfig
################################################################################
################################################################################
# Determine which libraries are needed for this configuration
@ -5115,7 +5166,7 @@ VS_SDK_PLATFORM_NAME_2013=
#CUSTOM_AUTOCONF_INCLUDE
# Do not change or remove the following line, it is needed for consistency checks:
DATE_WHEN_GENERATED=1509013542
DATE_WHEN_GENERATED=1509128484
###############################################################################
#
@ -17273,6 +17324,14 @@ $as_echo "$DEVKIT_ROOT" >&6; }
SYSROOT="$DEVKIT_ROOT/$host/sys-root"
fi
if test "x$DEVKIT_ROOT" != x; then
DEVKIT_LIB_DIR="$DEVKIT_ROOT/lib"
if test "x$OPENJDK_TARGET_CPU_BITS" = x64; then
DEVKIT_LIB_DIR="$DEVKIT_ROOT/lib64"
fi
fi
fi
@ -54169,6 +54228,49 @@ $as_echo "no" >&6; }
# AddressSanitizer
# Check whether --enable-asan was given.
if test "${enable_asan+set}" = set; then :
enableval=$enable_asan;
fi
ASAN_ENABLED="no"
if test "x$enable_asan" = "xyes"; then
case $TOOLCHAIN_TYPE in
gcc | clang)
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if asan is enabled" >&5
$as_echo_n "checking if asan is enabled... " >&6; }
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
ASAN_CFLAGS="-fsanitize=address -fno-omit-frame-pointer"
ASAN_LDFLAGS="-fsanitize=address"
JVM_CFLAGS="$JVM_CFLAGS $ASAN_CFLAGS"
JVM_LDFLAGS="$JVM_LDFLAGS $ASAN_LDFLAGS"
CFLAGS_JDKLIB="$CFLAGS_JDKLIB $ASAN_CFLAGS"
CFLAGS_JDKEXE="$CFLAGS_JDKEXE $ASAN_CFLAGS"
CXXFLAGS_JDKLIB="$CXXFLAGS_JDKLIB $ASAN_CFLAGS"
CXXFLAGS_JDKEXE="$CXXFLAGS_JDKEXE $ASAN_CFLAGS"
LDFLAGS_JDKLIB="$LDFLAGS_JDKLIB $ASAN_LDFLAGS"
LDFLAGS_JDKEXE="$LDFLAGS_JDKEXE $ASAN_LDFLAGS"
ASAN_ENABLED="yes"
;;
*)
as_fn_error $? "--enable-asan only works with toolchain type gcc or clang" "$LINENO" 5
;;
esac
elif test "x$enable_asan" = "xno"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if asan is enabled" >&5
$as_echo_n "checking if asan is enabled... " >&6; }
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
elif test "x$enable_asan" != "x"; then
as_fn_error $? "--enable-asan can only be assigned \"yes\" or \"no\"" "$LINENO" 5
fi
# Need toolchain to setup dtrace
# Test for dtrace dependencies
@ -54480,6 +54582,16 @@ $as_echo "yes" >&6; }
NEEDS_LIB_X11=true
fi
# Check if fontconfig is needed
if test "x$OPENJDK_TARGET_OS" = xwindows || test "x$OPENJDK_TARGET_OS" = xmacosx; then
# No fontconfig support on windows or macosx
NEEDS_LIB_FONTCONFIG=false
else
# All other instances need fontconfig, even if building headless only,
# libawt still needs fontconfig headers.
NEEDS_LIB_FONTCONFIG=true
fi
# Check if cups is needed
if test "x$OPENJDK_TARGET_OS" = xwindows; then
# Windows have a separate print system
@ -58297,6 +58409,116 @@ done
# Check whether --with-fontconfig was given.
if test "${with_fontconfig+set}" = set; then :
withval=$with_fontconfig;
fi
# Check whether --with-fontconfig-include was given.
if test "${with_fontconfig_include+set}" = set; then :
withval=$with_fontconfig_include;
fi
if test "x$NEEDS_LIB_FONTCONFIG" = xfalse; then
if (test "x${with_fontconfig}" != x && test "x${with_fontconfig}" != xno) || \
(test "x${with_fontconfig_include}" != x && test "x${with_fontconfig_include}" != xno); then
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: fontconfig not used, so --with-fontconfig[-*] is ignored" >&5
$as_echo "$as_me: WARNING: fontconfig not used, so --with-fontconfig[-*] is ignored" >&2;}
fi
FONTCONFIG_CFLAGS=
else
FONTCONFIG_FOUND=no
if test "x${with_fontconfig}" = xno || test "x${with_fontconfig_include}" = xno; then
as_fn_error $? "It is not possible to disable the use of fontconfig. Remove the --without-fontconfig option." "$LINENO" 5
fi
if test "x${with_fontconfig}" != x; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for fontconfig headers" >&5
$as_echo_n "checking for fontconfig headers... " >&6; }
if test -s "${with_fontconfig}/include/fontconfig/fontconfig.h"; then
FONTCONFIG_CFLAGS="-I${with_fontconfig}/include"
FONTCONFIG_FOUND=yes
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $FONTCONFIG_FOUND" >&5
$as_echo "$FONTCONFIG_FOUND" >&6; }
else
as_fn_error $? "Can't find 'include/fontconfig/fontconfig.h' under ${with_fontconfig} given with the --with-fontconfig option." "$LINENO" 5
fi
fi
if test "x${with_fontconfig_include}" != x; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for fontconfig headers" >&5
$as_echo_n "checking for fontconfig headers... " >&6; }
if test -s "${with_fontconfig_include}/fontconfig/fontconfig.h"; then
FONTCONFIG_CFLAGS="-I${with_fontconfig_include}"
FONTCONFIG_FOUND=yes
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $FONTCONFIG_FOUND" >&5
$as_echo "$FONTCONFIG_FOUND" >&6; }
else
as_fn_error $? "Can't find 'fontconfig/fontconfig.h' under ${with_fontconfig_include} given with the --with-fontconfig-include option." "$LINENO" 5
fi
fi
if test "x$FONTCONFIG_FOUND" = xno; then
# Are the fontconfig headers installed in the default /usr/include location?
for ac_header in fontconfig/fontconfig.h
do :
ac_fn_cxx_check_header_mongrel "$LINENO" "fontconfig/fontconfig.h" "ac_cv_header_fontconfig_fontconfig_h" "$ac_includes_default"
if test "x$ac_cv_header_fontconfig_fontconfig_h" = xyes; then :
cat >>confdefs.h <<_ACEOF
#define HAVE_FONTCONFIG_FONTCONFIG_H 1
_ACEOF
FONTCONFIG_FOUND=yes
FONTCONFIG_CFLAGS=
DEFAULT_FONTCONFIG=yes
fi
done
fi
if test "x$FONTCONFIG_FOUND" = xno; then
# Print a helpful message on how to acquire the necessary build dependency.
# fontconfig is the help tag: freetype, cups, alsa etc
MISSING_DEPENDENCY=fontconfig
if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then
cygwin_help $MISSING_DEPENDENCY
elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then
msys_help $MISSING_DEPENDENCY
else
PKGHANDLER_COMMAND=
case $PKGHANDLER in
apt-get)
apt_help $MISSING_DEPENDENCY ;;
yum)
yum_help $MISSING_DEPENDENCY ;;
brew)
brew_help $MISSING_DEPENDENCY ;;
port)
port_help $MISSING_DEPENDENCY ;;
pkgutil)
pkgutil_help $MISSING_DEPENDENCY ;;
pkgadd)
pkgadd_help $MISSING_DEPENDENCY ;;
esac
if test "x$PKGHANDLER_COMMAND" != x; then
HELP_MSG="You might be able to fix this by running '$PKGHANDLER_COMMAND'."
fi
fi
as_fn_error $? "Could not find fontconfig! $HELP_MSG " "$LINENO" 5
fi
fi
# Check whether --with-freetype was given.
if test "${with_freetype+set}" = set; then :
withval=$with_freetype;
@ -65831,6 +66053,7 @@ $as_echo "no, not found at $STLPORT_LIB" >&6; }
# Hotspot setup depends on lib checks.

View File

@ -113,6 +113,8 @@ apt_help() {
PKGHANDLER_COMMAND="sudo apt-get install libasound2-dev" ;;
cups)
PKGHANDLER_COMMAND="sudo apt-get install libcups2-dev" ;;
fontconfig)
PKGHANDLER_COMMAND="sudo apt-get install libfontconfig1-dev" ;;
freetype)
PKGHANDLER_COMMAND="sudo apt-get install libfreetype6-dev" ;;
ffi)
@ -136,6 +138,8 @@ yum_help() {
PKGHANDLER_COMMAND="sudo yum install alsa-lib-devel" ;;
cups)
PKGHANDLER_COMMAND="sudo yum install cups-devel" ;;
fontconfig)
PKGHANDLER_COMMAND="sudo yum install fontconfig-devel" ;;
freetype)
PKGHANDLER_COMMAND="sudo yum install freetype-devel" ;;
x11)

View File

@ -399,6 +399,46 @@ AC_DEFUN_ONCE([JDKOPT_SETUP_CODE_COVERAGE],
AC_SUBST(GCOV_ENABLED)
])
###############################################################################
#
# AddressSanitizer
#
AC_DEFUN_ONCE([JDKOPT_SETUP_ADDRESS_SANITIZER],
[
AC_ARG_ENABLE(asan, [AS_HELP_STRING([--enable-asan],
[enable AddressSanitizer if possible @<:@disabled@:>@])])
ASAN_ENABLED="no"
if test "x$enable_asan" = "xyes"; then
case $TOOLCHAIN_TYPE in
gcc | clang)
AC_MSG_CHECKING([if asan is enabled])
AC_MSG_RESULT([yes])
ASAN_CFLAGS="-fsanitize=address -fno-omit-frame-pointer"
ASAN_LDFLAGS="-fsanitize=address"
JVM_CFLAGS="$JVM_CFLAGS $ASAN_CFLAGS"
JVM_LDFLAGS="$JVM_LDFLAGS $ASAN_LDFLAGS"
CFLAGS_JDKLIB="$CFLAGS_JDKLIB $ASAN_CFLAGS"
CFLAGS_JDKEXE="$CFLAGS_JDKEXE $ASAN_CFLAGS"
CXXFLAGS_JDKLIB="$CXXFLAGS_JDKLIB $ASAN_CFLAGS"
CXXFLAGS_JDKEXE="$CXXFLAGS_JDKEXE $ASAN_CFLAGS"
LDFLAGS_JDKLIB="$LDFLAGS_JDKLIB $ASAN_LDFLAGS"
LDFLAGS_JDKEXE="$LDFLAGS_JDKEXE $ASAN_LDFLAGS"
ASAN_ENABLED="yes"
;;
*)
AC_MSG_ERROR([--enable-asan only works with toolchain type gcc or clang])
;;
esac
elif test "x$enable_asan" = "xno"; then
AC_MSG_CHECKING([if asan is enabled])
AC_MSG_RESULT([no])
elif test "x$enable_asan" != "x"; then
AC_MSG_ERROR([--enable-asan can only be assigned "yes" or "no"])
fi
AC_SUBST(ASAN_ENABLED)
])
################################################################################
#
# Static build support. When enabled will generate static

View File

@ -0,0 +1,85 @@
#
# Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License version 2 only, as
# published by the Free Software Foundation. Oracle designates this
# particular file as subject to the "Classpath" exception as provided
# by Oracle in the LICENSE file that accompanied this code.
#
# This code is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
# version 2 for more details (a copy is included in the LICENSE file that
# accompanied this code).
#
# You should have received a copy of the GNU General Public License version
# 2 along with this work; if not, write to the Free Software Foundation,
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
#
# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
# or visit www.oracle.com if you need additional information or have any
# questions.
#
################################################################################
# Setup fontconfig
################################################################################
AC_DEFUN_ONCE([LIB_SETUP_FONTCONFIG],
[
AC_ARG_WITH(fontconfig, [AS_HELP_STRING([--with-fontconfig],
[specify prefix directory for the fontconfig package
(expecting the headers under PATH/include)])])
AC_ARG_WITH(fontconfig-include, [AS_HELP_STRING([--with-fontconfig-include],
[specify directory for the fontconfig include files])])
if test "x$NEEDS_LIB_FONTCONFIG" = xfalse; then
if (test "x${with_fontconfig}" != x && test "x${with_fontconfig}" != xno) || \
(test "x${with_fontconfig_include}" != x && test "x${with_fontconfig_include}" != xno); then
AC_MSG_WARN([[fontconfig not used, so --with-fontconfig[-*] is ignored]])
fi
FONTCONFIG_CFLAGS=
else
FONTCONFIG_FOUND=no
if test "x${with_fontconfig}" = xno || test "x${with_fontconfig_include}" = xno; then
AC_MSG_ERROR([It is not possible to disable the use of fontconfig. Remove the --without-fontconfig option.])
fi
if test "x${with_fontconfig}" != x; then
AC_MSG_CHECKING([for fontconfig headers])
if test -s "${with_fontconfig}/include/fontconfig/fontconfig.h"; then
FONTCONFIG_CFLAGS="-I${with_fontconfig}/include"
FONTCONFIG_FOUND=yes
AC_MSG_RESULT([$FONTCONFIG_FOUND])
else
AC_MSG_ERROR([Can't find 'include/fontconfig/fontconfig.h' under ${with_fontconfig} given with the --with-fontconfig option.])
fi
fi
if test "x${with_fontconfig_include}" != x; then
AC_MSG_CHECKING([for fontconfig headers])
if test -s "${with_fontconfig_include}/fontconfig/fontconfig.h"; then
FONTCONFIG_CFLAGS="-I${with_fontconfig_include}"
FONTCONFIG_FOUND=yes
AC_MSG_RESULT([$FONTCONFIG_FOUND])
else
AC_MSG_ERROR([Can't find 'fontconfig/fontconfig.h' under ${with_fontconfig_include} given with the --with-fontconfig-include option.])
fi
fi
if test "x$FONTCONFIG_FOUND" = xno; then
# Are the fontconfig headers installed in the default /usr/include location?
AC_CHECK_HEADERS([fontconfig/fontconfig.h], [
FONTCONFIG_FOUND=yes
FONTCONFIG_CFLAGS=
DEFAULT_FONTCONFIG=yes
])
fi
if test "x$FONTCONFIG_FOUND" = xno; then
HELP_MSG_MISSING_DEPENDENCY([fontconfig])
AC_MSG_ERROR([Could not find fontconfig! $HELP_MSG ])
fi
fi
AC_SUBST(FONTCONFIG_CFLAGS)
])

View File

@ -31,6 +31,7 @@ m4_include([lib-ffi.m4])
m4_include([lib-freetype.m4])
m4_include([lib-std.m4])
m4_include([lib-x11.m4])
m4_include([lib-fontconfig.m4])
################################################################################
# Determine which libraries are needed for this configuration
@ -47,6 +48,16 @@ AC_DEFUN_ONCE([LIB_DETERMINE_DEPENDENCIES],
NEEDS_LIB_X11=true
fi
# Check if fontconfig is needed
if test "x$OPENJDK_TARGET_OS" = xwindows || test "x$OPENJDK_TARGET_OS" = xmacosx; then
# No fontconfig support on windows or macosx
NEEDS_LIB_FONTCONFIG=false
else
# All other instances need fontconfig, even if building headless only,
# libawt still needs fontconfig headers.
NEEDS_LIB_FONTCONFIG=true
fi
# Check if cups is needed
if test "x$OPENJDK_TARGET_OS" = xwindows; then
# Windows have a separate print system
@ -83,6 +94,7 @@ AC_DEFUN_ONCE([LIB_SETUP_LIBRARIES],
LIB_SETUP_STD_LIBS
LIB_SETUP_X11
LIB_SETUP_CUPS
LIB_SETUP_FONTCONFIG
LIB_SETUP_FREETYPE
LIB_SETUP_ALSA
LIB_SETUP_LIBFFI

View File

@ -311,6 +311,16 @@ UNLIMITED_CRYPTO=@UNLIMITED_CRYPTO@
GCOV_ENABLED=@GCOV_ENABLED@
# AddressSanitizer
export ASAN_ENABLED:=@ASAN_ENABLED@
export DEVKIT_LIB_DIR:=@DEVKIT_LIB_DIR@
ifeq ($(ASAN_ENABLED), yes)
export ASAN_OPTIONS="handle_segv=0 detect_leaks=0"
ifneq ($(DEVKIT_LIB_DIR),)
export LD_LIBRARY_PATH:=$(LD_LIBRARY_PATH):$(DEVKIT_LIB_DIR)
endif
endif
# Necessary additional compiler flags to compile X11
X_CFLAGS:=@X_CFLAGS@
X_LIBS:=@X_LIBS@

View File

@ -1060,7 +1060,7 @@ var getJibProfilesDependencies = function (input, common) {
jtreg: {
server: "javare",
revision: "4.2",
build_number: "b09",
build_number: "b10",
checksum_file: "MD5_VALUES",
file: "jtreg_bin-4.2.zip",
environment_name: "JT_HOME",

View File

@ -317,6 +317,7 @@ ifeq ($(findstring $(OPENJDK_TARGET_OS),windows macosx),)
LIBAWT_XAWT_CFLAGS += -DXAWT -DXAWT_HACK \
-DPACKAGE_PATH=\"$(PACKAGE_PATH)\" \
$(FONTCONFIG_CFLAGS) \
$(CUPS_CFLAGS)
ifeq ($(OPENJDK_TARGET_OS), solaris)
@ -555,6 +556,7 @@ ifeq ($(findstring $(OPENJDK_TARGET_OS), windows macosx),)
-DHEADLESS=true \
-DPACKAGE_PATH=\"$(PACKAGE_PATH)\" \
$(CUPS_CFLAGS) \
$(FONTCONFIG_CFLAGS) \
$(X_CFLAGS) \
$(LIBAWT_HEADLESS_CFLAGS), \
DISABLED_WARNINGS_xlc := 1506-356, \

View File

@ -431,11 +431,11 @@ frame frame::sender_for_interpreter_frame(RegisterMap* map) const {
// This is the sp before any possible extension (adapter/locals).
intptr_t* unextended_sp = interpreter_frame_sender_sp();
#if defined(COMPILER2) || INCLUDE_JVMCI
#if COMPILER2_OR_JVMCI
if (map->update_map()) {
update_map_with_saved_link(map, (intptr_t**) addr_at(link_offset));
}
#endif // COMPILER2 || INCLUDE_JVMCI
#endif // COMPILER2_OR_JVMCI
return frame(sender_sp, unextended_sp, link(), sender_pc());
}

View File

@ -41,7 +41,7 @@
#ifdef COMPILER1
#include "c1/c1_Runtime1.hpp"
#endif
#if defined(COMPILER2) || INCLUDE_JVMCI
#if COMPILER2_OR_JVMCI
#include "adfiles/ad_aarch64.hpp"
#include "opto/runtime.hpp"
#endif
@ -114,7 +114,7 @@ class RegisterSaver {
};
OopMap* RegisterSaver::save_live_registers(MacroAssembler* masm, int additional_frame_words, int* total_frame_words, bool save_vectors) {
#if defined(COMPILER2) || INCLUDE_JVMCI
#if COMPILER2_OR_JVMCI
if (save_vectors) {
// Save upper half of vector registers
int vect_words = 32 * 8 / wordSize;
@ -2688,7 +2688,7 @@ uint SharedRuntime::out_preserve_stack_slots() {
return 0;
}
#if defined(COMPILER2) || INCLUDE_JVMCI
#if COMPILER2_OR_JVMCI
//------------------------------generate_uncommon_trap_blob--------------------
void SharedRuntime::generate_uncommon_trap_blob() {
// Allocate space for the code
@ -2894,7 +2894,7 @@ void SharedRuntime::generate_uncommon_trap_blob() {
}
#endif
}
#endif // COMPILER2
#endif // COMPILER2_OR_JVMCI
//------------------------------generate_handler_blob------
@ -3070,8 +3070,7 @@ RuntimeStub* SharedRuntime::generate_resolve_blob(address destination, const cha
return RuntimeStub::new_runtime_stub(name, &buffer, frame_complete, frame_size_in_words, oop_maps, true);
}
#if defined(COMPILER2) || INCLUDE_JVMCI
#if COMPILER2_OR_JVMCI
// This is here instead of runtime_x86_64.cpp because it uses SimpleRuntimeFrame
//
//------------------------------generate_exception_blob---------------------------
@ -3200,4 +3199,4 @@ void OptoRuntime::generate_exception_blob() {
// Set exception blob
_exception_blob = ExceptionBlob::create(&buffer, oop_maps, SimpleRuntimeFrame::framesize >> 1);
}
#endif // COMPILER2
#endif // COMPILER2_OR_JVMCI

View File

@ -33,7 +33,7 @@
#include "runtime/safepoint.hpp"
// ----------------------------------------------------------------------------
#if defined(COMPILER2) || INCLUDE_JVMCI
#if COMPILER2_OR_JVMCI
#define __ _masm.
// emit call stub, compiled java to interpreter
address CompiledStaticCall::emit_to_interp_stub(CodeBuffer &cbuf, address mark) {
@ -89,7 +89,7 @@ address CompiledStaticCall::emit_to_interp_stub(CodeBuffer &cbuf, address mark)
int CompiledStaticCall::reloc_to_interp_stub() {
return 10; // 4 in emit_to_interp_stub + 1 in Java_Static_Call
}
#endif // COMPILER2 || JVMCI
#endif // COMPILER2_OR_JVMCI
// size of C2 call stub, compiled java to interpretor
int CompiledStaticCall::to_interp_stub_size() {

View File

@ -436,11 +436,11 @@ frame frame::sender_for_interpreter_frame(RegisterMap* map) const {
// This is the sp before any possible extension (adapter/locals).
intptr_t* unextended_sp = interpreter_frame_sender_sp();
#if defined(COMPILER2) || INCLUDE_JVMCI
#if COMPILER2_OR_JVMCI
if (map->update_map()) {
update_map_with_saved_link(map, (intptr_t**) addr_at(link_offset));
}
#endif // COMPILER2 || INCLUDE_JVMCI
#endif // COMPILER2_OR_JVMCI
return frame(sender_sp, unextended_sp, link(), sender_pc());
}

View File

@ -46,11 +46,11 @@ define_pd_global(uintx, CodeCacheSegmentSize, 64 TIERED_ONLY(+64)); // Tiered
// the the vep is aligned at CodeEntryAlignment whereas c2 only aligns
// the uep and the vep doesn't get real alignment but just slops on by
// only assured that the entry instruction meets the 5 byte size requirement.
#if defined(COMPILER2) || INCLUDE_JVMCI
#if COMPILER2_OR_JVMCI
define_pd_global(intx, CodeEntryAlignment, 32);
#else
define_pd_global(intx, CodeEntryAlignment, 16);
#endif // COMPILER2
#endif // COMPILER2_OR_JVMCI
define_pd_global(intx, OptoLoopAlignment, 16);
define_pd_global(intx, InlineFrequencyCount, 100);
define_pd_global(intx, InlineSmallCode, 1000);

View File

@ -151,7 +151,7 @@ OopMap* RegisterSaver::save_live_registers(MacroAssembler* masm, int additional_
if (UseAVX < 3) {
num_xmm_regs = num_xmm_regs/2;
}
#if defined(COMPILER2) || INCLUDE_JVMCI
#if COMPILER2_OR_JVMCI
if (save_vectors) {
assert(UseAVX > 0, "Vectors larger than 16 byte long are supported only with AVX");
assert(MaxVectorSize <= 64, "Only up to 64 byte long vectors are supported");
@ -260,7 +260,7 @@ OopMap* RegisterSaver::save_live_registers(MacroAssembler* masm, int additional_
}
}
#if defined(COMPILER2) || INCLUDE_JVMCI
#if COMPILER2_OR_JVMCI
if (save_vectors) {
off = ymm0_off;
int delta = ymm1_off - off;
@ -270,7 +270,7 @@ OopMap* RegisterSaver::save_live_registers(MacroAssembler* masm, int additional_
off += delta;
}
}
#endif // COMPILER2 || INCLUDE_JVMCI
#endif // COMPILER2_OR_JVMCI
// %%% These should all be a waste but we'll keep things as they were for now
if (true) {
@ -323,7 +323,7 @@ void RegisterSaver::restore_live_registers(MacroAssembler* masm, bool restore_ve
__ addptr(rsp, frame::arg_reg_save_area_bytes);
}
#if defined(COMPILER2) || INCLUDE_JVMCI
#if COMPILER2_OR_JVMCI
if (restore_vectors) {
assert(UseAVX > 0, "Vectors larger than 16 byte long are supported only with AVX");
assert(MaxVectorSize <= 64, "Only up to 64 byte long vectors are supported");

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1999, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -3433,6 +3433,8 @@ class StubGenerator: public StubCodeGenerator {
}
address generate_libmExp() {
StubCodeMark mark(this, "StubRoutines", "libmExp");
address start = __ pc();
const XMMRegister x0 = xmm0;
@ -3458,6 +3460,8 @@ class StubGenerator: public StubCodeGenerator {
}
address generate_libmLog() {
StubCodeMark mark(this, "StubRoutines", "libmLog");
address start = __ pc();
const XMMRegister x0 = xmm0;
@ -3483,6 +3487,8 @@ class StubGenerator: public StubCodeGenerator {
}
address generate_libmLog10() {
StubCodeMark mark(this, "StubRoutines", "libmLog10");
address start = __ pc();
const XMMRegister x0 = xmm0;
@ -3508,6 +3514,8 @@ class StubGenerator: public StubCodeGenerator {
}
address generate_libmPow() {
StubCodeMark mark(this, "StubRoutines", "libmPow");
address start = __ pc();
const XMMRegister x0 = xmm0;
@ -3533,6 +3541,8 @@ class StubGenerator: public StubCodeGenerator {
}
address generate_libm_reduce_pi04l() {
StubCodeMark mark(this, "StubRoutines", "libm_reduce_pi04l");
address start = __ pc();
BLOCK_COMMENT("Entry:");
@ -3543,6 +3553,8 @@ class StubGenerator: public StubCodeGenerator {
}
address generate_libm_sin_cos_huge() {
StubCodeMark mark(this, "StubRoutines", "libm_sin_cos_huge");
address start = __ pc();
const XMMRegister x0 = xmm0;
@ -3556,6 +3568,8 @@ class StubGenerator: public StubCodeGenerator {
}
address generate_libmSin() {
StubCodeMark mark(this, "StubRoutines", "libmSin");
address start = __ pc();
const XMMRegister x0 = xmm0;
@ -3579,6 +3593,8 @@ class StubGenerator: public StubCodeGenerator {
}
address generate_libmCos() {
StubCodeMark mark(this, "StubRoutines", "libmCos");
address start = __ pc();
const XMMRegister x0 = xmm0;
@ -3604,6 +3620,8 @@ class StubGenerator: public StubCodeGenerator {
}
address generate_libm_tan_cot_huge() {
StubCodeMark mark(this, "StubRoutines", "libm_tan_cot_huge");
address start = __ pc();
const XMMRegister x0 = xmm0;
@ -3617,6 +3635,8 @@ class StubGenerator: public StubCodeGenerator {
}
address generate_libmTan() {
StubCodeMark mark(this, "StubRoutines", "libmTan");
address start = __ pc();
const XMMRegister x0 = xmm0;

View File

@ -4619,6 +4619,8 @@ class StubGenerator: public StubCodeGenerator {
}
address generate_libmExp() {
StubCodeMark mark(this, "StubRoutines", "libmExp");
address start = __ pc();
const XMMRegister x0 = xmm0;
@ -4646,6 +4648,8 @@ class StubGenerator: public StubCodeGenerator {
}
address generate_libmLog() {
StubCodeMark mark(this, "StubRoutines", "libmLog");
address start = __ pc();
const XMMRegister x0 = xmm0;
@ -4674,6 +4678,8 @@ class StubGenerator: public StubCodeGenerator {
}
address generate_libmLog10() {
StubCodeMark mark(this, "StubRoutines", "libmLog10");
address start = __ pc();
const XMMRegister x0 = xmm0;
@ -4701,6 +4707,8 @@ class StubGenerator: public StubCodeGenerator {
}
address generate_libmPow() {
StubCodeMark mark(this, "StubRoutines", "libmPow");
address start = __ pc();
const XMMRegister x0 = xmm0;
@ -4731,6 +4739,8 @@ class StubGenerator: public StubCodeGenerator {
}
address generate_libmSin() {
StubCodeMark mark(this, "StubRoutines", "libmSin");
address start = __ pc();
const XMMRegister x0 = xmm0;
@ -4770,6 +4780,8 @@ class StubGenerator: public StubCodeGenerator {
}
address generate_libmCos() {
StubCodeMark mark(this, "StubRoutines", "libmCos");
address start = __ pc();
const XMMRegister x0 = xmm0;
@ -4809,6 +4821,8 @@ class StubGenerator: public StubCodeGenerator {
}
address generate_libmTan() {
StubCodeMark mark(this, "StubRoutines", "libmTan");
address start = __ pc();
const XMMRegister x0 = xmm0;

View File

@ -944,7 +944,7 @@ void VM_Version::get_processor_features() {
}
}
#endif
#if defined(COMPILER2) || INCLUDE_JVMCI
#if COMPILER2_OR_JVMCI
if (MaxVectorSize > 0) {
if (!is_power_of_2(MaxVectorSize)) {
warning("MaxVectorSize must be a power of 2");
@ -996,7 +996,7 @@ void VM_Version::get_processor_features() {
}
#endif // COMPILER2 && ASSERT
}
#endif // COMPILER2 || INCLUDE_JVMCI
#endif // COMPILER2_OR_JVMCI
#ifdef COMPILER2
#ifdef _LP64

View File

@ -73,7 +73,7 @@ bool JavaThread::pd_get_top_frame(frame* fr_addr, void* ucontext, bool isInJava)
frame ret_frame(ret_sp, ret_fp, addr.pc());
if (!ret_frame.safe_for_sender(jt)) {
#if defined(COMPILER2) || INCLUDE_JVMCI
#if COMPILER2_OR_JVMCI
// C2 and JVMCI use ebp as a general register see if NULL fp helps
frame ret_frame2(ret_sp, NULL, addr.pc());
if (!ret_frame2.safe_for_sender(jt)) {
@ -84,7 +84,7 @@ bool JavaThread::pd_get_top_frame(frame* fr_addr, void* ucontext, bool isInJava)
#else
// nothing else to try if the frame isn't good
return false;
#endif /* COMPILER2 || INCLUDE_JVMCI */
#endif // COMPILER2_OR_JVMCI
}
*fr_addr = ret_frame;
return true;

View File

@ -74,7 +74,7 @@ bool JavaThread::pd_get_top_frame(frame* fr_addr, void* ucontext, bool isInJava)
frame ret_frame(ret_sp, ret_fp, addr.pc());
if (!ret_frame.safe_for_sender(jt)) {
#if defined(COMPILER2) || INCLUDE_JVMCI
#if COMPILER2_OR_JVMCI
// C2 and JVMCI use ebp as a general register see if NULL fp helps
frame ret_frame2(ret_sp, NULL, addr.pc());
if (!ret_frame2.safe_for_sender(jt)) {
@ -85,7 +85,7 @@ bool JavaThread::pd_get_top_frame(frame* fr_addr, void* ucontext, bool isInJava)
#else
// nothing else to try if the frame isn't good
return false;
#endif /* COMPILER2 || INCLUDE_JVMCI */
#endif // COMPILER2_OR_JVMCI
}
*fr_addr = ret_frame;
return true;

View File

@ -81,7 +81,7 @@ bool JavaThread::pd_get_top_frame(frame* fr_addr, void* ucontext, bool isInJava)
frame ret_frame(ret_sp, ret_fp, addr.pc());
if (!ret_frame.safe_for_sender(jt)) {
#if defined(COMPILER2) || INCLUDE_JVMCI
#if COMPILER2_OR_JVMCI
// C2 and JVMCI use ebp as a general register see if NULL fp helps
frame ret_frame2(ret_sp, NULL, addr.pc());
if (!ret_frame2.safe_for_sender(jt)) {
@ -92,7 +92,7 @@ bool JavaThread::pd_get_top_frame(frame* fr_addr, void* ucontext, bool isInJava)
#else
// nothing else to try if the frame isn't good
return false;
#endif /* COMPILER2 || INCLUDE_JVMCI */
#endif // COMPILER2_OR_JVMCI
}
*fr_addr = ret_frame;
return true;

View File

@ -490,6 +490,8 @@ void AOTCodeHeap::link_stub_routines_symbols() {
SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_stub_routines_checkcast_arraycopy", address, StubRoutines::_checkcast_arraycopy);
SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_stub_routines_generic_arraycopy", address, StubRoutines::_generic_arraycopy);
SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_stub_routines_aescrypt_encryptBlock", address, StubRoutines::_aescrypt_encryptBlock);
SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_stub_routines_aescrypt_decryptBlock", address, StubRoutines::_aescrypt_decryptBlock);
SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_stub_routines_cipherBlockChaining_encryptAESCrypt", address, StubRoutines::_cipherBlockChaining_encryptAESCrypt);

View File

@ -228,7 +228,7 @@ void ScopeDesc::print_on(outputStream* st, PcDesc* pd) const {
}
}
#if defined(COMPILER2) || INCLUDE_JVMCI
#if COMPILER2_OR_JVMCI
if (NOT_JVMCI(DoEscapeAnalysis &&) is_top() && _objects != NULL) {
st->print_cr(" Objects");
for (int i = 0; i < _objects->length(); i++) {
@ -239,7 +239,7 @@ void ScopeDesc::print_on(outputStream* st, PcDesc* pd) const {
st->cr();
}
}
#endif // COMPILER2 || INCLUDE_JVMCI
#endif // COMPILER2_OR_JVMCI
}
#endif

View File

@ -268,9 +268,9 @@ static void add_derived_oop(oop* base, oop* derived) {
#if !defined(TIERED) && !defined(INCLUDE_JVMCI)
COMPILER1_PRESENT(ShouldNotReachHere();)
#endif // !defined(TIERED) && !defined(INCLUDE_JVMCI)
#if defined(COMPILER2) || INCLUDE_JVMCI
#if COMPILER2_OR_JVMCI
DerivedPointerTable::add(derived, base);
#endif // COMPILER2 || INCLUDE_JVMCI
#endif // COMPILER2_OR_JVMCI
}
@ -461,12 +461,12 @@ bool ImmutableOopMap::has_derived_pointer() const {
#if !defined(TIERED) && !defined(INCLUDE_JVMCI)
COMPILER1_PRESENT(return false);
#endif // !TIERED
#if defined(COMPILER2) || INCLUDE_JVMCI
#if COMPILER2_OR_JVMCI
OopMapStream oms(this,OopMapValue::derived_oop_value);
return oms.is_done();
#else
return false;
#endif // COMPILER2 || INCLUDE_JVMCI
#endif // COMPILER2_OR_JVMCI
}
#endif //PRODUCT
@ -726,7 +726,7 @@ ImmutableOopMapSet* ImmutableOopMapSet::build_from(const OopMapSet* oopmap_set)
//------------------------------DerivedPointerTable---------------------------
#if defined(COMPILER2) || INCLUDE_JVMCI
#if COMPILER2_OR_JVMCI
class DerivedPointerEntry : public CHeapObj<mtCompiler> {
private:
@ -819,4 +819,4 @@ void DerivedPointerTable::update_pointers() {
_active = false;
}
#endif // COMPILER2 || INCLUDE_JVMCI
#endif // COMPILER2_OR_JVMCI

View File

@ -427,7 +427,7 @@ private:
// oops, it is filled in with references to all locations that contains a
// derived oop (assumed to be very few). When the GC is complete, the derived
// pointers are updated based on their base pointers new value and an offset.
#if defined(COMPILER2) || INCLUDE_JVMCI
#if COMPILER2_OR_JVMCI
class DerivedPointerTable : public AllStatic {
friend class VMStructs;
private:
@ -463,6 +463,6 @@ class DerivedPointerTableDeactivate: public StackObj {
}
}
};
#endif // COMPILER2 || INCLUDE_JVMCI
#endif // COMPILER2_OR_JVMCI
#endif // SHARE_VM_COMPILER_OOPMAP_HPP

View File

@ -2296,7 +2296,7 @@ bool CMSCollector::verify_after_remark() {
// way with the marking information used by GC.
NoRefDiscovery no_discovery(ref_processor());
#if defined(COMPILER2) || INCLUDE_JVMCI
#if COMPILER2_OR_JVMCI
DerivedPointerTableDeactivate dpt_deact;
#endif
@ -2869,7 +2869,7 @@ void CMSCollector::checkpointRootsInitialWork() {
print_eden_and_survivor_chunk_arrays();
{
#if defined(COMPILER2) || INCLUDE_JVMCI
#if COMPILER2_OR_JVMCI
DerivedPointerTableDeactivate dpt_deact;
#endif
if (CMSParallelInitialMarkEnabled) {
@ -4171,7 +4171,7 @@ void CMSCollector::checkpointRootsFinalWork() {
print_eden_and_survivor_chunk_arrays();
{
#if defined(COMPILER2) || INCLUDE_JVMCI
#if COMPILER2_OR_JVMCI
DerivedPointerTableDeactivate dpt_deact;
#endif

View File

@ -2597,7 +2597,7 @@ void G1CollectedHeap::gc_epilogue(bool full) {
// FIXME: what is this about?
// I'm ignoring the "fill_newgen()" call if "alloc_event_enabled"
// is set.
#if defined(COMPILER2) || INCLUDE_JVMCI
#if COMPILER2_OR_JVMCI
assert(DerivedPointerTable::is_empty(), "derived pointer present");
#endif
// always_do_update_barrier = true;
@ -3010,7 +3010,7 @@ G1CollectedHeap::do_collection_pause_at_safepoint(double target_pause_time_ms) {
_verifier->check_bitmaps("GC Start");
#if defined(COMPILER2) || INCLUDE_JVMCI
#if COMPILER2_OR_JVMCI
DerivedPointerTable::clear();
#endif
@ -4439,7 +4439,7 @@ void G1CollectedHeap::post_evacuate_collection_set(EvacuationInfo& evacuation_in
purge_code_root_memory();
redirty_logged_cards();
#if defined(COMPILER2) || INCLUDE_JVMCI
#if COMPILER2_OR_JVMCI
double start = os::elapsedTime();
DerivedPointerTable::update_pointers();
g1_policy()->phase_times()->record_derived_pointer_table_update_time((os::elapsedTime() - start) * 1000.0);

View File

@ -414,7 +414,7 @@ double G1GCPhaseTimes::print_post_evacuate_collection_set() const {
debug_time("Redirty Cards", _recorded_redirty_logged_cards_time_ms);
trace_phase(_gc_par_phases[RedirtyCards]);
#if defined(COMPILER2) || INCLUDE_JVMCI
#if COMPILER2_OR_JVMCI
debug_time("DerivedPointerTable Update", _cur_derived_pointer_table_update_time_ms);
#endif

View File

@ -62,7 +62,7 @@ void G1MarkSweep::invoke_at_safepoint(ReferenceProcessor* rp,
assert(SafepointSynchronize::is_at_safepoint(), "must be at a safepoint");
HandleMark hm; // Discard invalid handles created during gc
#if defined(COMPILER2) || INCLUDE_JVMCI
#if COMPILER2_OR_JVMCI
DerivedPointerTable::clear();
#endif
#ifdef ASSERT
@ -96,7 +96,7 @@ void G1MarkSweep::invoke_at_safepoint(ReferenceProcessor* rp,
// Prepare compaction.
mark_sweep_phase2();
#if defined(COMPILER2) || INCLUDE_JVMCI
#if COMPILER2_OR_JVMCI
// Don't add any more derived pointers during phase3
DerivedPointerTable::set_active(false);
#endif
@ -111,7 +111,7 @@ void G1MarkSweep::invoke_at_safepoint(ReferenceProcessor* rp,
BiasedLocking::restore_marks();
GenMarkSweep::deallocate_stacks();
#if defined(COMPILER2) || INCLUDE_JVMCI
#if COMPILER2_OR_JVMCI
// Now update the derived pointers.
DerivedPointerTable::update_pointers();
#endif
@ -204,7 +204,7 @@ void G1MarkSweep::mark_sweep_phase1(bool& marked_for_unloading,
if (VerifyDuringGC) {
HandleMark hm; // handle scope
#if defined(COMPILER2) || INCLUDE_JVMCI
#if COMPILER2_OR_JVMCI
DerivedPointerTableDeactivate dpt_deact;
#endif
g1h->prepare_for_verify();

View File

@ -192,7 +192,7 @@ bool PSMarkSweep::invoke_no_policy(bool clear_all_softrefs) {
allocate_stacks();
#if defined(COMPILER2) || INCLUDE_JVMCI
#if COMPILER2_OR_JVMCI
DerivedPointerTable::clear();
#endif
@ -203,7 +203,7 @@ bool PSMarkSweep::invoke_no_policy(bool clear_all_softrefs) {
mark_sweep_phase2();
#if defined(COMPILER2) || INCLUDE_JVMCI
#if COMPILER2_OR_JVMCI
// Don't add any more derived pointers during phase3
assert(DerivedPointerTable::is_active(), "Sanity");
DerivedPointerTable::set_active(false);
@ -252,7 +252,7 @@ bool PSMarkSweep::invoke_no_policy(bool clear_all_softrefs) {
CodeCache::gc_epilogue();
JvmtiExport::gc_epilogue();
#if defined(COMPILER2) || INCLUDE_JVMCI
#if COMPILER2_OR_JVMCI
DerivedPointerTable::update_pointers();
#endif

View File

@ -1032,7 +1032,7 @@ void PSParallelCompact::post_compact()
CodeCache::gc_epilogue();
JvmtiExport::gc_epilogue();
#if defined(COMPILER2) || INCLUDE_JVMCI
#if COMPILER2_OR_JVMCI
DerivedPointerTable::update_pointers();
#endif
@ -1783,7 +1783,7 @@ bool PSParallelCompact::invoke_no_policy(bool maximum_heap_compaction) {
CodeCache::gc_prologue();
#if defined(COMPILER2) || INCLUDE_JVMCI
#if COMPILER2_OR_JVMCI
DerivedPointerTable::clear();
#endif
@ -1799,7 +1799,7 @@ bool PSParallelCompact::invoke_no_policy(bool maximum_heap_compaction) {
&& GCCause::is_user_requested_gc(gc_cause);
summary_phase(vmthread_cm, maximum_heap_compaction || max_on_system_gc);
#if defined(COMPILER2) || INCLUDE_JVMCI
#if COMPILER2_OR_JVMCI
assert(DerivedPointerTable::is_active(), "Sanity");
DerivedPointerTable::set_active(false);
#endif

View File

@ -331,7 +331,7 @@ bool PSScavenge::invoke_no_policy() {
save_to_space_top_before_gc();
#if defined(COMPILER2) || INCLUDE_JVMCI
#if COMPILER2_OR_JVMCI
DerivedPointerTable::clear();
#endif
@ -601,7 +601,7 @@ bool PSScavenge::invoke_no_policy() {
assert(young_gen->to_space()->is_empty(), "to space should be empty now");
}
#if defined(COMPILER2) || INCLUDE_JVMCI
#if COMPILER2_OR_JVMCI
DerivedPointerTable::update_pointers();
#endif

View File

@ -92,7 +92,7 @@ void GenMarkSweep::invoke_at_safepoint(ReferenceProcessor* rp, bool clear_all_so
mark_sweep_phase2();
// Don't add any more derived pointers during phase3
#if defined(COMPILER2) || INCLUDE_JVMCI
#if COMPILER2_OR_JVMCI
assert(DerivedPointerTable::is_active(), "Sanity");
DerivedPointerTable::set_active(false);
#endif

View File

@ -241,7 +241,7 @@ void CollectedHeap::set_barrier_set(BarrierSet* barrier_set) {
void CollectedHeap::pre_initialize() {
// Used for ReduceInitialCardMarks (when COMPILER2 is used);
// otherwise remains unused.
#if defined(COMPILER2) || INCLUDE_JVMCI
#if COMPILER2_OR_JVMCI
_defer_initial_card_mark = is_server_compilation_mode_vm() && ReduceInitialCardMarks && can_elide_tlab_store_barriers()
&& (DeferInitialCardMark || card_mark_must_follow_store());
#else
@ -545,7 +545,7 @@ void CollectedHeap::ensure_parsability(bool retire_tlabs) {
" to threads list is doomed to failure!");
for (JavaThread *thread = Threads::first(); thread; thread = thread->next()) {
if (use_tlab) thread->tlab().make_parsable(retire_tlabs);
#if defined(COMPILER2) || INCLUDE_JVMCI
#if COMPILER2_OR_JVMCI
// The deferred store barriers must all have been flushed to the
// card-table (or other remembered set structure) before GC starts
// processing the card-table (or other remembered set).

View File

@ -1067,11 +1067,11 @@ class GenGCEpilogueClosure: public GenCollectedHeap::GenClosure {
};
void GenCollectedHeap::gc_epilogue(bool full) {
#if defined(COMPILER2) || INCLUDE_JVMCI
#if COMPILER2_OR_JVMCI
assert(DerivedPointerTable::is_empty(), "derived pointer present");
size_t actual_gap = pointer_delta((HeapWord*) (max_uintx-3), *(end_addr()));
guarantee(is_client_compilation_mode_vm() || actual_gap > (size_t)FastAllocateSizeLimit, "inline allocation wraps");
#endif /* COMPILER2 || INCLUDE_JVMCI */
#endif // COMPILER2_OR_JVMCI
resize_all_tlabs();

View File

@ -921,6 +921,14 @@ nmethod* InterpreterRuntime::frequency_counter_overflow(JavaThread* thread, addr
int bci = method->bci_from(last_frame.bcp());
nm = method->lookup_osr_nmethod_for(bci, CompLevel_none, false);
}
if (nm != NULL && thread->is_interp_only_mode()) {
// Normally we never get an nm if is_interp_only_mode() is true, because
// policy()->event has a check for this and won't compile the method when
// true. However, it's possible for is_interp_only_mode() to become true
// during the compilation. We don't want to return the nm in that case
// because we want to continue to execute interpreted.
nm = NULL;
}
#ifndef PRODUCT
if (TraceOnStackReplacement) {
if (nm != NULL) {

View File

@ -55,10 +55,13 @@ private:
public:
JVMCICompiler();
static JVMCICompiler* instance(TRAPS) {
static JVMCICompiler* instance(bool require_non_null, TRAPS) {
if (!EnableJVMCI) {
THROW_MSG_NULL(vmSymbols::java_lang_InternalError(), "JVMCI is not enabled")
}
if (_instance == NULL && require_non_null) {
THROW_MSG_NULL(vmSymbols::java_lang_InternalError(), "The JVMCI compiler instance has not been created");
}
return _instance;
}

View File

@ -1018,7 +1018,7 @@ C2V_VMENTRY(jint, installCode, (JNIEnv *jniEnv, jobject, jobject target, jobject
Handle installed_code_handle(THREAD, JNIHandles::resolve(installed_code));
Handle speculation_log_handle(THREAD, JNIHandles::resolve(speculation_log));
JVMCICompiler* compiler = JVMCICompiler::instance(CHECK_JNI_ERR);
JVMCICompiler* compiler = JVMCICompiler::instance(true, CHECK_JNI_ERR);
TraceTime install_time("installCode", JVMCICompiler::codeInstallTimer());
bool is_immutable_PIC = HotSpotCompiledCode::isImmutablePIC(compiled_code_handle) > 0;
@ -1136,7 +1136,7 @@ C2V_VMENTRY(jint, getMetadata, (JNIEnv *jniEnv, jobject, jobject target, jobject
C2V_END
C2V_VMENTRY(void, resetCompilationStatistics, (JNIEnv *jniEnv, jobject))
JVMCICompiler* compiler = JVMCICompiler::instance(CHECK);
JVMCICompiler* compiler = JVMCICompiler::instance(true, CHECK);
CompilerStatistics* stats = compiler->stats();
stats->_standard.reset();
stats->_osr.reset();

View File

@ -821,7 +821,7 @@ void JVMCIRuntime::shutdown(TRAPS) {
}
CompLevel JVMCIRuntime::adjust_comp_level_inner(const methodHandle& method, bool is_osr, CompLevel level, JavaThread* thread) {
JVMCICompiler* compiler = JVMCICompiler::instance(thread);
JVMCICompiler* compiler = JVMCICompiler::instance(false, thread);
if (compiler != NULL && compiler->is_bootstrapping()) {
return level;
}

View File

@ -55,8 +55,8 @@ Metachunk::Metachunk(size_t word_size,
_container(container)
{
_top = initial_top();
#ifdef ASSERT
set_is_tagged_free(false);
#ifdef ASSERT
mangle(uninitMetaWordVal);
#endif
}

View File

@ -102,7 +102,7 @@ class Metachunk : public Metabase<Metachunk> {
// Current allocation top.
MetaWord* _top;
DEBUG_ONLY(bool _is_tagged_free;)
bool _is_tagged_free;
MetaWord* initial_top() const { return (MetaWord*)this + overhead(); }
MetaWord* top() const { return _top; }
@ -138,10 +138,8 @@ class Metachunk : public Metabase<Metachunk> {
size_t used_word_size() const;
size_t free_word_size() const;
#ifdef ASSERT
bool is_tagged_free() { return _is_tagged_free; }
void set_is_tagged_free(bool v) { _is_tagged_free = v; }
#endif
bool contains(const void* ptr) { return bottom() <= ptr && ptr < _top; }

View File

@ -108,6 +108,18 @@ static ChunkIndex next_chunk_index(ChunkIndex i) {
return (ChunkIndex) (i+1);
}
static const char* scale_unit(size_t scale) {
switch(scale) {
case 1: return "BYTES";
case K: return "KB";
case M: return "MB";
case G: return "GB";
default:
ShouldNotReachHere();
return NULL;
}
}
volatile intptr_t MetaspaceGC::_capacity_until_GC = 0;
uint MetaspaceGC::_shrink_factor = 0;
bool MetaspaceGC::_should_concurrent_collect = false;
@ -176,7 +188,7 @@ class ChunkManager : public CHeapObj<mtInternal> {
void locked_get_statistics(ChunkManagerStatistics* stat) const;
void get_statistics(ChunkManagerStatistics* stat) const;
static void print_statistics(const ChunkManagerStatistics* stat, outputStream* out);
static void print_statistics(const ChunkManagerStatistics* stat, outputStream* out, size_t scale);
public:
@ -283,7 +295,7 @@ class ChunkManager : public CHeapObj<mtInternal> {
// Prints composition for both non-class and (if available)
// class chunk manager.
static void print_all_chunkmanagers(outputStream* out);
static void print_all_chunkmanagers(outputStream* out, size_t scale = 1);
};
class SmallBlocks : public CHeapObj<mtClass> {
@ -480,6 +492,7 @@ class VirtualSpaceNode : public CHeapObj<mtClass> {
#endif
void print_on(outputStream* st) const;
void print_map(outputStream* st, bool is_class) const;
};
#define assert_is_aligned(value, alignment) \
@ -531,6 +544,94 @@ void VirtualSpaceNode::purge(ChunkManager* chunk_manager) {
}
}
void VirtualSpaceNode::print_map(outputStream* st, bool is_class) const {
// Format:
// <ptr>
// <ptr> . .. . . ..
// SSxSSMMMMMMMMMMMMMMMMsssXX
// 112114444444444444444
// <ptr> . .. . . ..
// SSxSSMMMMMMMMMMMMMMMMsssXX
// 112114444444444444444
if (bottom() == top()) {
return;
}
// First line: dividers for every med-chunk-sized interval
// Second line: a dot for the start of a chunk
// Third line: a letter per chunk type (x,s,m,h), uppercase if in use.
const size_t spec_chunk_size = is_class ? ClassSpecializedChunk : SpecializedChunk;
const size_t small_chunk_size = is_class ? ClassSmallChunk : SmallChunk;
const size_t med_chunk_size = is_class ? ClassMediumChunk : MediumChunk;
int line_len = 100;
const size_t section_len = align_up(spec_chunk_size * line_len, med_chunk_size);
line_len = (int)(section_len / spec_chunk_size);
char* line1 = (char*)os::malloc(line_len, mtInternal);
char* line2 = (char*)os::malloc(line_len, mtInternal);
char* line3 = (char*)os::malloc(line_len, mtInternal);
int pos = 0;
const MetaWord* p = bottom();
const Metachunk* chunk = (const Metachunk*)p;
const MetaWord* chunk_end = p + chunk->word_size();
while (p < top()) {
if (pos == line_len) {
pos = 0;
st->fill_to(22);
st->print_raw(line1, line_len);
st->cr();
st->fill_to(22);
st->print_raw(line2, line_len);
st->cr();
}
if (pos == 0) {
st->print(PTR_FORMAT ":", p2i(p));
}
if (p == chunk_end) {
chunk = (Metachunk*)p;
chunk_end = p + chunk->word_size();
}
if (p == (const MetaWord*)chunk) {
// chunk starts.
line1[pos] = '.';
} else {
line1[pos] = ' ';
}
// Line 2: chunk type (x=spec, s=small, m=medium, h=humongous), uppercase if
// chunk is in use.
const bool chunk_is_free = ((Metachunk*)chunk)->is_tagged_free();
if (chunk->word_size() == spec_chunk_size) {
line2[pos] = chunk_is_free ? 'x' : 'X';
} else if (chunk->word_size() == small_chunk_size) {
line2[pos] = chunk_is_free ? 's' : 'S';
} else if (chunk->word_size() == med_chunk_size) {
line2[pos] = chunk_is_free ? 'm' : 'M';
} else if (chunk->word_size() > med_chunk_size) {
line2[pos] = chunk_is_free ? 'h' : 'H';
} else {
ShouldNotReachHere();
}
p += spec_chunk_size;
pos ++;
}
if (pos > 0) {
st->fill_to(22);
st->print_raw(line1, pos);
st->cr();
st->fill_to(22);
st->print_raw(line2, pos);
st->cr();
}
os::free(line1);
os::free(line2);
os::free(line3);
}
#ifdef ASSERT
uintx VirtualSpaceNode::container_count_slow() {
uintx count = 0;
@ -637,6 +738,7 @@ class VirtualSpaceList : public CHeapObj<mtClass> {
void purge(ChunkManager* chunk_manager);
void print_on(outputStream* st) const;
void print_map(outputStream* st) const;
class VirtualSpaceListIterator : public StackObj {
VirtualSpaceNode* _virtual_spaces;
@ -1449,6 +1551,18 @@ void VirtualSpaceList::print_on(outputStream* st) const {
}
}
void VirtualSpaceList::print_map(outputStream* st) const {
VirtualSpaceNode* list = virtual_space_list();
VirtualSpaceListIterator iter(list);
unsigned i = 0;
while (iter.repeat()) {
st->print_cr("Node %u:", i);
VirtualSpaceNode* node = iter.get_next();
node->print_map(st, this->is_class());
i ++;
}
}
// MetaspaceGC methods
// VM_CollectForMetadataAllocation is the vm operation used to GC.
@ -1724,7 +1838,6 @@ bool Metadebug::test_metadata_failure() {
#endif
// ChunkManager methods
size_t ChunkManager::free_chunks_total_words() {
return _free_chunks_total;
}
@ -1923,11 +2036,10 @@ Metachunk* ChunkManager::free_chunks_get(size_t word_size) {
// Remove it from the links to this freelist
chunk->set_next(NULL);
chunk->set_prev(NULL);
#ifdef ASSERT
// Chunk is no longer on any freelist. Setting to false make container_count_slow()
// work.
chunk->set_is_tagged_free(false);
#endif
chunk->container()->inc_container_count();
slow_locked_verify();
@ -1995,7 +2107,7 @@ void ChunkManager::return_single_chunk(ChunkIndex index, Metachunk* chunk) {
chunk_size_name(index), p2i(chunk), chunk->word_size());
}
chunk->container()->dec_container_count();
DEBUG_ONLY(chunk->set_is_tagged_free(true);)
chunk->set_is_tagged_free(true);
// Chunk has been added; update counters.
account_for_added_chunk(chunk);
@ -2057,22 +2169,45 @@ void ChunkManager::get_statistics(ChunkManagerStatistics* stat) const {
locked_get_statistics(stat);
}
void ChunkManager::print_statistics(const ChunkManagerStatistics* stat, outputStream* out) {
void ChunkManager::print_statistics(const ChunkManagerStatistics* stat, outputStream* out, size_t scale) {
size_t total = 0;
assert(scale == 1 || scale == K || scale == M || scale == G, "Invalid scale");
const char* unit = scale_unit(scale);
for (ChunkIndex i = ZeroIndex; i < NumberOfFreeLists; i = next_chunk_index(i)) {
out->print_cr(" " SIZE_FORMAT " %s (" SIZE_FORMAT " bytes) chunks, total " SIZE_FORMAT " bytes",
stat->num_by_type[i], chunk_size_name(i),
stat->single_size_by_type[i],
stat->total_size_by_type[i]);
out->print(" " SIZE_FORMAT " %s (" SIZE_FORMAT " bytes) chunks, total ",
stat->num_by_type[i], chunk_size_name(i),
stat->single_size_by_type[i]);
if (scale == 1) {
out->print_cr(SIZE_FORMAT " bytes", stat->total_size_by_type[i]);
} else {
out->print_cr("%.2f%s", (float)stat->total_size_by_type[i] / scale, unit);
}
total += stat->total_size_by_type[i];
}
out->print_cr(" " SIZE_FORMAT " humongous chunks, total " SIZE_FORMAT " bytes",
stat->num_humongous_chunks, stat->total_size_humongous_chunks);
total += stat->total_size_humongous_chunks;
out->print_cr(" total size: " SIZE_FORMAT ".", total);
if (scale == 1) {
out->print_cr(" " SIZE_FORMAT " humongous chunks, total " SIZE_FORMAT " bytes",
stat->num_humongous_chunks, stat->total_size_humongous_chunks);
out->print_cr(" total size: " SIZE_FORMAT " bytes.", total);
} else {
out->print_cr(" " SIZE_FORMAT " humongous chunks, total %.2f%s",
stat->num_humongous_chunks,
(float)stat->total_size_humongous_chunks / scale, unit);
out->print_cr(" total size: %.2f%s.", (float)total / scale, unit);
}
}
void ChunkManager::print_all_chunkmanagers(outputStream* out) {
void ChunkManager::print_all_chunkmanagers(outputStream* out, size_t scale) {
assert(scale == 1 || scale == K || scale == M || scale == G, "Invalid scale");
// Note: keep lock protection only to retrieving statistics; keep printing
// out of lock protection
ChunkManagerStatistics stat;
@ -2080,7 +2215,7 @@ void ChunkManager::print_all_chunkmanagers(outputStream* out) {
const ChunkManager* const non_class_cm = Metaspace::chunk_manager_metadata();
if (non_class_cm != NULL) {
non_class_cm->get_statistics(&stat);
ChunkManager::print_statistics(&stat, out);
ChunkManager::print_statistics(&stat, out, scale);
} else {
out->print_cr("unavailable.");
}
@ -2088,7 +2223,7 @@ void ChunkManager::print_all_chunkmanagers(outputStream* out) {
const ChunkManager* const class_cm = Metaspace::chunk_manager_class();
if (class_cm != NULL) {
class_cm->get_statistics(&stat);
ChunkManager::print_statistics(&stat, out);
ChunkManager::print_statistics(&stat, out, scale);
} else {
out->print_cr("unavailable.");
}
@ -2911,9 +3046,9 @@ void MetaspaceAux::print_on(outputStream* out, Metaspace::MetadataType mdtype) {
size_t free_bytes = free_bytes_slow(mdtype);
size_t used_and_free = used_bytes + free_bytes +
free_chunks_capacity_bytes;
out->print_cr(" Chunk accounting: used in chunks " SIZE_FORMAT
out->print_cr(" Chunk accounting: (used in chunks " SIZE_FORMAT
"K + unused in chunks " SIZE_FORMAT "K + "
" capacity in free chunks " SIZE_FORMAT "K = " SIZE_FORMAT
" capacity in free chunks " SIZE_FORMAT "K) = " SIZE_FORMAT
"K capacity in allocated chunks " SIZE_FORMAT "K",
used_bytes / K,
free_bytes / K,
@ -2981,6 +3116,194 @@ void MetaspaceAux::print_waste(outputStream* out) {
}
}
class MetadataStats VALUE_OBJ_CLASS_SPEC {
private:
size_t _capacity;
size_t _used;
size_t _free;
size_t _waste;
public:
MetadataStats() : _capacity(0), _used(0), _free(0), _waste(0) { }
MetadataStats(size_t capacity, size_t used, size_t free, size_t waste)
: _capacity(capacity), _used(used), _free(free), _waste(waste) { }
void add(const MetadataStats& stats) {
_capacity += stats.capacity();
_used += stats.used();
_free += stats.free();
_waste += stats.waste();
}
size_t capacity() const { return _capacity; }
size_t used() const { return _used; }
size_t free() const { return _free; }
size_t waste() const { return _waste; }
void print_on(outputStream* out, size_t scale) const;
};
void MetadataStats::print_on(outputStream* out, size_t scale) const {
const char* unit = scale_unit(scale);
out->print_cr("capacity=%10.2f%s used=%10.2f%s free=%10.2f%s waste=%10.2f%s",
(float)capacity() / scale, unit,
(float)used() / scale, unit,
(float)free() / scale, unit,
(float)waste() / scale, unit);
}
class PrintCLDMetaspaceInfoClosure : public CLDClosure {
private:
outputStream* _out;
size_t _scale;
size_t _total_count;
MetadataStats _total_metadata;
MetadataStats _total_class;
size_t _total_anon_count;
MetadataStats _total_anon_metadata;
MetadataStats _total_anon_class;
public:
PrintCLDMetaspaceInfoClosure(outputStream* out, size_t scale = K)
: _out(out), _scale(scale), _total_count(0), _total_anon_count(0) { }
~PrintCLDMetaspaceInfoClosure() {
print_summary();
}
void do_cld(ClassLoaderData* cld) {
assert(SafepointSynchronize::is_at_safepoint(), "Must be at a safepoint");
if (cld->is_unloading()) return;
Metaspace* msp = cld->metaspace_or_null();
if (msp == NULL) {
return;
}
bool anonymous = false;
if (cld->is_anonymous()) {
_out->print_cr("ClassLoader: for anonymous class");
anonymous = true;
} else {
ResourceMark rm;
_out->print_cr("ClassLoader: %s", cld->loader_name());
}
print_metaspace(msp, anonymous);
_out->cr();
}
private:
void print_metaspace(Metaspace* msp, bool anonymous);
void print_summary() const;
};
void PrintCLDMetaspaceInfoClosure::print_metaspace(Metaspace* msp, bool anonymous){
assert(msp != NULL, "Sanity");
SpaceManager* vsm = msp->vsm();
const char* unit = scale_unit(_scale);
size_t capacity = vsm->sum_capacity_in_chunks_in_use() * BytesPerWord;
size_t used = vsm->sum_used_in_chunks_in_use() * BytesPerWord;
size_t free = vsm->sum_free_in_chunks_in_use() * BytesPerWord;
size_t waste = vsm->sum_waste_in_chunks_in_use() * BytesPerWord;
_total_count ++;
MetadataStats metadata_stats(capacity, used, free, waste);
_total_metadata.add(metadata_stats);
if (anonymous) {
_total_anon_count ++;
_total_anon_metadata.add(metadata_stats);
}
_out->print(" Metadata ");
metadata_stats.print_on(_out, _scale);
if (Metaspace::using_class_space()) {
vsm = msp->class_vsm();
capacity = vsm->sum_capacity_in_chunks_in_use() * BytesPerWord;
used = vsm->sum_used_in_chunks_in_use() * BytesPerWord;
free = vsm->sum_free_in_chunks_in_use() * BytesPerWord;
waste = vsm->sum_waste_in_chunks_in_use() * BytesPerWord;
MetadataStats class_stats(capacity, used, free, waste);
_total_class.add(class_stats);
if (anonymous) {
_total_anon_class.add(class_stats);
}
_out->print(" Class data ");
class_stats.print_on(_out, _scale);
}
}
void PrintCLDMetaspaceInfoClosure::print_summary() const {
const char* unit = scale_unit(_scale);
_out->cr();
_out->print_cr("Summary:");
MetadataStats total;
total.add(_total_metadata);
total.add(_total_class);
_out->print(" Total class loaders=" SIZE_FORMAT_W(6) " ", _total_count);
total.print_on(_out, _scale);
_out->print(" Metadata ");
_total_metadata.print_on(_out, _scale);
if (Metaspace::using_class_space()) {
_out->print(" Class data ");
_total_class.print_on(_out, _scale);
}
_out->cr();
MetadataStats total_anon;
total_anon.add(_total_anon_metadata);
total_anon.add(_total_anon_class);
_out->print("For anonymous classes=" SIZE_FORMAT_W(6) " ", _total_anon_count);
total_anon.print_on(_out, _scale);
_out->print(" Metadata ");
_total_anon_metadata.print_on(_out, _scale);
if (Metaspace::using_class_space()) {
_out->print(" Class data ");
_total_anon_class.print_on(_out, _scale);
}
}
void MetaspaceAux::print_metadata_for_nmt(outputStream* out, size_t scale) {
const char* unit = scale_unit(scale);
out->print_cr("Metaspaces:");
out->print_cr(" Metadata space: reserved=" SIZE_FORMAT_W(10) "%s committed=" SIZE_FORMAT_W(10) "%s",
reserved_bytes(Metaspace::NonClassType) / scale, unit,
committed_bytes(Metaspace::NonClassType) / scale, unit);
if (Metaspace::using_class_space()) {
out->print_cr(" Class space: reserved=" SIZE_FORMAT_W(10) "%s committed=" SIZE_FORMAT_W(10) "%s",
reserved_bytes(Metaspace::ClassType) / scale, unit,
committed_bytes(Metaspace::ClassType) / scale, unit);
}
out->cr();
ChunkManager::print_all_chunkmanagers(out, scale);
out->cr();
out->print_cr("Per-classloader metadata:");
out->cr();
PrintCLDMetaspaceInfoClosure cl(out, scale);
ClassLoaderDataGraph::cld_do(&cl);
}
// Dump global metaspace things from the end of ClassLoaderDataGraph
void MetaspaceAux::dump(outputStream* out) {
out->print_cr("All Metaspace:");
@ -2989,6 +3312,31 @@ void MetaspaceAux::dump(outputStream* out) {
print_waste(out);
}
// Prints an ASCII representation of the given space.
void MetaspaceAux::print_metaspace_map(outputStream* out, Metaspace::MetadataType mdtype) {
MutexLockerEx cl(SpaceManager::expand_lock(), Mutex::_no_safepoint_check_flag);
const bool for_class = mdtype == Metaspace::ClassType ? true : false;
VirtualSpaceList* const vsl = for_class ? Metaspace::class_space_list() : Metaspace::space_list();
if (vsl != NULL) {
if (for_class) {
if (!Metaspace::using_class_space()) {
out->print_cr("No Class Space.");
return;
}
out->print_raw("---- Metaspace Map (Class Space) ----");
} else {
out->print_raw("---- Metaspace Map (Non-Class Space) ----");
}
// Print legend:
out->cr();
out->print_cr("Chunk Types (uppercase chunks are in use): x-specialized, s-small, m-medium, h-humongous.");
out->cr();
VirtualSpaceList* const vsl = for_class ? Metaspace::class_space_list() : Metaspace::space_list();
vsl->print_map(out);
out->cr();
}
}
void MetaspaceAux::verify_free_chunks() {
Metaspace::chunk_manager_metadata()->verify();
if (Metaspace::using_class_space()) {
@ -3627,6 +3975,7 @@ void Metaspace::report_metadata_oome(ClassLoaderData* loader_data, size_t word_s
}
LogStream ls(log.info());
MetaspaceAux::dump(&ls);
MetaspaceAux::print_metaspace_map(&ls, mdtype);
ChunkManager::print_all_chunkmanagers(&ls);
}

View File

@ -63,6 +63,7 @@ class MetaspaceTracer;
class MetaWord;
class Mutex;
class outputStream;
class PrintCLDMetaspaceInfoClosure;
class SpaceManager;
class VirtualSpaceList;
@ -87,6 +88,7 @@ class Metaspace : public CHeapObj<mtClass> {
friend class MetaspaceAux;
friend class MetaspaceShared;
friend class CollectorPolicy;
friend class PrintCLDMetaspaceInfoClosure;
public:
enum MetadataType {
@ -347,6 +349,8 @@ class MetaspaceAux : AllStatic {
return min_chunk_size_words() * BytesPerWord;
}
static void print_metadata_for_nmt(outputStream* out, size_t scale = K);
static bool has_chunk_free_list(Metaspace::MetadataType mdtype);
static MetaspaceChunkFreeListSummary chunk_free_list_summary(Metaspace::MetadataType mdtype);
@ -357,6 +361,10 @@ class MetaspaceAux : AllStatic {
static void print_class_waste(outputStream* out);
static void print_waste(outputStream* out);
// Prints an ASCII representation of the given space.
static void print_metaspace_map(outputStream* out, Metaspace::MetadataType mdtype);
static void dump(outputStream* out);
static void verify_free_chunks();
// Checks that the values returned by allocated_capacity_bytes() and

View File

@ -305,14 +305,9 @@ void ConstantPool::resolve_class_constants(TRAPS) {
constantPoolHandle cp(THREAD, this);
for (int index = 1; index < length(); index++) { // Index 0 is unused
if (tag_at(index).is_string()) {
Symbol* sym = cp->unresolved_string_at(index);
// Look up only. Only resolve references to already interned strings.
oop str = StringTable::lookup(sym);
if (str != NULL) {
int cache_index = cp->cp_to_object_index(index);
cp->string_at_put(index, cache_index, str);
}
if (tag_at(index).is_string() && !cp->is_pseudo_string_at(index)) {
int cache_index = cp->cp_to_object_index(index);
string_at_impl(cp, index, cache_index, CHECK);
}
}
}

View File

@ -271,7 +271,7 @@ class Method : public Metadata {
int highest_osr_comp_level() const;
void set_highest_osr_comp_level(int level);
#if defined(COMPILER2) || INCLUDE_JVMCI
#if COMPILER2_OR_JVMCI
// Count of times method was exited via exception while interpreting
void interpreter_throwout_increment(TRAPS) {
MethodCounters* mcs = get_method_counters(CHECK);
@ -426,7 +426,7 @@ class Method : public Metadata {
return (mcs == NULL) ? 0 : mcs->interpreter_invocation_count();
}
}
#if defined(COMPILER2) || INCLUDE_JVMCI
#if COMPILER2_OR_JVMCI
int increment_interpreter_invocation_count(TRAPS) {
if (TieredCompilation) ShouldNotReachHere();
MethodCounters* mcs = get_method_counters(CHECK_0);

View File

@ -40,7 +40,7 @@ class MethodCounters : public Metadata {
#if INCLUDE_AOT
Method* _method; // Back link to Method
#endif
#if defined(COMPILER2) || INCLUDE_JVMCI
#if COMPILER2_OR_JVMCI
int _interpreter_invocation_count; // Count of times invoked (reused as prev_event_count in tiered)
u2 _interpreter_throwout_count; // Count of times method was exited via exception while interpreting
#endif
@ -130,7 +130,7 @@ class MethodCounters : public Metadata {
MetaspaceObj::Type type() const { return MethodCountersType; }
void clear_counters();
#if defined(COMPILER2) || INCLUDE_JVMCI
#if COMPILER2_OR_JVMCI
int interpreter_invocation_count() {
return _interpreter_invocation_count;
@ -154,7 +154,7 @@ class MethodCounters : public Metadata {
_interpreter_throwout_count = count;
}
#else // defined(COMPILER2) || INCLUDE_JVMCI
#else // COMPILER2_OR_JVMCI
int interpreter_invocation_count() {
return 0;
@ -170,7 +170,7 @@ class MethodCounters : public Metadata {
assert(count == 0, "count must be 0");
}
#endif // defined(COMPILER2) || INCLUDE_JVMCI
#endif // COMPILER2_OR_JVMCI
#if INCLUDE_JVMTI
u2 number_of_breakpoints() const { return _number_of_breakpoints; }
@ -213,7 +213,7 @@ class MethodCounters : public Metadata {
return byte_offset_of(MethodCounters, _nmethod_age);
}
#if defined(COMPILER2) || INCLUDE_JVMCI
#if COMPILER2_OR_JVMCI
static ByteSize interpreter_invocation_counter_offset() {
return byte_offset_of(MethodCounters, _interpreter_invocation_count);
@ -223,14 +223,14 @@ class MethodCounters : public Metadata {
return offset_of(MethodCounters, _interpreter_invocation_count);
}
#else // defined(COMPILER2) || INCLUDE_JVMCI
#else // COMPILER2_OR_JVMCI
static ByteSize interpreter_invocation_counter_offset() {
ShouldNotReachHere();
return in_ByteSize(0);
}
#endif // defined(COMPILER2) || INCLUDE_JVMCI
#endif // COMPILER2_OR_JVMCI
static ByteSize invocation_counter_offset() {
return byte_offset_of(MethodCounters, _invocation_counter);

View File

@ -3949,7 +3949,7 @@ static jint JNI_CreateJavaVM_inner(JavaVM **vm, void **penv, void *args) {
// JVMCI is initialized on a CompilerThread
if (BootstrapJVMCI) {
JavaThread* THREAD = thread;
JVMCICompiler* compiler = JVMCICompiler::instance(CATCH);
JVMCICompiler* compiler = JVMCICompiler::instance(true, CATCH);
compiler->bootstrap(THREAD);
if (HAS_PENDING_EXCEPTION) {
HandleMark hm;

View File

@ -1715,6 +1715,10 @@ WB_ENTRY(jobject, WB_GetResolvedReferences(JNIEnv* env, jobject wb, jclass clazz
}
WB_END
WB_ENTRY(jboolean, WB_AreOpenArchiveHeapObjectsMapped(JNIEnv* env))
return MetaspaceShared::open_archive_heap_region_mapped();
WB_END
WB_ENTRY(jboolean, WB_IsCDSIncludedInVmBuild(JNIEnv* env))
#if INCLUDE_CDS
return true;
@ -2031,6 +2035,7 @@ static JNINativeMethod methods[] = {
{CC"isSharedClass", CC"(Ljava/lang/Class;)Z", (void*)&WB_IsSharedClass },
{CC"areSharedStringsIgnored", CC"()Z", (void*)&WB_AreSharedStringsIgnored },
{CC"getResolvedReferences", CC"(Ljava/lang/Class;)Ljava/lang/Object;", (void*)&WB_GetResolvedReferences},
{CC"areOpenArchiveHeapObjectsMapped", CC"()Z", (void*)&WB_AreOpenArchiveHeapObjectsMapped},
{CC"isCDSIncludedInVmBuild", CC"()Z", (void*)&WB_IsCDSIncludedInVmBuild },
{CC"clearInlineCaches0", CC"(Z)V", (void*)&WB_ClearInlineCaches },
{CC"addCompilerDirective", CC"(Ljava/lang/String;)I",

View File

@ -396,6 +396,10 @@ static SpecialFlag const special_jvm_flags[] = {
{ "MinSleepInterval", JDK_Version::jdk(9), JDK_Version::jdk(10), JDK_Version::jdk(11) },
{ "PermSize", JDK_Version::undefined(), JDK_Version::jdk(8), JDK_Version::undefined() },
{ "MaxPermSize", JDK_Version::undefined(), JDK_Version::jdk(8), JDK_Version::undefined() },
{ "SharedReadWriteSize", JDK_Version::undefined(), JDK_Version::jdk(10), JDK_Version::undefined() },
{ "SharedReadOnlySize", JDK_Version::undefined(), JDK_Version::jdk(10), JDK_Version::undefined() },
{ "SharedMiscDataSize", JDK_Version::undefined(), JDK_Version::jdk(10), JDK_Version::undefined() },
{ "SharedMiscCodeSize", JDK_Version::undefined(), JDK_Version::jdk(10), JDK_Version::undefined() },
#ifdef TEST_VERIFY_SPECIAL_JVM_FLAGS
{ "dep > obs", JDK_Version::jdk(9), JDK_Version::jdk(8), JDK_Version::undefined() },
@ -1860,7 +1864,7 @@ void Arguments::set_ergonomics_flags() {
#endif
select_gc();
#if defined(COMPILER2) || INCLUDE_JVMCI
#if COMPILER2_OR_JVMCI
// Shared spaces work fine with other GCs but causes bytecode rewriting
// to be disabled, which hurts interpreter performance and decreases
// server performance. When -server is specified, keep the default off
@ -2089,9 +2093,10 @@ void Arguments::set_heap_size() {
// respecting the maximum and minimum sizes of the heap.
if (FLAG_IS_DEFAULT(MaxHeapSize)) {
julong reasonable_max = (julong)((phys_mem * MaxRAMPercentage) / 100);
if (phys_mem <= (julong)((MaxHeapSize * MinRAMPercentage) / 100)) {
const julong reasonable_min = (julong)((phys_mem * MinRAMPercentage) / 100);
if (reasonable_min < MaxHeapSize) {
// Small physical memory, so use a minimum fraction of it for the heap
reasonable_max = (julong)((phys_mem * MinRAMPercentage) / 100);
reasonable_max = reasonable_min;
} else {
// Not-small physical memory, so require a heap at least
// as large as MaxHeapSize

View File

@ -192,7 +192,7 @@ Deoptimization::UnrollBlock* Deoptimization::fetch_unroll_info_helper(JavaThread
bool realloc_failures = false;
#if defined(COMPILER2) || INCLUDE_JVMCI
#if COMPILER2_OR_JVMCI
// Reallocate the non-escaping objects and restore their fields. Then
// relock objects if synchronization on them was eliminated.
#ifndef INCLUDE_JVMCI
@ -282,7 +282,7 @@ Deoptimization::UnrollBlock* Deoptimization::fetch_unroll_info_helper(JavaThread
}
}
#endif // INCLUDE_JVMCI
#endif // COMPILER2 || INCLUDE_JVMCI
#endif // COMPILER2_OR_JVMCI
ScopeDesc* trap_scope = chunk->at(0)->scope();
Handle exceptionObject;
@ -303,7 +303,7 @@ Deoptimization::UnrollBlock* Deoptimization::fetch_unroll_info_helper(JavaThread
NoSafepointVerifier no_safepoint;
vframeArray* array = create_vframeArray(thread, deoptee, &map, chunk, realloc_failures);
#if defined(COMPILER2) || INCLUDE_JVMCI
#if COMPILER2_OR_JVMCI
if (realloc_failures) {
pop_frames_failed_reallocs(thread, array);
}
@ -792,7 +792,7 @@ int Deoptimization::deoptimize_dependents() {
Deoptimization::DeoptAction Deoptimization::_unloaded_action
= Deoptimization::Action_reinterpret;
#if defined(COMPILER2) || INCLUDE_JVMCI
#if COMPILER2_OR_JVMCI
bool Deoptimization::realloc_objects(JavaThread* thread, frame* fr, GrowableArray<ScopeValue*>* objects, TRAPS) {
Handle pending_exception(THREAD, thread->pending_exception());
const char* exception_file = thread->exception_file();
@ -1151,7 +1151,7 @@ void Deoptimization::print_objects(GrowableArray<ScopeValue*>* objects, bool rea
}
}
#endif
#endif // COMPILER2 || INCLUDE_JVMCI
#endif // COMPILER2_OR_JVMCI
vframeArray* Deoptimization::create_vframeArray(JavaThread* thread, frame fr, RegisterMap *reg_map, GrowableArray<compiledVFrame*>* chunk, bool realloc_failures) {
Events::log(thread, "DEOPT PACKING pc=" INTPTR_FORMAT " sp=" INTPTR_FORMAT, p2i(fr.pc()), p2i(fr.sp()));
@ -1211,7 +1211,7 @@ vframeArray* Deoptimization::create_vframeArray(JavaThread* thread, frame fr, Re
return array;
}
#if defined(COMPILER2) || INCLUDE_JVMCI
#if COMPILER2_OR_JVMCI
void Deoptimization::pop_frames_failed_reallocs(JavaThread* thread, vframeArray* array) {
// Reallocation of some scalar replaced objects failed. Record
// that we need to pop all the interpreter frames for the
@ -1443,7 +1443,7 @@ Deoptimization::get_method_data(JavaThread* thread, const methodHandle& m,
return mdo;
}
#if defined(COMPILER2) || INCLUDE_JVMCI
#if COMPILER2_OR_JVMCI
void Deoptimization::load_class_by_index(const constantPoolHandle& constant_pool, int index, TRAPS) {
// in case of an unresolved klass entry, load the class.
if (constant_pool->tag_at(index).is_unresolved_klass()) {
@ -2350,7 +2350,7 @@ void Deoptimization::print_statistics() {
if (xtty != NULL) xtty->tail("statistics");
}
}
#else // COMPILER2 || INCLUDE_JVMCI
#else // COMPILER2_OR_JVMCI
// Stubs for C1 only system.
@ -2386,4 +2386,4 @@ const char* Deoptimization::format_trap_state(char* buf, size_t buflen,
return buf;
}
#endif // COMPILER2 || INCLUDE_JVMCI
#endif // COMPILER2_OR_JVMCI

View File

@ -151,7 +151,7 @@ class Deoptimization : AllStatic {
// executing in a particular CodeBlob if UseBiasedLocking is enabled
static void revoke_biases_of_monitors(CodeBlob* cb);
#if defined(COMPILER2) || INCLUDE_JVMCI
#if COMPILER2_OR_JVMCI
JVMCI_ONLY(public:)
// Support for restoring non-escaping objects
@ -162,7 +162,7 @@ JVMCI_ONLY(public:)
static void relock_objects(GrowableArray<MonitorInfo*>* monitors, JavaThread* thread, bool realloc_failures);
static void pop_frames_failed_reallocs(JavaThread* thread, vframeArray* array);
NOT_PRODUCT(static void print_objects(GrowableArray<ScopeValue*>* objects, bool realloc_failures);)
#endif // COMPILER2 || INCLUDE_JVMCI
#endif // COMPILER2_OR_JVMCI
public:
static vframeArray* create_vframeArray(JavaThread* thread, frame fr, RegisterMap *reg_map, GrowableArray<compiledVFrame*>* chunk, bool realloc_failures);

View File

@ -1148,7 +1148,7 @@ void frame::verify(const RegisterMap* map) {
// make sure we have the right receiver type
}
}
#if defined(COMPILER2) || INCLUDE_JVMCI
#if COMPILER2_OR_JVMCI
assert(DerivedPointerTable::is_empty(), "must be empty before verify");
#endif
oops_do_internal(&VerifyOopClosure::verify_oop, NULL, (RegisterMap*)map, false);

View File

@ -99,11 +99,11 @@ define_pd_global(uint64_t,MaxRAM, 1ULL*G);
#define CI_COMPILER_COUNT 0
#else
#if defined(COMPILER2) || INCLUDE_JVMCI
#if COMPILER2_OR_JVMCI
#define CI_COMPILER_COUNT 2
#else
#define CI_COMPILER_COUNT 1
#endif // COMPILER2 || INCLUDE_JVMCI
#endif // COMPILER2_OR_JVMCI
#endif // no compilers
@ -3901,18 +3901,6 @@ public:
"If PrintSharedArchiveAndExit is true, also print the shared " \
"dictionary") \
\
product(size_t, SharedReadWriteSize, 0, \
"Deprecated") \
\
product(size_t, SharedReadOnlySize, 0, \
"Deprecated") \
\
product(size_t, SharedMiscDataSize, 0, \
"Deprecated") \
\
product(size_t, SharedMiscCodeSize, 0, \
"Deprecated") \
\
product(size_t, SharedBaseAddress, LP64_ONLY(32*G) \
NOT_LP64(LINUX_ONLY(2*G) NOT_LINUX(0)), \
"Address to allocate shared memory region for class data") \

View File

@ -155,7 +155,7 @@ void InterpretedRFrame::init() {
void RFrame::print(const char* kind) {
#ifndef PRODUCT
#if defined(COMPILER2) || INCLUDE_JVMCI
#if COMPILER2_OR_JVMCI
int cnt = top_method()->interpreter_invocation_count();
#else
int cnt = top_method()->invocation_count();

View File

@ -102,13 +102,13 @@ void SharedRuntime::generate_stubs() {
_resolve_static_call_blob = generate_resolve_blob(CAST_FROM_FN_PTR(address, SharedRuntime::resolve_static_call_C), "resolve_static_call");
_resolve_static_call_entry = _resolve_static_call_blob->entry_point();
#if defined(COMPILER2) || INCLUDE_JVMCI
#if COMPILER2_OR_JVMCI
// Vectors are generated only by C2 and JVMCI.
bool support_wide = is_wide_vector(MaxVectorSize);
if (support_wide) {
_polling_page_vectors_safepoint_handler_blob = generate_handler_blob(CAST_FROM_FN_PTR(address, SafepointSynchronize::handle_polling_page_exception), POLL_AT_VECTOR_LOOP);
}
#endif // COMPILER2 || INCLUDE_JVMCI
#endif // COMPILER2_OR_JVMCI
_polling_page_safepoint_handler_blob = generate_handler_blob(CAST_FROM_FN_PTR(address, SafepointSynchronize::handle_polling_page_exception), POLL_AT_LOOP);
_polling_page_return_handler_blob = generate_handler_blob(CAST_FROM_FN_PTR(address, SafepointSynchronize::handle_polling_page_exception), POLL_AT_RETURN);

View File

@ -3724,7 +3724,7 @@ jint Threads::create_vm(JavaVMInitArgs* args, bool* canTryAgain) {
}
// initialize compiler(s)
#if defined(COMPILER1) || defined(COMPILER2) || INCLUDE_JVMCI
#if defined(COMPILER1) || COMPILER2_OR_JVMCI
CompileBroker::compilation_init(CHECK_JNI_ERR);
#endif

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -230,6 +230,10 @@ void VM_PrintJNI::doit() {
JNIHandles::print_on(_out);
}
void VM_PrintMetadata::doit() {
MetaspaceAux::print_metadata_for_nmt(_out, _scale);
}
VM_FindDeadlocks::~VM_FindDeadlocks() {
if (_deadlocks != NULL) {
DeadlockCycle* cycle = _deadlocks;

View File

@ -111,6 +111,7 @@
template(ThreadsSuspendJVMTI) \
template(ICBufferFull) \
template(ScavengeMonitors) \
template(PrintMetadata) \
class VM_Operation: public CHeapObj<mtInternal> {
public:
@ -374,6 +375,17 @@ class VM_PrintJNI: public VM_Operation {
void doit();
};
class VM_PrintMetadata : public VM_Operation {
private:
outputStream* _out;
size_t _scale;
public:
VM_PrintMetadata(outputStream* out, size_t scale) : _out(out), _scale(scale) {};
VMOp_Type type() const { return VMOp_PrintMetadata; }
void doit();
};
class DeadlockCycle;
class VM_FindDeadlocks: public VM_Operation {
private:

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -24,6 +24,8 @@
#include "precompiled.hpp"
#include "memory/resourceArea.hpp"
#include "runtime/mutexLocker.hpp"
#include "runtime/vmThread.hpp"
#include "runtime/vm_operations.hpp"
#include "services/nmtDCmd.hpp"
#include "services/memReporter.hpp"
#include "services/memTracker.hpp"
@ -38,6 +40,8 @@ NMTDCmd::NMTDCmd(outputStream* output,
_detail("detail", "request runtime to report memory allocation >= "
"1K by each callsite.",
"BOOLEAN", false, "false"),
_metadata("metadata", "request runtime to report metadata information",
"BOOLEAN", false, "false"),
_baseline("baseline", "request runtime to baseline current memory usage, " \
"so it can be compared against in later time.",
"BOOLEAN", false, "false"),
@ -57,6 +61,7 @@ NMTDCmd::NMTDCmd(outputStream* output,
"STRING", false, "KB") {
_dcmdparser.add_dcmd_option(&_summary);
_dcmdparser.add_dcmd_option(&_detail);
_dcmdparser.add_dcmd_option(&_metadata);
_dcmdparser.add_dcmd_option(&_baseline);
_dcmdparser.add_dcmd_option(&_summary_diff);
_dcmdparser.add_dcmd_option(&_detail_diff);
@ -92,6 +97,7 @@ void NMTDCmd::execute(DCmdSource source, TRAPS) {
int nopt = 0;
if (_summary.is_set() && _summary.value()) { ++nopt; }
if (_detail.is_set() && _detail.value()) { ++nopt; }
if (_metadata.is_set() && _metadata.value()) { ++nopt; }
if (_baseline.is_set() && _baseline.value()) { ++nopt; }
if (_summary_diff.is_set() && _summary_diff.value()) { ++nopt; }
if (_detail_diff.is_set() && _detail_diff.value()) { ++nopt; }
@ -100,7 +106,7 @@ void NMTDCmd::execute(DCmdSource source, TRAPS) {
if (nopt > 1) {
output()->print_cr("At most one of the following option can be specified: " \
"summary, detail, baseline, summary.diff, detail.diff, shutdown");
"summary, detail, metadata, baseline, summary.diff, detail.diff, shutdown");
return;
} else if (nopt == 0) {
if (_summary.is_set()) {
@ -118,9 +124,13 @@ void NMTDCmd::execute(DCmdSource source, TRAPS) {
report(true, scale_unit);
} else if (_detail.value()) {
if (!check_detail_tracking_level(output())) {
return;
}
return;
}
report(false, scale_unit);
} else if (_metadata.value()) {
size_t scale = get_scale(_scale.value());
VM_PrintMetadata op(output(), scale);
VMThread::execute(&op);
} else if (_baseline.value()) {
MemBaseline& baseline = MemTracker::get_baseline();
if (!baseline.baseline(MemTracker::tracking_level() != NMT_detail)) {

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -39,6 +39,7 @@ class NMTDCmd: public DCmdWithParser {
protected:
DCmdArgument<bool> _summary;
DCmdArgument<bool> _detail;
DCmdArgument<bool> _metadata;
DCmdArgument<bool> _baseline;
DCmdArgument<bool> _summary_diff;
DCmdArgument<bool> _detail_diff;

View File

@ -698,7 +698,7 @@ public final class FilePermission extends Permission implements Serializable {
if (p2.equals(EMPTY_PATH)) {
return 0;
} else if (p2.getName(0).equals(DOTDOT_PATH)) {
// "." contains p2 iif p2 has no "..". Since a
// "." contains p2 iff p2 has no "..". Since
// a normalized path can only have 0 or more
// ".." at the beginning. We only need to look
// at the head.
@ -711,7 +711,7 @@ public final class FilePermission extends Permission implements Serializable {
} else if (p2.equals(EMPTY_PATH)) {
int c1 = p1.getNameCount();
if (!p1.getName(c1 - 1).equals(DOTDOT_PATH)) {
// "." is inside p1 iif p1 is 1 or more "..".
// "." is inside p1 iff p1 is 1 or more "..".
// For the same reason above, we only need to
// look at the tail.
return -1;

View File

@ -57,8 +57,6 @@ import java.util.stream.Stream;
import jdk.internal.loader.BuiltinClassLoader;
import jdk.internal.loader.BootLoader;
import jdk.internal.loader.ClassLoaders;
import jdk.internal.misc.JavaLangAccess;
import jdk.internal.misc.SharedSecrets;
import jdk.internal.module.IllegalAccessLogger;
import jdk.internal.module.ModuleLoaderMap;
import jdk.internal.module.ServicesCatalog;
@ -68,6 +66,7 @@ import jdk.internal.org.objectweb.asm.Attribute;
import jdk.internal.org.objectweb.asm.ClassReader;
import jdk.internal.org.objectweb.asm.ClassVisitor;
import jdk.internal.org.objectweb.asm.ClassWriter;
import jdk.internal.org.objectweb.asm.ModuleVisitor;
import jdk.internal.org.objectweb.asm.Opcodes;
import jdk.internal.reflect.CallerSensitive;
import jdk.internal.reflect.Reflection;
@ -1432,7 +1431,7 @@ public final class Module implements AnnotatedElement {
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS
+ ClassWriter.COMPUTE_FRAMES);
ClassVisitor cv = new ClassVisitor(Opcodes.ASM5, cw) {
ClassVisitor cv = new ClassVisitor(Opcodes.ASM6, cw) {
@Override
public void visit(int version,
int access,
@ -1458,6 +1457,11 @@ public final class Module implements AnnotatedElement {
public void visitAttribute(Attribute attr) {
// drop non-annotation attributes
}
@Override
public ModuleVisitor visitModule(String name, int flags, String version) {
// drop Module attribute
return null;
}
};
ClassReader cr = new ClassReader(in);

View File

@ -1937,7 +1937,7 @@ public final class System {
// initialization. So make sure the "props" is available at the
// very beginning of the initialization and all system properties to
// be put into it directly.
props = new Properties();
props = new Properties(84);
initProperties(props); // initialized by the VM
// There are certain system configurations that may be controlled by

View File

@ -765,7 +765,7 @@ public abstract class MethodHandle {
* In every other case, all conversions are applied <em>pairwise</em>,
* which means that each argument or return value is converted to
* exactly one argument or return value (or no return value).
* The applied conversions are defined by consulting the
* The applied conversions are defined by consulting
* the corresponding component types of the old and new
* method handle types.
* <p>

View File

@ -194,7 +194,7 @@ public final class StringConcatFactory {
static {
// In case we need to double-back onto the StringConcatFactory during this
// static initialization, make sure we have the reasonable defaults to complete
// the static initialization properly. After that, actual users would use the
// the static initialization properly. After that, actual users would use
// the proper values we have read from the properties.
STRATEGY = DEFAULT_STRATEGY;
// CACHE_ENABLE = false; // implied

View File

@ -205,7 +205,7 @@ import static java.lang.invoke.MethodHandleStatics.newInternalError;
* and {@code double} on 32-bit platforms.
*
* <p>Access modes will override any memory ordering effects specified at
* the declaration site of a variable. For example, a VarHandle accessing a
* the declaration site of a variable. For example, a VarHandle accessing
* a field using the {@code get} access mode will access the field as
* specified <em>by its access mode</em> even if that field is declared
* {@code volatile}. When mixed access is performed extreme care should be
@ -423,7 +423,7 @@ import static java.lang.invoke.MethodHandleStatics.newInternalError;
* {@link java.lang.invoke.MethodHandles#varHandleInvoker}.
*
* <h1>Interoperation between VarHandles and Java generics</h1>
* A VarHandle can be obtained for a variable, such as a a field, which is
* A VarHandle can be obtained for a variable, such as a field, which is
* declared with Java generic types. As with the Core Reflection API, the
* VarHandle's variable type will be constructed from the erasure of the
* source-level type. When a VarHandle access mode method is invoked, the

View File

@ -988,7 +988,7 @@ class DatagramSocket implements java.io.Closeable {
/**
* Sets the SO_RCVBUF option to the specified value for this
* {@code DatagramSocket}. The SO_RCVBUF option is used by the
* {@code DatagramSocket}. The SO_RCVBUF option is used by
* the network implementation as a hint to size the underlying
* network I/O buffers. The SO_RCVBUF setting may also be used
* by the network implementation to determine the maximum size

View File

@ -143,7 +143,7 @@ class Inet4Address extends InetAddress {
/**
* Prior to 1.4 an InetAddress was created with a family
* based on the platform AF_INET value (usually 2).
* For compatibility reasons we must therefore write the
* For compatibility reasons we must therefore write
* the InetAddress with this family.
*/
inet.holder().family = 2;

View File

@ -333,7 +333,7 @@ public abstract class SocketImpl implements SocketOptions {
* latency, and low latency above short connection time, then it could
* invoke this method with the values {@code (0, 1, 2)}.
*
* By default, this method does nothing, unless it is overridden in a
* By default, this method does nothing, unless it is overridden in
* a sub-class.
*
* @param connectionTime

View File

@ -657,7 +657,7 @@ class SocksSocketImpl extends PlainSocketImpl implements SocksConsts {
/**
* Sends the Bind request to the SOCKS proxy. In the SOCKS protocol, bind
* means "accept incoming connection from", so the SocketAddress is the
* means "accept incoming connection from", so the SocketAddress is
* the one of the host we do accept connection from.
*
* @param saddr the Socket address of the remote host.

View File

@ -785,7 +785,7 @@ public abstract class URLConnection {
* required to make the connection. By default, this method
* returns {@code java.security.AllPermission}. Subclasses
* should override this method and return the permission
* that best represents the permission required to make a
* that best represents the permission required to make
* a connection to the URL. For example, a {@code URLConnection}
* representing a {@code file:} URL would return a
* {@code java.io.FilePermission} object.

View File

@ -165,7 +165,7 @@ public abstract class AsynchronousFileChannel
* <tr>
* <th scope="row" > {@link StandardOpenOption#DELETE_ON_CLOSE DELETE_ON_CLOSE} </th>
* <td> When this option is present then the implementation makes a
* <em>best effort</em> attempt to delete the file when closed by the
* <em>best effort</em> attempt to delete the file when closed by
* the {@link #close close} method. If the {@code close} method is not
* invoked then a <em>best effort</em> attempt is made to delete the file
* when the Java virtual machine terminates. </td>

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -368,6 +368,10 @@ public final class Channels {
@Override
public int read(ByteBuffer dst) throws IOException {
if (!isOpen()) {
throw new ClosedChannelException();
}
int len = dst.remaining();
int totalRead = 0;
int bytesRead = 0;
@ -442,6 +446,10 @@ public final class Channels {
@Override
public int write(ByteBuffer src) throws IOException {
if (!isOpen()) {
throw new ClosedChannelException();
}
int len = src.remaining();
int totalWritten = 0;
synchronized (writeLock) {

View File

@ -216,7 +216,7 @@ public abstract class FileChannel
* <tr>
* <th scope="row" > {@link StandardOpenOption#DELETE_ON_CLOSE DELETE_ON_CLOSE} </th>
* <td> When this option is present then the implementation makes a
* <em>best effort</em> attempt to delete the file when closed by the
* <em>best effort</em> attempt to delete the file when closed by
* the {@link #close close} method. If the {@code close} method is not
* invoked then a <em>best effort</em> attempt is made to delete the file
* when the Java virtual machine terminates. </td>

View File

@ -2401,7 +2401,7 @@ public final class Files {
*
* <p> Note that the result of this method is immediately outdated. If this
* method indicates the file exists then there is no guarantee that a
* subsequence access will succeed. Care should be taken when using this
* subsequent access will succeed. Care should be taken when using this
* method in security sensitive applications.
*
* @param path
@ -2458,7 +2458,7 @@ public final class Files {
* or not then both methods return {@code false}. As with the {@code exists}
* method, the result of this method is immediately outdated. If this
* method indicates the file does exist then there is no guarantee that a
* subsequence attempt to create the file will succeed. Care should be taken
* subsequent attempt to create the file will succeed. Care should be taken
* when using this method in security sensitive applications.
*
* @param path
@ -3301,7 +3301,7 @@ public final class Files {
}
/**
* Writes bytes to a file. The {@code options} parameter specifies how the
* Writes bytes to a file. The {@code options} parameter specifies how
* the file is created or opened. If no options are present then this method
* works as if the {@link StandardOpenOption#CREATE CREATE}, {@link
* StandardOpenOption#TRUNCATE_EXISTING TRUNCATE_EXISTING}, and {@link

View File

@ -84,7 +84,7 @@ import sun.security.util.Debug;
* exists (e.g., so-called <i>community parameters</i> in DSA), there are two
* {@link #initialize(java.security.spec.AlgorithmParameterSpec)
* initialize} methods that have an {@code AlgorithmParameterSpec}
* argument. One also has a {@code SecureRandom} argument, while the
* argument. One also has a {@code SecureRandom} argument, while
* the other uses the {@code SecureRandom}
* implementation of the highest-priority installed provider as the source
* of randomness. (If none of the installed providers supply an implementation

View File

@ -4775,7 +4775,7 @@ public final class DateTimeFormatterBuilder {
//-----------------------------------------------------------------------
/**
* Prints or parses a localized pattern from a localized field.
* The specific formatter and parameters is not selected until the
* The specific formatter and parameters is not selected until
* the field is to be printed or parsed.
* The locale is needed to select the proper WeekFields from which
* the field for day-of-week, week-of-month, or week-of-year is selected.

View File

@ -311,7 +311,7 @@ public final class WeekFields implements Serializable {
* the new month or year.
* <p>
* WeekFields instances are singletons; for each unique combination
* of {@code firstDayOfWeek} and {@code minimalDaysInFirstWeek} the
* of {@code firstDayOfWeek} and {@code minimalDaysInFirstWeek}
* the same instance will be returned.
*
* @param firstDayOfWeek the first day of the week, not null

View File

@ -56,7 +56,7 @@ import java.nio.charset.StandardCharsets;
* base64 alphabet.</p></li>
*
* <li><a id="mime"><b>MIME</b></a>
* <p> Uses the "The Base64 Alphabet" as specified in Table 1 of
* <p> Uses "The Base64 Alphabet" as specified in Table 1 of
* RFC 2045 for encoding and decoding operation. The encoded output
* must be represented in lines of no more than 76 characters each
* and uses a carriage return {@code '\r'} followed immediately by

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -26,6 +26,7 @@ package java.util;
import java.util.function.DoubleConsumer;
import java.util.stream.Collector;
import java.util.stream.DoubleStream;
/**
* A state object for collecting statistics such as count, min, max, sum, and
@ -69,12 +70,65 @@ public class DoubleSummaryStatistics implements DoubleConsumer {
private double max = Double.NEGATIVE_INFINITY;
/**
* Construct an empty instance with zero count, zero sum,
* Constructs an empty instance with zero count, zero sum,
* {@code Double.POSITIVE_INFINITY} min, {@code Double.NEGATIVE_INFINITY}
* max and zero average.
*/
public DoubleSummaryStatistics() { }
/**
* Constructs a non-empty instance with the specified {@code count},
* {@code min}, {@code max}, and {@code sum}.
*
* <p>If {@code count} is zero then the remaining arguments are ignored and
* an empty instance is constructed.
*
* <p>If the arguments are inconsistent then an {@code IllegalArgumentException}
* is thrown. The necessary consistent argument conditions are:
* <ul>
* <li>{@code count >= 0}</li>
* <li>{@code (min <= max && !isNaN(sum)) || (isNaN(min) && isNaN(max) && isNaN(sum))}</li>
* </ul>
* @apiNote
* The enforcement of argument correctness means that the retrieved set of
* recorded values obtained from a {@code DoubleSummaryStatistics} source
* instance may not be a legal set of arguments for this constructor due to
* arithmetic overflow of the source's recorded count of values.
* The consistent argument conditions are not sufficient to prevent the
* creation of an internally inconsistent instance. An example of such a
* state would be an instance with: {@code count} = 2, {@code min} = 1,
* {@code max} = 2, and {@code sum} = 0.
*
* @param count the count of values
* @param min the minimum value
* @param max the maximum value
* @param sum the sum of all values
* @throws IllegalArgumentException if the arguments are inconsistent
* @since 10
*/
public DoubleSummaryStatistics(long count, double min, double max, double sum)
throws IllegalArgumentException {
if (count < 0L) {
throw new IllegalArgumentException("Negative count value");
} else if (count > 0L) {
if (min > max)
throw new IllegalArgumentException("Minimum greater than maximum");
// All NaN or non NaN
var ncount = DoubleStream.of(min, max, sum).filter(Double::isNaN).count();
if (ncount > 0 && ncount < 3)
throw new IllegalArgumentException("Some, not all, of the minimum, maximum, or sum is NaN");
this.count = count;
this.sum = sum;
this.simpleSum = sum;
this.sumCompensation = 0.0d;
this.min = min;
this.max = max;
}
// Use default field values if count == 0
}
/**
* Records another value into the summary information.
*

View File

@ -43,13 +43,13 @@ public class EventObject implements java.io.Serializable {
/**
* The object on which the Event initially occurred.
*/
protected transient Object source;
protected transient Object source;
/**
* Constructs a prototypical Event.
*
* @param source The object on which the Event initially occurred.
* @exception IllegalArgumentException if source is null.
* @param source the object on which the Event initially occurred
* @throws IllegalArgumentException if source is null
*/
public EventObject(Object source) {
if (source == null)
@ -61,7 +61,7 @@ public class EventObject implements java.io.Serializable {
/**
* The object on which the Event initially occurred.
*
* @return The object on which the Event initially occurred.
* @return the object on which the Event initially occurred
*/
public Object getSource() {
return source;
@ -70,7 +70,7 @@ public class EventObject implements java.io.Serializable {
/**
* Returns a String representation of this EventObject.
*
* @return A a String representation of this EventObject.
* @return a String representation of this EventObject
*/
public String toString() {
return getClass().getName() + "[source=" + source + "]";

View File

@ -26,7 +26,7 @@
package java.util;
/**
* FomattableFlags are passed to the {@link Formattable#formatTo
* FormattableFlags are passed to the {@link Formattable#formatTo
* Formattable.formatTo()} method and modify the output format for {@linkplain
* Formattable Formattables}. Implementations of {@link Formattable} are
* responsible for interpreting and validating any flags.

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -69,12 +69,57 @@ public class IntSummaryStatistics implements IntConsumer {
private int max = Integer.MIN_VALUE;
/**
* Construct an empty instance with zero count, zero sum,
* Constructs an empty instance with zero count, zero sum,
* {@code Integer.MAX_VALUE} min, {@code Integer.MIN_VALUE} max and zero
* average.
*/
public IntSummaryStatistics() { }
/**
* Constructs a non-empty instance with the specified {@code count},
* {@code min}, {@code max}, and {@code sum}.
*
* <p>If {@code count} is zero then the remaining arguments are ignored and
* an empty instance is constructed.
*
* <p>If the arguments are inconsistent then an {@code IllegalArgumentException}
* is thrown. The necessary consistent argument conditions are:
* <ul>
* <li>{@code count >= 0}</li>
* <li>{@code min <= max}</li>
* </ul>
* @apiNote
* The enforcement of argument correctness means that the retrieved set of
* recorded values obtained from a {@code IntSummaryStatistics} source
* instance may not be a legal set of arguments for this constructor due to
* arithmetic overflow of the source's recorded count of values.
* The consistent argument conditions are not sufficient to prevent the
* creation of an internally inconsistent instance. An example of such a
* state would be an instance with: {@code count} = 2, {@code min} = 1,
* {@code max} = 2, and {@code sum} = 0.
*
* @param count the count of values
* @param min the minimum value
* @param max the maximum value
* @param sum the sum of all values
* @throws IllegalArgumentException if the arguments are inconsistent
* @since 10
*/
public IntSummaryStatistics(long count, int min, int max, long sum)
throws IllegalArgumentException {
if (count < 0L) {
throw new IllegalArgumentException("Negative count value");
} else if (count > 0L) {
if (min > max) throw new IllegalArgumentException("Minimum greater than maximum");
this.count = count;
this.sum = sum;
this.min = min;
this.max = max;
}
// Use default field values if count == 0
}
/**
* Records a new value into the summary information
*

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -70,12 +70,57 @@ public class LongSummaryStatistics implements LongConsumer, IntConsumer {
private long max = Long.MIN_VALUE;
/**
* Construct an empty instance with zero count, zero sum,
* Constructs an empty instance with zero count, zero sum,
* {@code Long.MAX_VALUE} min, {@code Long.MIN_VALUE} max and zero
* average.
*/
public LongSummaryStatistics() { }
/**
* Constructs a non-empty instance with the specified {@code count},
* {@code min}, {@code max}, and {@code sum}.
*
* <p>If {@code count} is zero then the remaining arguments are ignored and
* an empty instance is constructed.
*
* <p>If the arguments are inconsistent then an {@code IllegalArgumentException}
* is thrown. The necessary consistent argument conditions are:
* <ul>
* <li>{@code count >= 0}</li>
* <li>{@code min <= max}</li>
* </ul>
* @apiNote
* The enforcement of argument correctness means that the retrieved set of
* recorded values obtained from a {@code LongSummaryStatistics} source
* instance may not be a legal set of arguments for this constructor due to
* arithmetic overflow of the source's recorded count of values.
* The consistent argument conditions are not sufficient to prevent the
* creation of an internally inconsistent instance. An example of such a
* state would be an instance with: {@code count} = 2, {@code min} = 1,
* {@code max} = 2, and {@code sum} = 0.
*
* @param count the count of values
* @param min the minimum value
* @param max the maximum value
* @param sum the sum of all values
* @throws IllegalArgumentException if the arguments are inconsistent
* @since 10
*/
public LongSummaryStatistics(long count, long min, long max, long sum)
throws IllegalArgumentException {
if (count < 0L) {
throw new IllegalArgumentException("Negative count value");
} else if (count > 0L) {
if (min > max) throw new IllegalArgumentException("Minimum greater than maximum");
this.count = count;
this.sum = sum;
this.min = min;
this.max = max;
}
// Use default field values if count == 0
}
/**
* Records a new {@code int} value into the summary information.
*

View File

@ -122,6 +122,10 @@ import jdk.internal.util.xml.PropertiesDefaultHandler;
* <p>This class is thread-safe: multiple threads can share a single
* {@code Properties} object without the need for external synchronization.
*
* @apiNote
* The {@code Properties} class does not inherit the concept of a load factor
* from its superclass, {@code Hashtable}.
*
* @author Arthur van Hoff
* @author Michael McCloskey
* @author Xueming Shen
@ -148,25 +152,49 @@ class Properties extends Hashtable<Object,Object> {
* simple read operations. Writes and bulk operations remain synchronized,
* as in Hashtable.
*/
private transient ConcurrentHashMap<Object, Object> map =
new ConcurrentHashMap<>(8);
private transient ConcurrentHashMap<Object, Object> map;
/**
* Creates an empty property list with no default values.
*
* @implNote The initial capacity of a {@code Properties} object created
* with this constructor is unspecified.
*/
public Properties() {
this(null);
this(null, 8);
}
/**
* Creates an empty property list with no default values, and with an
* initial size accommodating the specified number of elements without the
* need to dynamically resize.
*
* @param initialCapacity the {@code Properties} will be sized to
* accommodate this many elements
* @throws IllegalArgumentException if the initial capacity is less than
* zero.
*/
public Properties(int initialCapacity) {
this(null, initialCapacity);
}
/**
* Creates an empty property list with the specified defaults.
*
* @implNote The initial capacity of a {@code Properties} object created
* with this constructor is unspecified.
*
* @param defaults the defaults.
*/
public Properties(Properties defaults) {
this(defaults, 8);
}
private Properties(Properties defaults, int initialCapacity) {
// use package-private constructor to
// initialize unused fields with dummy values
super((Void) null);
map = new ConcurrentHashMap<>(initialCapacity);
this.defaults = defaults;
}

View File

@ -2743,7 +2743,7 @@ public abstract class ResourceBundle {
* of multiple subtags separated by underscore, generate candidate
* <code>Locale</code>s by omitting the variant subtags one by one, then
* insert them after every occurrence of <code> Locale</code>s with the
* full variant value in the original list. For example, if the
* full variant value in the original list. For example, if
* the variant consists of two subtags <em>V1</em> and <em>V2</em>:
*
* <ul>

View File

@ -238,7 +238,7 @@ public final class BootstrapLogger implements Logger, PlatformLogger.Bridge,
// This way we could simply do things like:
// push((logger) -> logger.log(level, msg));
// Unfortunately, if we come to here it means we are in the bootsraping
// phase where using lambdas is not safe yet - so we have to use a
// phase where using lambdas is not safe yet - so we have to use
// a data object instead...
//
static final class LogEvent {

View File

@ -1,765 +0,0 @@
/*
* 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.internal.module;
import java.lang.module.ModuleDescriptor;
import java.lang.module.ModuleDescriptor.Builder;
import java.lang.module.ModuleDescriptor.Requires;
import java.lang.module.ModuleDescriptor.Exports;
import java.lang.module.ModuleDescriptor.Opens;
import java.lang.module.ModuleDescriptor.Provides;
import java.lang.module.ModuleDescriptor.Version;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import jdk.internal.misc.JavaLangModuleAccess;
import jdk.internal.misc.SharedSecrets;
import jdk.internal.org.objectweb.asm.Attribute;
import jdk.internal.org.objectweb.asm.ByteVector;
import jdk.internal.org.objectweb.asm.ClassReader;
import jdk.internal.org.objectweb.asm.ClassWriter;
import jdk.internal.org.objectweb.asm.Label;
import static jdk.internal.module.ClassFileConstants.*;
/**
* Provides ASM implementations of {@code Attribute} to read and write the
* class file attributes in a module-info class file.
*/
public final class ClassFileAttributes {
private ClassFileAttributes() { }
/**
* Module_attribute {
* // See lang-vm.html for details.
* }
*/
public static class ModuleAttribute extends Attribute {
private static final JavaLangModuleAccess JLMA
= SharedSecrets.getJavaLangModuleAccess();
private ModuleDescriptor descriptor;
private Version replacementVersion;
public ModuleAttribute(ModuleDescriptor descriptor) {
super(MODULE);
this.descriptor = descriptor;
}
public ModuleAttribute(Version v) {
super(MODULE);
this.replacementVersion = v;
}
public ModuleAttribute() {
super(MODULE);
}
@Override
protected Attribute read(ClassReader cr,
int off,
int len,
char[] buf,
int codeOff,
Label[] labels)
{
// module_name (CONSTANT_Module_info)
String mn = cr.readModule(off, buf);
off += 2;
// module_flags
int module_flags = cr.readUnsignedShort(off);
off += 2;
Set<ModuleDescriptor.Modifier> modifiers = new HashSet<>();
if ((module_flags & ACC_OPEN) != 0)
modifiers.add(ModuleDescriptor.Modifier.OPEN);
if ((module_flags & ACC_SYNTHETIC) != 0)
modifiers.add(ModuleDescriptor.Modifier.SYNTHETIC);
if ((module_flags & ACC_MANDATED) != 0)
modifiers.add(ModuleDescriptor.Modifier.MANDATED);
Builder builder = JLMA.newModuleBuilder(mn, false, modifiers);
// module_version
String module_version = cr.readUTF8(off, buf);
off += 2;
if (replacementVersion != null) {
builder.version(replacementVersion);
} else if (module_version != null) {
builder.version(module_version);
}
// requires_count and requires[requires_count]
int requires_count = cr.readUnsignedShort(off);
off += 2;
for (int i=0; i<requires_count; i++) {
// CONSTANT_Module_info
String dn = cr.readModule(off, buf);
off += 2;
// requires_flags
int requires_flags = cr.readUnsignedShort(off);
off += 2;
Set<Requires.Modifier> mods;
if (requires_flags == 0) {
mods = Collections.emptySet();
} else {
mods = new HashSet<>();
if ((requires_flags & ACC_TRANSITIVE) != 0)
mods.add(Requires.Modifier.TRANSITIVE);
if ((requires_flags & ACC_STATIC_PHASE) != 0)
mods.add(Requires.Modifier.STATIC);
if ((requires_flags & ACC_SYNTHETIC) != 0)
mods.add(Requires.Modifier.SYNTHETIC);
if ((requires_flags & ACC_MANDATED) != 0)
mods.add(Requires.Modifier.MANDATED);
}
// requires_version
String requires_version = cr.readUTF8(off, buf);
off += 2;
if (requires_version == null) {
builder.requires(mods, dn);
} else {
JLMA.requires(builder, mods, dn, requires_version);
}
}
// exports_count and exports[exports_count]
int exports_count = cr.readUnsignedShort(off);
off += 2;
if (exports_count > 0) {
for (int i=0; i<exports_count; i++) {
// CONSTANT_Package_info
String pkg = cr.readPackage(off, buf).replace('/', '.');
off += 2;
int exports_flags = cr.readUnsignedShort(off);
off += 2;
Set<Exports.Modifier> mods;
if (exports_flags == 0) {
mods = Collections.emptySet();
} else {
mods = new HashSet<>();
if ((exports_flags & ACC_SYNTHETIC) != 0)
mods.add(Exports.Modifier.SYNTHETIC);
if ((exports_flags & ACC_MANDATED) != 0)
mods.add(Exports.Modifier.MANDATED);
}
int exports_to_count = cr.readUnsignedShort(off);
off += 2;
if (exports_to_count > 0) {
Set<String> targets = new HashSet<>();
for (int j=0; j<exports_to_count; j++) {
String t = cr.readModule(off, buf);
off += 2;
targets.add(t);
}
builder.exports(mods, pkg, targets);
} else {
builder.exports(mods, pkg);
}
}
}
// opens_count and opens[opens_count]
int open_count = cr.readUnsignedShort(off);
off += 2;
if (open_count > 0) {
for (int i=0; i<open_count; i++) {
// CONSTANT_Package_info
String pkg = cr.readPackage(off, buf).replace('/', '.');
off += 2;
int opens_flags = cr.readUnsignedShort(off);
off += 2;
Set<Opens.Modifier> mods;
if (opens_flags == 0) {
mods = Collections.emptySet();
} else {
mods = new HashSet<>();
if ((opens_flags & ACC_SYNTHETIC) != 0)
mods.add(Opens.Modifier.SYNTHETIC);
if ((opens_flags & ACC_MANDATED) != 0)
mods.add(Opens.Modifier.MANDATED);
}
int opens_to_count = cr.readUnsignedShort(off);
off += 2;
if (opens_to_count > 0) {
Set<String> targets = new HashSet<>();
for (int j=0; j<opens_to_count; j++) {
String t = cr.readModule(off, buf);
off += 2;
targets.add(t);
}
builder.opens(mods, pkg, targets);
} else {
builder.opens(mods, pkg);
}
}
}
// uses_count and uses_index[uses_count]
int uses_count = cr.readUnsignedShort(off);
off += 2;
if (uses_count > 0) {
for (int i=0; i<uses_count; i++) {
String sn = cr.readClass(off, buf).replace('/', '.');
builder.uses(sn);
off += 2;
}
}
// provides_count and provides[provides_count]
int provides_count = cr.readUnsignedShort(off);
off += 2;
if (provides_count > 0) {
for (int i=0; i<provides_count; i++) {
String service = cr.readClass(off, buf).replace('/', '.');
off += 2;
int with_count = cr.readUnsignedShort(off);
off += 2;
List<String> providers = new ArrayList<>();
for (int j=0; j<with_count; j++) {
String cn = cr.readClass(off, buf).replace('/', '.');
off += 2;
providers.add(cn);
}
builder.provides(service, providers);
}
}
return new ModuleAttribute(builder.build());
}
@Override
protected ByteVector write(ClassWriter cw,
byte[] code,
int len,
int maxStack,
int maxLocals)
{
assert descriptor != null;
ByteVector attr = new ByteVector();
// module_name
String mn = descriptor.name();
int module_name_index = cw.newModule(mn);
attr.putShort(module_name_index);
// module_flags
Set<ModuleDescriptor.Modifier> modifiers = descriptor.modifiers();
int module_flags = 0;
if (modifiers.contains(ModuleDescriptor.Modifier.OPEN))
module_flags |= ACC_OPEN;
if (modifiers.contains(ModuleDescriptor.Modifier.SYNTHETIC))
module_flags |= ACC_SYNTHETIC;
if (modifiers.contains(ModuleDescriptor.Modifier.MANDATED))
module_flags |= ACC_MANDATED;
attr.putShort(module_flags);
// module_version
String vs = descriptor.rawVersion().orElse(null);
if (vs == null) {
attr.putShort(0);
} else {
int module_version_index = cw.newUTF8(vs);
attr.putShort(module_version_index);
}
// requires_count
attr.putShort(descriptor.requires().size());
// requires[requires_count]
for (Requires r : descriptor.requires()) {
int requires_index = cw.newModule(r.name());
attr.putShort(requires_index);
int requires_flags = 0;
if (r.modifiers().contains(Requires.Modifier.TRANSITIVE))
requires_flags |= ACC_TRANSITIVE;
if (r.modifiers().contains(Requires.Modifier.STATIC))
requires_flags |= ACC_STATIC_PHASE;
if (r.modifiers().contains(Requires.Modifier.SYNTHETIC))
requires_flags |= ACC_SYNTHETIC;
if (r.modifiers().contains(Requires.Modifier.MANDATED))
requires_flags |= ACC_MANDATED;
attr.putShort(requires_flags);
int requires_version_index;
vs = r.rawCompiledVersion().orElse(null);
if (vs == null) {
requires_version_index = 0;
} else {
requires_version_index = cw.newUTF8(vs);
}
attr.putShort(requires_version_index);
}
// exports_count and exports[exports_count];
attr.putShort(descriptor.exports().size());
for (Exports e : descriptor.exports()) {
String pkg = e.source().replace('.', '/');
attr.putShort(cw.newPackage(pkg));
int exports_flags = 0;
if (e.modifiers().contains(Exports.Modifier.SYNTHETIC))
exports_flags |= ACC_SYNTHETIC;
if (e.modifiers().contains(Exports.Modifier.MANDATED))
exports_flags |= ACC_MANDATED;
attr.putShort(exports_flags);
if (e.isQualified()) {
Set<String> ts = e.targets();
attr.putShort(ts.size());
ts.forEach(target -> attr.putShort(cw.newModule(target)));
} else {
attr.putShort(0);
}
}
// opens_counts and opens[opens_counts]
attr.putShort(descriptor.opens().size());
for (Opens obj : descriptor.opens()) {
String pkg = obj.source().replace('.', '/');
attr.putShort(cw.newPackage(pkg));
int opens_flags = 0;
if (obj.modifiers().contains(Opens.Modifier.SYNTHETIC))
opens_flags |= ACC_SYNTHETIC;
if (obj.modifiers().contains(Opens.Modifier.MANDATED))
opens_flags |= ACC_MANDATED;
attr.putShort(opens_flags);
if (obj.isQualified()) {
Set<String> ts = obj.targets();
attr.putShort(ts.size());
ts.forEach(target -> attr.putShort(cw.newModule(target)));
} else {
attr.putShort(0);
}
}
// uses_count and uses_index[uses_count]
if (descriptor.uses().isEmpty()) {
attr.putShort(0);
} else {
attr.putShort(descriptor.uses().size());
for (String s : descriptor.uses()) {
String service = s.replace('.', '/');
int index = cw.newClass(service);
attr.putShort(index);
}
}
// provides_count and provides[provides_count]
if (descriptor.provides().isEmpty()) {
attr.putShort(0);
} else {
attr.putShort(descriptor.provides().size());
for (Provides p : descriptor.provides()) {
String service = p.service().replace('.', '/');
attr.putShort(cw.newClass(service));
int with_count = p.providers().size();
attr.putShort(with_count);
for (String provider : p.providers()) {
attr.putShort(cw.newClass(provider.replace('.', '/')));
}
}
}
return attr;
}
}
/**
* ModulePackages attribute.
*
* <pre> {@code
*
* ModulePackages_attribute {
* // index to CONSTANT_utf8_info structure in constant pool representing
* // the string "ModulePackages"
* u2 attribute_name_index;
* u4 attribute_length;
*
* // the number of entries in the packages table
* u2 packages_count;
* { // index to CONSTANT_Package_info structure with the package name
* u2 package_index
* } packages[package_count];
*
* }</pre>
*/
public static class ModulePackagesAttribute extends Attribute {
private final Set<String> packages;
public ModulePackagesAttribute(Set<String> packages) {
super(MODULE_PACKAGES);
this.packages = packages;
}
public ModulePackagesAttribute() {
this(null);
}
@Override
protected Attribute read(ClassReader cr,
int off,
int len,
char[] buf,
int codeOff,
Label[] labels)
{
// package count
int package_count = cr.readUnsignedShort(off);
off += 2;
// packages
Set<String> packages = new HashSet<>();
for (int i=0; i<package_count; i++) {
String pkg = cr.readPackage(off, buf).replace('/', '.');
packages.add(pkg);
off += 2;
}
return new ModulePackagesAttribute(packages);
}
@Override
protected ByteVector write(ClassWriter cw,
byte[] code,
int len,
int maxStack,
int maxLocals)
{
assert packages != null;
ByteVector attr = new ByteVector();
// package_count
attr.putShort(packages.size());
// packages
packages.stream()
.map(p -> p.replace('.', '/'))
.forEach(p -> attr.putShort(cw.newPackage(p)));
return attr;
}
}
/**
* ModuleMainClass attribute.
*
* <pre> {@code
*
* MainClass_attribute {
* // index to CONSTANT_utf8_info structure in constant pool representing
* // the string "ModuleMainClass"
* u2 attribute_name_index;
* u4 attribute_length;
*
* // index to CONSTANT_Class_info structure with the main class name
* u2 main_class_index;
* }
*
* } </pre>
*/
public static class ModuleMainClassAttribute extends Attribute {
private final String mainClass;
public ModuleMainClassAttribute(String mainClass) {
super(MODULE_MAIN_CLASS);
this.mainClass = mainClass;
}
public ModuleMainClassAttribute() {
this(null);
}
@Override
protected Attribute read(ClassReader cr,
int off,
int len,
char[] buf,
int codeOff,
Label[] labels)
{
String value = cr.readClass(off, buf).replace('/', '.');
return new ModuleMainClassAttribute(value);
}
@Override
protected ByteVector write(ClassWriter cw,
byte[] code,
int len,
int maxStack,
int maxLocals)
{
ByteVector attr = new ByteVector();
int index = cw.newClass(mainClass.replace('.', '/'));
attr.putShort(index);
return attr;
}
}
/**
* ModuleTarget attribute.
*
* <pre> {@code
*
* TargetPlatform_attribute {
* // index to CONSTANT_utf8_info structure in constant pool representing
* // the string "ModuleTarget"
* u2 attribute_name_index;
* u4 attribute_length;
*
* // index to CONSTANT_utf8_info structure with the target platform
* u2 target_platform_index;
* }
*
* } </pre>
*/
public static class ModuleTargetAttribute extends Attribute {
private final String targetPlatform;
public ModuleTargetAttribute(String targetPlatform) {
super(MODULE_TARGET);
this.targetPlatform = targetPlatform;
}
public ModuleTargetAttribute() {
this(null);
}
public String targetPlatform() {
return targetPlatform;
}
@Override
protected Attribute read(ClassReader cr,
int off,
int len,
char[] buf,
int codeOff,
Label[] labels)
{
String targetPlatform = null;
int target_platform_index = cr.readUnsignedShort(off);
if (target_platform_index != 0)
targetPlatform = cr.readUTF8(off, buf);
off += 2;
return new ModuleTargetAttribute(targetPlatform);
}
@Override
protected ByteVector write(ClassWriter cw,
byte[] code,
int len,
int maxStack,
int maxLocals)
{
ByteVector attr = new ByteVector();
int target_platform_index = 0;
if (targetPlatform != null && targetPlatform.length() > 0)
target_platform_index = cw.newUTF8(targetPlatform);
attr.putShort(target_platform_index);
return attr;
}
}
/**
* ModuleHashes attribute.
*
* <pre> {@code
*
* ModuleHashes_attribute {
* // index to CONSTANT_utf8_info structure in constant pool representing
* // the string "ModuleHashes"
* u2 attribute_name_index;
* u4 attribute_length;
*
* // index to CONSTANT_utf8_info structure with algorithm name
* u2 algorithm_index;
*
* // the number of entries in the hashes table
* u2 hashes_count;
* { u2 module_name_index (index to CONSTANT_Module_info structure)
* u2 hash_length;
* u1 hash[hash_length];
* } hashes[hashes_count];
*
* } </pre>
*/
static class ModuleHashesAttribute extends Attribute {
private final ModuleHashes hashes;
ModuleHashesAttribute(ModuleHashes hashes) {
super(MODULE_HASHES);
this.hashes = hashes;
}
ModuleHashesAttribute() {
this(null);
}
@Override
protected Attribute read(ClassReader cr,
int off,
int len,
char[] buf,
int codeOff,
Label[] labels)
{
String algorithm = cr.readUTF8(off, buf);
off += 2;
int hashes_count = cr.readUnsignedShort(off);
off += 2;
Map<String, byte[]> map = new HashMap<>();
for (int i=0; i<hashes_count; i++) {
String mn = cr.readModule(off, buf);
off += 2;
int hash_length = cr.readUnsignedShort(off);
off += 2;
byte[] hash = new byte[hash_length];
for (int j=0; j<hash_length; j++) {
hash[j] = (byte) (0xff & cr.readByte(off+j));
}
off += hash_length;
map.put(mn, hash);
}
ModuleHashes hashes = new ModuleHashes(algorithm, map);
return new ModuleHashesAttribute(hashes);
}
@Override
protected ByteVector write(ClassWriter cw,
byte[] code,
int len,
int maxStack,
int maxLocals)
{
ByteVector attr = new ByteVector();
int index = cw.newUTF8(hashes.algorithm());
attr.putShort(index);
Set<String> names = hashes.names();
attr.putShort(names.size());
for (String mn : names) {
byte[] hash = hashes.hashFor(mn);
assert hash != null;
attr.putShort(cw.newModule(mn));
attr.putShort(hash.length);
for (byte b: hash) {
attr.putByte(b);
}
}
return attr;
}
}
/**
* ModuleResolution_attribute {
* u2 attribute_name_index; // "ModuleResolution"
* u4 attribute_length; // 2
* u2 resolution_flags;
*
* The value of the resolution_flags item is a mask of flags used to denote
* properties of module resolution. The flags are as follows:
*
* // Optional
* 0x0001 (DO_NOT_RESOLVE_BY_DEFAULT)
*
* // At most one of:
* 0x0002 (WARN_DEPRECATED)
* 0x0004 (WARN_DEPRECATED_FOR_REMOVAL)
* 0x0008 (WARN_INCUBATING)
*/
static class ModuleResolutionAttribute extends Attribute {
private final int value;
ModuleResolutionAttribute() {
super(MODULE_RESOLUTION);
value = 0;
}
ModuleResolutionAttribute(int value) {
super(MODULE_RESOLUTION);
this.value = value;
}
@Override
protected Attribute read(ClassReader cr,
int off,
int len,
char[] buf,
int codeOff,
Label[] labels)
{
int flags = cr.readUnsignedShort(off);
return new ModuleResolutionAttribute(flags);
}
@Override
protected ByteVector write(ClassWriter cw,
byte[] code,
int len,
int maxStack,
int maxLocals)
{
ByteVector attr = new ByteVector();
attr.putShort(value);
return attr;
}
}
}

View File

@ -31,18 +31,18 @@ import java.io.OutputStream;
import java.lang.module.ModuleDescriptor.Version;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import jdk.internal.org.objectweb.asm.Attribute;
import jdk.internal.org.objectweb.asm.ClassReader;
import jdk.internal.org.objectweb.asm.ClassVisitor;
import jdk.internal.org.objectweb.asm.ClassWriter;
import jdk.internal.org.objectweb.asm.ModuleVisitor;
import jdk.internal.org.objectweb.asm.Opcodes;
import static jdk.internal.module.ClassFileAttributes.*;
import jdk.internal.org.objectweb.asm.commons.ModuleHashesAttribute;
import jdk.internal.org.objectweb.asm.commons.ModuleResolutionAttribute;
import jdk.internal.org.objectweb.asm.commons.ModuleTargetAttribute;
/**
* Utility class to extend a module-info.class with additional attributes.
@ -132,43 +132,6 @@ public final class ModuleInfoExtender {
return this;
}
/**
* A ClassVisitor that supports adding class file attributes. If an
* attribute already exists then the first occurrence of the attribute
* is replaced.
*/
private static class AttributeAddingClassVisitor extends ClassVisitor {
private Map<String, Attribute> attrs = new HashMap<>();
AttributeAddingClassVisitor(int api, ClassVisitor cv) {
super(api, cv);
}
void addAttribute(Attribute attr) {
attrs.put(attr.type, attr);
}
@Override
public void visitAttribute(Attribute attr) {
String name = attr.type;
Attribute replacement = attrs.get(name);
if (replacement != null) {
attr = replacement;
attrs.remove(name);
}
super.visitAttribute(attr);
}
/**
* Adds any remaining attributes that weren't replaced to the
* class file.
*/
void finish() {
attrs.values().forEach(a -> super.visitAttribute(a));
attrs.clear();
}
}
/**
* Outputs the modified module-info.class to the given output stream.
* Once this method has been called then the Extender object should
@ -185,38 +148,86 @@ public final class ModuleInfoExtender {
* be discarded.
*/
public byte[] toByteArray() throws IOException {
ClassWriter cw
= new ClassWriter(ClassWriter.COMPUTE_MAXS + ClassWriter.COMPUTE_FRAMES);
AttributeAddingClassVisitor cv
= new AttributeAddingClassVisitor(Opcodes.ASM5, cw);
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS
+ ClassWriter.COMPUTE_FRAMES);
ClassReader cr = new ClassReader(in);
if (packages != null)
cv.addAttribute(new ModulePackagesAttribute(packages));
if (mainClass != null)
cv.addAttribute(new ModuleMainClassAttribute(mainClass));
if (targetPlatform != null)
cv.addAttribute(new ModuleTargetAttribute(targetPlatform));
if (hashes != null)
cv.addAttribute(new ModuleHashesAttribute(hashes));
if (moduleResolution != null)
cv.addAttribute(new ModuleResolutionAttribute(moduleResolution.value()));
ClassVisitor cv = new ClassVisitor(Opcodes.ASM6, cw) {
@Override
public ModuleVisitor visitModule(String name, int flags, String version) {
Version v = ModuleInfoExtender.this.version;
String vs = (v != null) ? v.toString() : version;
ModuleVisitor mv = super.visitModule(name, flags, vs);
// ModuleMainClass attribute
if (mainClass != null) {
mv.visitMainClass(mainClass.replace('.', '/'));
}
// ModulePackages attribute
if (packages != null) {
packages.forEach(pn -> mv.visitPackage(pn.replace('.', '/')));
}
return new ModuleVisitor(Opcodes.ASM6, mv) {
public void visitMainClass(String existingMainClass) {
// skip main class if there is a new value
if (mainClass == null) {
super.visitMainClass(existingMainClass);
}
}
public void visitPackage(String existingPackage) {
// skip packages if there is a new set of packages
if (packages == null) {
super.visitPackage(existingPackage);
}
}
};
}
@Override
public void visitAttribute(Attribute attr) {
String name = attr.type;
// drop existing attributes if there are replacements
if (name.equals(ClassFileConstants.MODULE_TARGET)
&& targetPlatform != null)
return;
if (name.equals(ClassFileConstants.MODULE_RESOLUTION)
&& moduleResolution != null)
return;
if (name.equals(ClassFileConstants.MODULE_HASHES)
&& hashes != null)
return;
super.visitAttribute(attr);
}
};
List<Attribute> attrs = new ArrayList<>();
// prototypes of attributes that should be parsed
attrs.add(new ModuleAttribute(version));
attrs.add(new ModulePackagesAttribute());
attrs.add(new ModuleMainClassAttribute());
attrs.add(new ModuleTargetAttribute());
attrs.add(new ModuleResolutionAttribute());
attrs.add(new ModuleHashesAttribute());
cr.accept(cv, attrs.toArray(new Attribute[0]), 0);
// add any attributes that didn't replace previous attributes
cv.finish();
// add ModuleTarget, ModuleResolution and ModuleHashes attributes
if (targetPlatform != null) {
cw.visitAttribute(new ModuleTargetAttribute(targetPlatform));
}
if (moduleResolution != null) {
int flags = moduleResolution.value();
cw.visitAttribute(new ModuleResolutionAttribute(flags));
}
if (hashes != null) {
String algorithm = hashes.algorithm();
List<String> names = new ArrayList<>();
List<byte[]> values = new ArrayList<>();
for (String name : hashes.names()) {
names.add(name);
values.add(hashes.hashFor(name));
}
cw.visitAttribute(new ModuleHashesAttribute(algorithm, names, values));
}
return cw.toByteArray();
}

View File

@ -28,13 +28,14 @@ import java.io.IOException;
import java.io.OutputStream;
import java.lang.module.ModuleDescriptor;
import java.nio.ByteBuffer;
import java.util.Map;
import java.util.stream.Stream;
import jdk.internal.org.objectweb.asm.ClassWriter;
import jdk.internal.org.objectweb.asm.ModuleVisitor;
import jdk.internal.org.objectweb.asm.Opcodes;
import static jdk.internal.module.ClassFileAttributes.*;
import static jdk.internal.module.ClassFileConstants.ACC_MODULE;
import jdk.internal.org.objectweb.asm.commons.ModuleTargetAttribute;
import static jdk.internal.org.objectweb.asm.Opcodes.*;
/**
* Utility class to write a ModuleDescriptor as a module-info.class.
@ -42,6 +43,35 @@ import static jdk.internal.module.ClassFileConstants.ACC_MODULE;
public final class ModuleInfoWriter {
private static final Map<ModuleDescriptor.Modifier, Integer>
MODULE_MODS_TO_FLAGS = Map.of(
ModuleDescriptor.Modifier.OPEN, ACC_OPEN,
ModuleDescriptor.Modifier.SYNTHETIC, ACC_SYNTHETIC,
ModuleDescriptor.Modifier.MANDATED, ACC_MANDATED
);
private static final Map<ModuleDescriptor.Requires.Modifier, Integer>
REQUIRES_MODS_TO_FLAGS = Map.of(
ModuleDescriptor.Requires.Modifier.TRANSITIVE, ACC_TRANSITIVE,
ModuleDescriptor.Requires.Modifier.STATIC, ACC_STATIC_PHASE,
ModuleDescriptor.Requires.Modifier.SYNTHETIC, ACC_SYNTHETIC,
ModuleDescriptor.Requires.Modifier.MANDATED, ACC_MANDATED
);
private static final Map<ModuleDescriptor.Exports.Modifier, Integer>
EXPORTS_MODS_TO_FLAGS = Map.of(
ModuleDescriptor.Exports.Modifier.SYNTHETIC, ACC_SYNTHETIC,
ModuleDescriptor.Exports.Modifier.MANDATED, ACC_MANDATED
);
private static final Map<ModuleDescriptor.Opens.Modifier, Integer>
OPENS_MODS_TO_FLAGS = Map.of(
ModuleDescriptor.Opens.Modifier.SYNTHETIC, ACC_SYNTHETIC,
ModuleDescriptor.Opens.Modifier.MANDATED, ACC_MANDATED
);
private static final String[] EMPTY_STRING_ARRAY = new String[0];
private ModuleInfoWriter() { }
/**
@ -50,24 +80,75 @@ public final class ModuleInfoWriter {
*/
private static byte[] toModuleInfo(ModuleDescriptor md, ModuleTarget target) {
ClassWriter cw = new ClassWriter(0);
cw.visit(Opcodes.V1_9, ACC_MODULE, "module-info", null, null, null);
cw.visitAttribute(new ModuleAttribute(md));
cw.visit(Opcodes.V9, ACC_MODULE, "module-info", null, null, null);
// for tests: write the ModulePackages attribute when there are packages
// that aren't exported or open
int moduleFlags = md.modifiers().stream()
.map(MODULE_MODS_TO_FLAGS::get)
.reduce(0, (x, y) -> (x | y));
String vs = md.rawVersion().orElse(null);
ModuleVisitor mv = cw.visitModule(md.name(), moduleFlags, vs);
// requires
for (ModuleDescriptor.Requires r : md.requires()) {
int flags = r.modifiers().stream()
.map(REQUIRES_MODS_TO_FLAGS::get)
.reduce(0, (x, y) -> (x | y));
vs = r.rawCompiledVersion().orElse(null);
mv.visitRequire(r.name(), flags, vs);
}
// exports
for (ModuleDescriptor.Exports e : md.exports()) {
int flags = e.modifiers().stream()
.map(EXPORTS_MODS_TO_FLAGS::get)
.reduce(0, (x, y) -> (x | y));
String[] targets = e.targets().toArray(EMPTY_STRING_ARRAY);
mv.visitExport(e.source().replace('.', '/'), flags, targets);
}
// opens
for (ModuleDescriptor.Opens opens : md.opens()) {
int flags = opens.modifiers().stream()
.map(OPENS_MODS_TO_FLAGS::get)
.reduce(0, (x, y) -> (x | y));
String[] targets = opens.targets().toArray(EMPTY_STRING_ARRAY);
mv.visitOpen(opens.source().replace('.', '/'), flags, targets);
}
// uses
md.uses().stream().map(sn -> sn.replace('.', '/')).forEach(mv::visitUse);
// provides
for (ModuleDescriptor.Provides p : md.provides()) {
mv.visitProvide(p.service().replace('.', '/'),
p.providers()
.stream()
.map(pn -> pn.replace('.', '/'))
.toArray(String[]::new));
}
// add the ModulePackages attribute when there are packages that aren't
// exported or open
Stream<String> exported = md.exports().stream()
.map(ModuleDescriptor.Exports::source);
Stream<String> open = md.opens().stream()
.map(ModuleDescriptor.Opens::source);
long exportedOrOpen = Stream.concat(exported, open).distinct().count();
if (md.packages().size() > exportedOrOpen)
cw.visitAttribute(new ModulePackagesAttribute(md.packages()));
if (md.packages().size() > exportedOrOpen) {
md.packages().stream()
.map(pn -> pn.replace('.', '/'))
.forEach(mv::visitPackage);
}
// write ModuleMainClass if the module has a main class
md.mainClass().ifPresent(mc -> cw.visitAttribute(new ModuleMainClassAttribute(mc)));
// ModuleMainClass attribute
md.mainClass()
.map(mc -> mc.replace('.', '/'))
.ifPresent(mv::visitMainClass);
// write ModuleTarget if there is a target platform
if (target != null) {
mv.visitEnd();
// write ModuleTarget attribute if there is a target platform
if (target != null && target.targetPlatform().length() > 0) {
cw.visitAttribute(new ModuleTargetAttribute(target.targetPlatform()));
}

View File

@ -70,7 +70,7 @@ public abstract class AnnotationVisitor {
/**
* The ASM API version implemented by this visitor. The value of this field
* must be one of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
* must be one of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
*/
protected final int api;
@ -85,7 +85,7 @@ public abstract class AnnotationVisitor {
*
* @param api
* the ASM API version implemented by this visitor. Must be one
* of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
* of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
*/
public AnnotationVisitor(final int api) {
this(api, null);
@ -96,13 +96,13 @@ public abstract class AnnotationVisitor {
*
* @param api
* the ASM API version implemented by this visitor. Must be one
* of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
* of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
* @param av
* the annotation visitor to which this visitor must delegate
* method calls. May be null.
*/
public AnnotationVisitor(final int api, final AnnotationVisitor av) {
if (api != Opcodes.ASM4 && api != Opcodes.ASM5) {
if (api < Opcodes.ASM4 || api > Opcodes.ASM6) {
throw new IllegalArgumentException();
}
this.api = api;
@ -118,7 +118,7 @@ public abstract class AnnotationVisitor {
* the actual value, whose type must be {@link Byte},
* {@link Boolean}, {@link Character}, {@link Short},
* {@link Integer} , {@link Long}, {@link Float}, {@link Double},
* {@link String} or {@link Type} or OBJECT or ARRAY sort. This
* {@link String} or {@link Type} of OBJECT or ARRAY sort. This
* value can also be an array of byte, boolean, short, char, int,
* long, float or double values (this is equivalent to using
* {@link #visitArray visitArray} and visiting each array element

View File

@ -133,7 +133,7 @@ final class AnnotationWriter extends AnnotationVisitor {
*/
AnnotationWriter(final ClassWriter cw, final boolean named,
final ByteVector bv, final ByteVector parent, final int offset) {
super(Opcodes.ASM5);
super(Opcodes.ASM6);
this.cw = cw;
this.named = named;
this.bv = bv;

View File

@ -72,31 +72,6 @@ import java.io.InputStream;
*/
public class ClassReader {
/**
* True to enable signatures support.
*/
static final boolean SIGNATURES = true;
/**
* True to enable annotations support.
*/
static final boolean ANNOTATIONS = true;
/**
* True to enable stack map frames support.
*/
static final boolean FRAMES = true;
/**
* True to enable bytecode writing support.
*/
static final boolean WRITER = true;
/**
* True to enable JSR_W and GOTO_W support.
*/
static final boolean RESIZE = true;
/**
* Flag to skip method code. If this class is set <code>CODE</code>
* attribute won't be visited. This can be used, for example, to retrieve
@ -133,6 +108,21 @@ public class ClassReader {
*/
public static final int EXPAND_FRAMES = 8;
/**
* Flag to expand the ASM pseudo instructions into an equivalent sequence of
* standard bytecode instructions. When resolving a forward jump it may
* happen that the signed 2 bytes offset reserved for it is not sufficient
* to store the bytecode offset. In this case the jump instruction is
* replaced with a temporary ASM pseudo instruction using an unsigned 2
* bytes offset (see Label#resolve). This internal flag is used to re-read
* classes containing such instructions, in order to replace them with
* standard instructions. In addition, when this flag is used, GOTO_W and
* JSR_W are <i>not</i> converted into GOTO and JSR, to make sure that
* infinite loops where a GOTO_W is replaced with a GOTO in ClassReader and
* converted back to a GOTO_W in ClassWriter cannot occur.
*/
static final int EXPAND_ASM_INSNS = 256;
/**
* The class to be parsed. <i>The content of this array must not be
* modified. This field is intended for {@link Attribute} sub classes, and
@ -195,7 +185,7 @@ public class ClassReader {
public ClassReader(final byte[] b, final int off, final int len) {
this.b = b;
// checks the class version
if (readShort(off + 6) > Opcodes.V1_9) {
if (readShort(off + 6) > Opcodes.V9) {
throw new IllegalArgumentException();
}
// parses the constant pool
@ -234,6 +224,8 @@ public class ClassReader {
// case ClassWriter.CLASS:
// case ClassWriter.STR:
// case ClassWriter.MTYPE
// case ClassWriter.PACKAGE:
// case ClassWriter.MODULE:
default:
size = 3;
break;
@ -377,7 +369,9 @@ public class ClassReader {
break;
// case ClassWriter.STR:
// case ClassWriter.CLASS:
// case ClassWriter.MTYPE
// case ClassWriter.MTYPE:
// case ClassWriter.MODULE:
// case ClassWriter.PACKAGE:
default:
item.set(tag, readUTF8(index, buf), null, null);
break;
@ -584,11 +578,14 @@ public class ClassReader {
String enclosingOwner = null;
String enclosingName = null;
String enclosingDesc = null;
String moduleMainClass = null;
int anns = 0;
int ianns = 0;
int tanns = 0;
int itanns = 0;
int innerClasses = 0;
int module = 0;
int packages = 0;
Attribute attributes = null;
u = getAttributes();
@ -607,13 +604,11 @@ public class ClassReader {
enclosingName = readUTF8(items[item], c);
enclosingDesc = readUTF8(items[item] + 2, c);
}
} else if (SIGNATURES && "Signature".equals(attrName)) {
} else if ("Signature".equals(attrName)) {
signature = readUTF8(u + 8, c);
} else if (ANNOTATIONS
&& "RuntimeVisibleAnnotations".equals(attrName)) {
} else if ("RuntimeVisibleAnnotations".equals(attrName)) {
anns = u + 8;
} else if (ANNOTATIONS
&& "RuntimeVisibleTypeAnnotations".equals(attrName)) {
} else if ("RuntimeVisibleTypeAnnotations".equals(attrName)) {
tanns = u + 8;
} else if ("Deprecated".equals(attrName)) {
access |= Opcodes.ACC_DEPRECATED;
@ -623,12 +618,16 @@ public class ClassReader {
} else if ("SourceDebugExtension".equals(attrName)) {
int len = readInt(u + 4);
sourceDebug = readUTF(u + 8, len, new char[len]);
} else if (ANNOTATIONS
&& "RuntimeInvisibleAnnotations".equals(attrName)) {
} else if ("RuntimeInvisibleAnnotations".equals(attrName)) {
ianns = u + 8;
} else if (ANNOTATIONS
&& "RuntimeInvisibleTypeAnnotations".equals(attrName)) {
} else if ("RuntimeInvisibleTypeAnnotations".equals(attrName)) {
itanns = u + 8;
} else if ("Module".equals(attrName)) {
module = u + 8;
} else if ("ModuleMainClass".equals(attrName)) {
moduleMainClass = readClass(u + 8, c);
} else if ("ModulePackages".equals(attrName)) {
packages = u + 10;
} else if ("BootstrapMethods".equals(attrName)) {
int[] bootstrapMethods = new int[readUnsignedShort(u + 8)];
for (int j = 0, v = u + 10; j < bootstrapMethods.length; j++) {
@ -657,6 +656,12 @@ public class ClassReader {
classVisitor.visitSource(sourceFile, sourceDebug);
}
// visits the module info and associated attributes
if (module != 0) {
readModule(classVisitor, context, module,
moduleMainClass, packages);
}
// visits the outer class
if (enclosingOwner != null) {
classVisitor.visitOuterClass(enclosingOwner, enclosingName,
@ -664,19 +669,19 @@ public class ClassReader {
}
// visits the class annotations and type annotations
if (ANNOTATIONS && anns != 0) {
if (anns != 0) {
for (int i = readUnsignedShort(anns), v = anns + 2; i > 0; --i) {
v = readAnnotationValues(v + 2, c, true,
classVisitor.visitAnnotation(readUTF8(v, c), true));
}
}
if (ANNOTATIONS && ianns != 0) {
if (ianns != 0) {
for (int i = readUnsignedShort(ianns), v = ianns + 2; i > 0; --i) {
v = readAnnotationValues(v + 2, c, true,
classVisitor.visitAnnotation(readUTF8(v, c), false));
}
}
if (ANNOTATIONS && tanns != 0) {
if (tanns != 0) {
for (int i = readUnsignedShort(tanns), v = tanns + 2; i > 0; --i) {
v = readAnnotationTarget(context, v);
v = readAnnotationValues(v + 2, c, true,
@ -684,7 +689,7 @@ public class ClassReader {
context.typePath, readUTF8(v, c), true));
}
}
if (ANNOTATIONS && itanns != 0) {
if (itanns != 0) {
for (int i = readUnsignedShort(itanns), v = itanns + 2; i > 0; --i) {
v = readAnnotationTarget(context, v);
v = readAnnotationValues(v + 2, c, true,
@ -726,6 +731,120 @@ public class ClassReader {
classVisitor.visitEnd();
}
/**
* Reads the module attribute and visit it.
*
* @param classVisitor
* the current class visitor
* @param context
* information about the class being parsed.
* @param u
* start offset of the module attribute in the class file.
* @param mainClass
* name of the main class of a module or null.
* @param packages
* start offset of the concealed package attribute.
*/
private void readModule(final ClassVisitor classVisitor,
final Context context, int u,
final String mainClass, int packages) {
char[] buffer = context.buffer;
// reads module name, flags and version
String name = readModule(u, buffer);
int flags = readUnsignedShort(u + 2);
String version = readUTF8(u + 4, buffer);
u += 6;
ModuleVisitor mv = classVisitor.visitModule(name, flags, version);
if (mv == null) {
return;
}
// module attributes (main class, packages)
if (mainClass != null) {
mv.visitMainClass(mainClass);
}
if (packages != 0) {
for (int i = readUnsignedShort(packages - 2); i > 0; --i) {
String packaze = readPackage(packages, buffer);
mv.visitPackage(packaze);
packages += 2;
}
}
// reads requires
u += 2;
for (int i = readUnsignedShort(u - 2); i > 0; --i) {
String module = readModule(u, buffer);
int access = readUnsignedShort(u + 2);
String requireVersion = readUTF8(u + 4, buffer);
mv.visitRequire(module, access, requireVersion);
u += 6;
}
// reads exports
u += 2;
for (int i = readUnsignedShort(u - 2); i > 0; --i) {
String export = readPackage(u, buffer);
int access = readUnsignedShort(u + 2);
int exportToCount = readUnsignedShort(u + 4);
u += 6;
String[] tos = null;
if (exportToCount != 0) {
tos = new String[exportToCount];
for (int j = 0; j < tos.length; ++j) {
tos[j] = readModule(u, buffer);
u += 2;
}
}
mv.visitExport(export, access, tos);
}
// reads opens
u += 2;
for (int i = readUnsignedShort(u - 2); i > 0; --i) {
String open = readPackage(u, buffer);
int access = readUnsignedShort(u + 2);
int openToCount = readUnsignedShort(u + 4);
u += 6;
String[] tos = null;
if (openToCount != 0) {
tos = new String[openToCount];
for (int j = 0; j < tos.length; ++j) {
tos[j] = readModule(u, buffer);
u += 2;
}
}
mv.visitOpen(open, access, tos);
}
// read uses
u += 2;
for (int i = readUnsignedShort(u - 2); i > 0; --i) {
mv.visitUse(readClass(u, buffer));
u += 2;
}
// read provides
u += 2;
for (int i = readUnsignedShort(u - 2); i > 0; --i) {
String service = readClass(u, buffer);
int provideWithCount = readUnsignedShort(u + 2);
u += 4;
String[] withs = new String[provideWithCount];
for (int j = 0; j < withs.length; ++j) {
withs[j] = readClass(u, buffer);
u += 2;
}
mv.visitProvide(service, withs);
}
mv.visitEnd();
}
/**
* Reads a field and makes the given visitor visit it.
*
@ -762,24 +881,20 @@ public class ClassReader {
if ("ConstantValue".equals(attrName)) {
int item = readUnsignedShort(u + 8);
value = item == 0 ? null : readConst(item, c);
} else if (SIGNATURES && "Signature".equals(attrName)) {
} else if ("Signature".equals(attrName)) {
signature = readUTF8(u + 8, c);
} else if ("Deprecated".equals(attrName)) {
access |= Opcodes.ACC_DEPRECATED;
} else if ("Synthetic".equals(attrName)) {
access |= Opcodes.ACC_SYNTHETIC
| ClassWriter.ACC_SYNTHETIC_ATTRIBUTE;
} else if (ANNOTATIONS
&& "RuntimeVisibleAnnotations".equals(attrName)) {
} else if ("RuntimeVisibleAnnotations".equals(attrName)) {
anns = u + 8;
} else if (ANNOTATIONS
&& "RuntimeVisibleTypeAnnotations".equals(attrName)) {
} else if ("RuntimeVisibleTypeAnnotations".equals(attrName)) {
tanns = u + 8;
} else if (ANNOTATIONS
&& "RuntimeInvisibleAnnotations".equals(attrName)) {
} else if ("RuntimeInvisibleAnnotations".equals(attrName)) {
ianns = u + 8;
} else if (ANNOTATIONS
&& "RuntimeInvisibleTypeAnnotations".equals(attrName)) {
} else if ("RuntimeInvisibleTypeAnnotations".equals(attrName)) {
itanns = u + 8;
} else {
Attribute attr = readAttribute(context.attrs, attrName, u + 8,
@ -801,19 +916,19 @@ public class ClassReader {
}
// visits the field annotations and type annotations
if (ANNOTATIONS && anns != 0) {
if (anns != 0) {
for (int i = readUnsignedShort(anns), v = anns + 2; i > 0; --i) {
v = readAnnotationValues(v + 2, c, true,
fv.visitAnnotation(readUTF8(v, c), true));
}
}
if (ANNOTATIONS && ianns != 0) {
if (ianns != 0) {
for (int i = readUnsignedShort(ianns), v = ianns + 2; i > 0; --i) {
v = readAnnotationValues(v + 2, c, true,
fv.visitAnnotation(readUTF8(v, c), false));
}
}
if (ANNOTATIONS && tanns != 0) {
if (tanns != 0) {
for (int i = readUnsignedShort(tanns), v = tanns + 2; i > 0; --i) {
v = readAnnotationTarget(context, v);
v = readAnnotationValues(v + 2, c, true,
@ -821,7 +936,7 @@ public class ClassReader {
context.typePath, readUTF8(v, c), true));
}
}
if (ANNOTATIONS && itanns != 0) {
if (itanns != 0) {
for (int i = readUnsignedShort(itanns), v = itanns + 2; i > 0; --i) {
v = readAnnotationTarget(context, v);
v = readAnnotationValues(v + 2, c, true,
@ -895,32 +1010,26 @@ public class ClassReader {
exceptions[j] = readClass(exception, c);
exception += 2;
}
} else if (SIGNATURES && "Signature".equals(attrName)) {
} else if ("Signature".equals(attrName)) {
signature = readUTF8(u + 8, c);
} else if ("Deprecated".equals(attrName)) {
context.access |= Opcodes.ACC_DEPRECATED;
} else if (ANNOTATIONS
&& "RuntimeVisibleAnnotations".equals(attrName)) {
} else if ("RuntimeVisibleAnnotations".equals(attrName)) {
anns = u + 8;
} else if (ANNOTATIONS
&& "RuntimeVisibleTypeAnnotations".equals(attrName)) {
} else if ("RuntimeVisibleTypeAnnotations".equals(attrName)) {
tanns = u + 8;
} else if (ANNOTATIONS && "AnnotationDefault".equals(attrName)) {
} else if ("AnnotationDefault".equals(attrName)) {
dann = u + 8;
} else if ("Synthetic".equals(attrName)) {
context.access |= Opcodes.ACC_SYNTHETIC
| ClassWriter.ACC_SYNTHETIC_ATTRIBUTE;
} else if (ANNOTATIONS
&& "RuntimeInvisibleAnnotations".equals(attrName)) {
} else if ("RuntimeInvisibleAnnotations".equals(attrName)) {
ianns = u + 8;
} else if (ANNOTATIONS
&& "RuntimeInvisibleTypeAnnotations".equals(attrName)) {
} else if ("RuntimeInvisibleTypeAnnotations".equals(attrName)) {
itanns = u + 8;
} else if (ANNOTATIONS
&& "RuntimeVisibleParameterAnnotations".equals(attrName)) {
} else if ("RuntimeVisibleParameterAnnotations".equals(attrName)) {
mpanns = u + 8;
} else if (ANNOTATIONS
&& "RuntimeInvisibleParameterAnnotations".equals(attrName)) {
} else if ("RuntimeInvisibleParameterAnnotations".equals(attrName)) {
impanns = u + 8;
} else if ("MethodParameters".equals(attrName)) {
methodParameters = u + 8;
@ -953,7 +1062,7 @@ public class ClassReader {
* access, name and descriptor can have been changed, this is not
* important since they are not copied as is from the reader).
*/
if (WRITER && mv instanceof MethodWriter) {
if (mv instanceof MethodWriter) {
MethodWriter mw = (MethodWriter) mv;
if (mw.cw.cr == this && signature == mw.signature) {
boolean sameExceptions = false;
@ -990,26 +1099,26 @@ public class ClassReader {
}
// visits the method annotations
if (ANNOTATIONS && dann != 0) {
if (dann != 0) {
AnnotationVisitor dv = mv.visitAnnotationDefault();
readAnnotationValue(dann, c, null, dv);
if (dv != null) {
dv.visitEnd();
}
}
if (ANNOTATIONS && anns != 0) {
if (anns != 0) {
for (int i = readUnsignedShort(anns), v = anns + 2; i > 0; --i) {
v = readAnnotationValues(v + 2, c, true,
mv.visitAnnotation(readUTF8(v, c), true));
}
}
if (ANNOTATIONS && ianns != 0) {
if (ianns != 0) {
for (int i = readUnsignedShort(ianns), v = ianns + 2; i > 0; --i) {
v = readAnnotationValues(v + 2, c, true,
mv.visitAnnotation(readUTF8(v, c), false));
}
}
if (ANNOTATIONS && tanns != 0) {
if (tanns != 0) {
for (int i = readUnsignedShort(tanns), v = tanns + 2; i > 0; --i) {
v = readAnnotationTarget(context, v);
v = readAnnotationValues(v + 2, c, true,
@ -1017,7 +1126,7 @@ public class ClassReader {
context.typePath, readUTF8(v, c), true));
}
}
if (ANNOTATIONS && itanns != 0) {
if (itanns != 0) {
for (int i = readUnsignedShort(itanns), v = itanns + 2; i > 0; --i) {
v = readAnnotationTarget(context, v);
v = readAnnotationValues(v + 2, c, true,
@ -1025,10 +1134,10 @@ public class ClassReader {
context.typePath, readUTF8(v, c), false));
}
}
if (ANNOTATIONS && mpanns != 0) {
if (mpanns != 0) {
readParameterAnnotations(mv, context, mpanns, true);
}
if (ANNOTATIONS && impanns != 0) {
if (impanns != 0) {
readParameterAnnotations(mv, context, impanns, false);
}
@ -1075,7 +1184,7 @@ public class ClassReader {
int codeStart = u;
int codeEnd = u + codeLength;
Label[] labels = context.labels = new Label[codeLength + 2];
readLabel(codeLength + 1, labels);
createLabel(codeLength + 1, labels);
while (u < codeEnd) {
int offset = u - codeStart;
int opcode = b[u] & 0xFF;
@ -1085,11 +1194,16 @@ public class ClassReader {
u += 1;
break;
case ClassWriter.LABEL_INSN:
readLabel(offset + readShort(u + 1), labels);
createLabel(offset + readShort(u + 1), labels);
u += 3;
break;
case ClassWriter.ASM_LABEL_INSN:
createLabel(offset + readUnsignedShort(u + 1), labels);
u += 3;
break;
case ClassWriter.LABELW_INSN:
readLabel(offset + readInt(u + 1), labels);
case ClassWriter.ASM_LABELW_INSN:
createLabel(offset + readInt(u + 1), labels);
u += 5;
break;
case ClassWriter.WIDE_INSN:
@ -1104,9 +1218,9 @@ public class ClassReader {
// skips 0 to 3 padding bytes
u = u + 4 - (offset & 3);
// reads instruction
readLabel(offset + readInt(u), labels);
createLabel(offset + readInt(u), labels);
for (int i = readInt(u + 8) - readInt(u + 4) + 1; i > 0; --i) {
readLabel(offset + readInt(u + 12), labels);
createLabel(offset + readInt(u + 12), labels);
u += 4;
}
u += 12;
@ -1115,9 +1229,9 @@ public class ClassReader {
// skips 0 to 3 padding bytes
u = u + 4 - (offset & 3);
// reads instruction
readLabel(offset + readInt(u), labels);
createLabel(offset + readInt(u), labels);
for (int i = readInt(u + 4); i > 0; --i) {
readLabel(offset + readInt(u + 12), labels);
createLabel(offset + readInt(u + 12), labels);
u += 8;
}
u += 8;
@ -1147,9 +1261,9 @@ public class ClassReader {
// reads the try catch entries to find the labels, and also visits them
for (int i = readUnsignedShort(u); i > 0; --i) {
Label start = readLabel(readUnsignedShort(u + 2), labels);
Label end = readLabel(readUnsignedShort(u + 4), labels);
Label handler = readLabel(readUnsignedShort(u + 6), labels);
Label start = createLabel(readUnsignedShort(u + 2), labels);
Label end = createLabel(readUnsignedShort(u + 4), labels);
Label handler = createLabel(readUnsignedShort(u + 6), labels);
String type = readUTF8(items[readUnsignedShort(u + 8)], c);
mv.visitTryCatchBlock(start, end, handler, type);
u += 8;
@ -1180,13 +1294,9 @@ public class ClassReader {
varTable = u + 8;
for (int j = readUnsignedShort(u + 8), v = u; j > 0; --j) {
int label = readUnsignedShort(v + 10);
if (labels[label] == null) {
readLabel(label, labels).status |= Label.DEBUG;
}
createDebugLabel(label, labels);
label += readUnsignedShort(v + 12);
if (labels[label] == null) {
readLabel(label, labels).status |= Label.DEBUG;
}
createDebugLabel(label, labels);
v += 10;
}
}
@ -1196,9 +1306,7 @@ public class ClassReader {
if ((context.flags & SKIP_DEBUG) == 0) {
for (int j = readUnsignedShort(u + 8), v = u; j > 0; --j) {
int label = readUnsignedShort(v + 10);
if (labels[label] == null) {
readLabel(label, labels).status |= Label.DEBUG;
}
createDebugLabel(label, labels);
Label l = labels[label];
while (l.line > 0) {
if (l.next == null) {
@ -1210,17 +1318,15 @@ public class ClassReader {
v += 4;
}
}
} else if (ANNOTATIONS
&& "RuntimeVisibleTypeAnnotations".equals(attrName)) {
} else if ("RuntimeVisibleTypeAnnotations".equals(attrName)) {
tanns = readTypeAnnotations(mv, context, u + 8, true);
ntoff = tanns.length == 0 || readByte(tanns[0]) < 0x43 ? -1
: readUnsignedShort(tanns[0] + 1);
} else if (ANNOTATIONS
&& "RuntimeInvisibleTypeAnnotations".equals(attrName)) {
} else if ("RuntimeInvisibleTypeAnnotations".equals(attrName)) {
itanns = readTypeAnnotations(mv, context, u + 8, false);
nitoff = itanns.length == 0 || readByte(itanns[0]) < 0x43 ? -1
: readUnsignedShort(itanns[0] + 1);
} else if (FRAMES && "StackMapTable".equals(attrName)) {
} else if ("StackMapTable".equals(attrName)) {
if ((context.flags & SKIP_FRAMES) == 0) {
stackMap = u + 10;
stackMapSize = readInt(u + 4);
@ -1244,7 +1350,7 @@ public class ClassReader {
* this by parsing the stack map table without a full decoding
* (see below).
*/
} else if (FRAMES && "StackMap".equals(attrName)) {
} else if ("StackMap".equals(attrName)) {
if ((context.flags & SKIP_FRAMES) == 0) {
zip = false;
stackMap = u + 10;
@ -1273,7 +1379,7 @@ public class ClassReader {
u += 2;
// generates the first (implicit) stack map frame
if (FRAMES && stackMap != 0) {
if (stackMap != 0) {
/*
* for the first explicit frame the offset is not offset_delta + 1
* but only offset_delta; setting the implicit frame offset to -1
@ -1306,14 +1412,31 @@ public class ClassReader {
int v = readUnsignedShort(i + 1);
if (v >= 0 && v < codeLength) {
if ((b[codeStart + v] & 0xFF) == Opcodes.NEW) {
readLabel(v, labels);
createLabel(v, labels);
}
}
}
}
}
if ((context.flags & EXPAND_ASM_INSNS) != 0
&& (context.flags & EXPAND_FRAMES) != 0) {
// Expanding the ASM pseudo instructions can introduce F_INSERT
// frames, even if the method does not currently have any frame.
// Also these inserted frames must be computed by simulating the
// effect of the bytecode instructions one by one, starting from the
// first one and the last existing frame (or the implicit first
// one). Finally, due to the way MethodWriter computes this (with
// the compute = INSERTED_FRAMES option), MethodWriter needs to know
// maxLocals before the first instruction is visited. For all these
// reasons we always visit the implicit first frame in this case
// (passing only maxLocals - the rest can be and is computed in
// MethodWriter).
mv.visitFrame(Opcodes.F_NEW, maxLocals, null, 0, null);
}
// visits the instructions
int opcodeDelta = (context.flags & EXPAND_ASM_INSNS) == 0 ? -33 : 0;
boolean insertFrame = false;
u = codeStart;
while (u < codeEnd) {
int offset = u - codeStart;
@ -1334,7 +1457,7 @@ public class ClassReader {
}
// visits the frame for this offset, if any
while (FRAMES && frame != null
while (frame != null
&& (frame.offset == offset || frame.offset == -1)) {
// if there is a frame for this offset, makes the visitor visit
// it, and reads the next frame if there is one.
@ -1346,6 +1469,9 @@ public class ClassReader {
mv.visitFrame(frame.mode, frame.localDiff, frame.local,
frame.stackCount, frame.stack);
}
// if there is already a frame for this offset, there is no
// need to insert a new one.
insertFrame = false;
}
if (frameCount > 0) {
stackMap = readFrame(stackMap, zip, unzip, frame);
@ -1354,6 +1480,13 @@ public class ClassReader {
frame = null;
}
}
// inserts a frame for this offset, if requested by setting
// insertFrame to true during the previous iteration. The actual
// frame content will be computed in MethodWriter.
if (insertFrame) {
mv.visitFrame(ClassWriter.F_INSERT, 0, null, 0, null);
insertFrame = false;
}
// visits the instruction at this offset
int opcode = b[u] & 0xFF;
@ -1378,9 +1511,47 @@ public class ClassReader {
u += 3;
break;
case ClassWriter.LABELW_INSN:
mv.visitJumpInsn(opcode - 33, labels[offset + readInt(u + 1)]);
mv.visitJumpInsn(opcode + opcodeDelta, labels[offset
+ readInt(u + 1)]);
u += 5;
break;
case ClassWriter.ASM_LABEL_INSN: {
// changes temporary opcodes 202 to 217 (inclusive), 218
// and 219 to IFEQ ... JSR (inclusive), IFNULL and
// IFNONNULL
opcode = opcode < 218 ? opcode - 49 : opcode - 20;
Label target = labels[offset + readUnsignedShort(u + 1)];
// replaces GOTO with GOTO_W, JSR with JSR_W and IFxxx
// <l> with IFNOTxxx <L> GOTO_W <l> L:..., where IFNOTxxx is
// the "opposite" opcode of IFxxx (i.e., IFNE for IFEQ)
// and where <L> designates the instruction just after
// the GOTO_W.
if (opcode == Opcodes.GOTO || opcode == Opcodes.JSR) {
mv.visitJumpInsn(opcode + 33, target);
} else {
opcode = opcode <= 166 ? ((opcode + 1) ^ 1) - 1
: opcode ^ 1;
Label endif = createLabel(offset + 3, labels);
mv.visitJumpInsn(opcode, endif);
mv.visitJumpInsn(200, target); // GOTO_W
// endif designates the instruction just after GOTO_W,
// and is visited as part of the next instruction. Since
// it is a jump target, we need to insert a frame here.
insertFrame = true;
}
u += 3;
break;
}
case ClassWriter.ASM_LABELW_INSN: {
// replaces the pseudo GOTO_W instruction with a real one.
mv.visitJumpInsn(200, labels[offset + readInt(u + 1)]);
// The instruction just after is a jump target (because pseudo
// GOTO_W are used in patterns IFNOTxxx <L> GOTO_W <l> L:...,
// see MethodWriter), so we need to insert a frame here.
insertFrame = true;
u += 5;
break;
}
case ClassWriter.WIDE_INSN:
opcode = b[u + 1] & 0xFF;
if (opcode == Opcodes.IINC) {
@ -1636,8 +1807,8 @@ public class ClassReader {
for (int j = readUnsignedShort(u + 1); j > 0; --j) {
int start = readUnsignedShort(u + 3);
int length = readUnsignedShort(u + 5);
readLabel(start, context.labels);
readLabel(start + length, context.labels);
createLabel(start, context.labels);
createLabel(start + length, context.labels);
u += 6;
}
u += 3;
@ -1716,8 +1887,8 @@ public class ClassReader {
for (int i = 0; i < n; ++i) {
int start = readUnsignedShort(u);
int length = readUnsignedShort(u + 2);
context.start[i] = readLabel(start, context.labels);
context.end[i] = readLabel(start + length, context.labels);
context.start[i] = createLabel(start, context.labels);
context.end[i] = createLabel(start + length, context.labels);
context.index[i] = readUnsignedShort(u + 4);
u += 6;
}
@ -2137,7 +2308,7 @@ public class ClassReader {
}
}
frame.offset += delta + 1;
readLabel(frame.offset, labels);
createLabel(frame.offset, labels);
return stackMap;
}
@ -2190,7 +2361,7 @@ public class ClassReader {
v += 2;
break;
default: // Uninitialized
frame[index] = readLabel(readUnsignedShort(v), labels);
frame[index] = createLabel(readUnsignedShort(v), labels);
v += 2;
}
return v;
@ -2216,6 +2387,39 @@ public class ClassReader {
return labels[offset];
}
/**
* Creates a label without the Label.DEBUG flag set, for the given offset.
* The label is created with a call to {@link #readLabel} and its
* Label.DEBUG flag is cleared.
*
* @param offset
* a bytecode offset in a method.
* @param labels
* the already created labels, indexed by their offset.
* @return a Label without the Label.DEBUG flag set.
*/
private Label createLabel(int offset, Label[] labels) {
Label label = readLabel(offset, labels);
label.status &= ~Label.DEBUG;
return label;
}
/**
* Creates a label with the Label.DEBUG flag set, if there is no already
* existing label for the given offset (otherwise does nothing). The label
* is created with a call to {@link #readLabel}.
*
* @param offset
* a bytecode offset in a method.
* @param labels
* the already created labels, indexed by their offset.
*/
private void createDebugLabel(int offset, Label[] labels) {
if (labels[offset] == null) {
readLabel(offset, labels).status |= Label.DEBUG;
}
}
/**
* Returns the start index of the attribute_info structure of this class.
*
@ -2470,6 +2674,20 @@ public class ClassReader {
return new String(buf, 0, strLen);
}
/**
* Read a stringish constant item (CONSTANT_Class, CONSTANT_String,
* CONSTANT_MethodType, CONSTANT_Module or CONSTANT_Package
* @param index
* @param buf
* @return
*/
private String readStringish(final int index, final char[] buf) {
// computes the start index of the item in b
// and reads the CONSTANT_Utf8 item designated by
// the first two bytes of this item
return readUTF8(items[readUnsignedShort(index)], buf);
}
/**
* Reads a class constant pool item in {@link #b b}. <i>This method is
* intended for {@link Attribute} sub classes, and is normally not needed by
@ -2484,44 +2702,41 @@ public class ClassReader {
* @return the String corresponding to the specified class item.
*/
public String readClass(final int index, final char[] buf) {
// computes the start index of the CONSTANT_Class item in b
// and reads the CONSTANT_Utf8 item designated by
// the first two bytes of this CONSTANT_Class item
return readUTF8(items[readUnsignedShort(index)], buf);
return readStringish(index, buf);
}
/**
* Reads a CONSTANT_Module_info item in {@code b}. This method is intended
* for {@link Attribute} sub classes, and is normally not needed by class
* generators or adapters.</i>
* Reads a module constant pool item in {@link #b b}. <i>This method is
* intended for {@link Attribute} sub classes, and is normally not needed by
* class generators or adapters.</i>
*
* @param index
* the start index of an unsigned short value in {@link #b b},
* whose value is the index of a module constant pool item.
* @param buf
* buffer to be used to read the item. This buffer must be
* sufficiently large. It is not automatically resized.
* @param index
* the start index of an unsigned short value in {@link #b b},
* whose value is the index of a module constant pool item.
* @param buf
* buffer to be used to read the item. This buffer must be
* sufficiently large. It is not automatically resized.
* @return the String corresponding to the specified module item.
*/
public String readModule(int index, char[] buf) {
return readUTF8(items[readUnsignedShort(index)], buf);
public String readModule(final int index, final char[] buf) {
return readStringish(index, buf);
}
/**
* Reads a CONSTANT_Package_info item in {@code b}. This method is
* intended for {@link Attribute} sub slasses, and is normally not needed
* by class generators or adapters.</i>
* Reads a module constant pool item in {@link #b b}. <i>This method is
* intended for {@link Attribute} sub classes, and is normally not needed by
* class generators or adapters.</i>
*
* @param index
* the start index of an unsigned short value in {@link #b b},
* whose value is the index of a package constant pool item.
* @param buf
* buffer to be used to read the item. This buffer must be
* sufficiently large. It is not automatically resized.
* @return the String corresponding to the specified package item.
* @param index
* the start index of an unsigned short value in {@link #b b},
* whose value is the index of a module constant pool item.
* @param buf
* buffer to be used to read the item. This buffer must be
* sufficiently large. It is not automatically resized.
* @return the String corresponding to the specified module item.
*/
public String readPackage(int index, char[] buf) {
return readUTF8(items[readUnsignedShort(index)], buf);
public String readPackage(final int index, final char[] buf) {
return readStringish(index, buf);
}
/**
@ -2550,8 +2765,6 @@ public class ClassReader {
case ClassWriter.DOUBLE:
return Double.longBitsToDouble(readLong(index));
case ClassWriter.CLASS:
case ClassWriter.MODULE:
case ClassWriter.PACKAGE:
return Type.getObjectType(readUTF8(index, buf));
case ClassWriter.STR:
return readUTF8(index, buf);

View File

@ -61,7 +61,7 @@ package jdk.internal.org.objectweb.asm;
/**
* A visitor to visit a Java class. The methods of this class must be called in
* the following order: <tt>visit</tt> [ <tt>visitSource</tt> ] [
* <tt>visitOuterClass</tt> ] ( <tt>visitAnnotation</tt> |
* <tt>visitModule</tt> ][ <tt>visitOuterClass</tt> ] ( <tt>visitAnnotation</tt> |
* <tt>visitTypeAnnotation</tt> | <tt>visitAttribute</tt> )* (
* <tt>visitInnerClass</tt> | <tt>visitField</tt> | <tt>visitMethod</tt> )*
* <tt>visitEnd</tt>.
@ -72,7 +72,7 @@ public abstract class ClassVisitor {
/**
* The ASM API version implemented by this visitor. The value of this field
* must be one of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
* must be one of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
*/
protected final int api;
@ -87,7 +87,7 @@ public abstract class ClassVisitor {
*
* @param api
* the ASM API version implemented by this visitor. Must be one
* of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
* of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
*/
public ClassVisitor(final int api) {
this(api, null);
@ -98,13 +98,13 @@ public abstract class ClassVisitor {
*
* @param api
* the ASM API version implemented by this visitor. Must be one
* of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
* of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
* @param cv
* the class visitor to which this visitor must delegate method
* calls. May be null.
*/
public ClassVisitor(final int api, final ClassVisitor cv) {
if (api != Opcodes.ASM4 && api != Opcodes.ASM5) {
if (api < Opcodes.ASM4 || api > Opcodes.ASM6) {
throw new IllegalArgumentException();
}
this.api = api;
@ -160,6 +160,28 @@ public abstract class ClassVisitor {
}
}
/**
* Visit the module corresponding to the class.
* @param name
* module name
* @param access
* module flags, among {@code ACC_OPEN}, {@code ACC_SYNTHETIC}
* and {@code ACC_MANDATED}.
* @param version
* module version or null.
* @return a visitor to visit the module values, or <tt>null</tt> if
* this visitor is not interested in visiting this module.
*/
public ModuleVisitor visitModule(String name, int access, String version) {
if (api < Opcodes.ASM6) {
throw new RuntimeException();
}
if (cv != null) {
return cv.visitModule(name, access, version);
}
return null;
}
/**
* Visits the enclosing class of the class. This method must be called only
* if the class has an enclosing class.

View File

@ -87,8 +87,8 @@ public class ClassWriter extends ClassVisitor {
* {@link MethodVisitor#visitFrame} method are ignored, and the stack map
* frames are recomputed from the methods bytecode. The arguments of the
* {@link MethodVisitor#visitMaxs visitMaxs} method are also ignored and
* recomputed from the bytecode. In other words, computeFrames implies
* computeMaxs.
* recomputed from the bytecode. In other words, COMPUTE_FRAMES implies
* COMPUTE_MAXS.
*
* @see #ClassWriter(int)
*/
@ -196,6 +196,27 @@ public class ClassWriter extends ClassVisitor {
*/
static final int WIDE_INSN = 17;
/**
* The type of the ASM pseudo instructions with an unsigned 2 bytes offset
* label (see Label#resolve).
*/
static final int ASM_LABEL_INSN = 18;
/**
* The type of the ASM pseudo instructions with a 4 bytes offset label.
*/
static final int ASM_LABELW_INSN = 19;
/**
* Represents a frame inserted between already existing frames. This kind of
* frame can only be used if the frame content can be computed from the
* previous existing frame and from the instructions between this existing
* frame and the inserted one, without any knowledge of the type hierarchy.
* This kind of frame is only used when an unconditional jump is inserted in
* a method while expanding an ASM pseudo instruction (see ClassReader).
*/
static final int F_INSERT = 256;
/**
* The instruction types of all JVM opcodes.
*/
@ -284,7 +305,7 @@ public class ClassWriter extends ClassVisitor {
/**
* The base value for all CONSTANT_MethodHandle constant pool items.
* Internally, ASM store the 9 variations of CONSTANT_MethodHandle into 9
* different items.
* different items (from 21 to 29).
*/
static final int HANDLE_BASE = 20;
@ -433,6 +454,11 @@ public class ClassWriter extends ClassVisitor {
*/
private ByteVector sourceDebug;
/**
* The module attribute of this class.
*/
private ModuleWriter moduleWriter;
/**
* The constant pool item that contains the name of the enclosing class of
* this class.
@ -523,25 +549,19 @@ public class ClassWriter extends ClassVisitor {
MethodWriter lastMethod;
/**
* <tt>true</tt> if the maximum stack size and number of local variables
* must be automatically computed.
* Indicates what must be automatically computed.
*
* @see MethodWriter#compute
*/
private boolean computeMaxs;
private int compute;
/**
* <tt>true</tt> if the stack map frames must be recomputed from scratch.
* <tt>true</tt> if some methods have wide forward jumps using ASM pseudo
* instructions, which need to be expanded into sequences of standard
* bytecode instructions. In this case the class is re-read and re-written
* with a ClassReader -> ClassWriter chain to perform this transformation.
*/
private boolean computeFrames;
/**
* <tt>true</tt> if the stack map tables of this class are invalid. The
* {@link MethodWriter#resizeInstructions} method cannot transform existing
* stack map tables, and so produces potentially invalid classes when it is
* executed. In this case the class is reread and rewritten with the
* {@link #COMPUTE_FRAMES} option (the resizeInstructions method can resize
* stack map tables when this option is used).
*/
boolean invalidFrames;
boolean hasAsmInsns;
// ------------------------------------------------------------------------
// Static initializer
@ -552,11 +572,11 @@ public class ClassWriter extends ClassVisitor {
*/
static {
int i;
byte[] b = new byte[220];
byte[] b = new byte[221];
String s = "AAAAAAAAAAAAAAAABCLMMDDDDDEEEEEEEEEEEEEEEEEEEEAAAAAAAADD"
+ "DDDEEEEEEEEEEEEEEEEEEEEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAANAAAAAAAAAAAAAAAAAAAAJJJJJJJJJJJJJJJJDOPAA"
+ "AAAAGGGGGGGHIFBFAAFFAARQJJKKJJJJJJJJJJJJJJJJJJ";
+ "AAAAGGGGGGGHIFBFAAFFAARQJJKKSSSSSSSSSSSSSSSSSST";
for (i = 0; i < b.length; ++i) {
b[i] = (byte) (s.charAt(i) - 'A');
}
@ -610,8 +630,9 @@ public class ClassWriter extends ClassVisitor {
// // temporary opcodes used internally by ASM - see Label and
// MethodWriter
// for (i = 202; i < 220; ++i) {
// b[i] = LABEL_INSN;
// b[i] = ASM_LABEL_INSN;
// }
// b[220] = ASM_LABELW_INSN;
//
// // LDC(_W) instructions
// b[Constants.LDC] = LDC_INSN;
@ -644,7 +665,7 @@ public class ClassWriter extends ClassVisitor {
* {@link #COMPUTE_FRAMES}.
*/
public ClassWriter(final int flags) {
super(Opcodes.ASM5);
super(Opcodes.ASM6);
index = 1;
pool = new ByteVector();
items = new Item[256];
@ -653,8 +674,9 @@ public class ClassWriter extends ClassVisitor {
key2 = new Item();
key3 = new Item();
key4 = new Item();
this.computeMaxs = (flags & COMPUTE_MAXS) != 0;
this.computeFrames = (flags & COMPUTE_FRAMES) != 0;
this.compute = (flags & COMPUTE_FRAMES) != 0 ? MethodWriter.FRAMES
: ((flags & COMPUTE_MAXS) != 0 ? MethodWriter.MAXS
: MethodWriter.NOTHING);
}
/**
@ -684,9 +706,9 @@ public class ClassWriter extends ClassVisitor {
* @param flags
* option flags that can be used to modify the default behavior
* of this class. <i>These option flags do not affect methods
* that are copied as is in the new class. This means that the
* maximum stack size nor the stack frames will be computed for
* these methods</i>. See {@link #COMPUTE_MAXS},
* that are copied as is in the new class. This means that
* neither the maximum stack size nor the stack frames will be
* computed for these methods</i>. See {@link #COMPUTE_MAXS},
* {@link #COMPUTE_FRAMES}.
*/
public ClassWriter(final ClassReader classReader, final int flags) {
@ -705,9 +727,9 @@ public class ClassWriter extends ClassVisitor {
final String[] interfaces) {
this.version = version;
this.access = access;
this.name = (name == null) ? 0 : newClass(name);
this.name = newClass(name);
thisName = name;
if (ClassReader.SIGNATURES && signature != null) {
if (signature != null) {
this.signature = newUTF8(signature);
}
this.superName = superName == null ? 0 : newClass(superName);
@ -731,6 +753,14 @@ public class ClassWriter extends ClassVisitor {
}
}
@Override
public final ModuleVisitor visitModule(final String name,
final int access, final String version) {
return moduleWriter = new ModuleWriter(this,
newModule(name), access,
version == null ? 0 : newUTF8(version));
}
@Override
public final void visitOuterClass(final String owner, final String name,
final String desc) {
@ -743,9 +773,6 @@ public class ClassWriter extends ClassVisitor {
@Override
public final AnnotationVisitor visitAnnotation(final String desc,
final boolean visible) {
if (!ClassReader.ANNOTATIONS) {
return null;
}
ByteVector bv = new ByteVector();
// write type, and reserve space for values count
bv.putShort(newUTF8(desc)).putShort(0);
@ -763,9 +790,6 @@ public class ClassWriter extends ClassVisitor {
@Override
public final AnnotationVisitor visitTypeAnnotation(int typeRef,
TypePath typePath, final String desc, final boolean visible) {
if (!ClassReader.ANNOTATIONS) {
return null;
}
ByteVector bv = new ByteVector();
// write target_type and target_info
AnnotationWriter.putTarget(typeRef, typePath, bv);
@ -805,7 +829,7 @@ public class ClassWriter extends ClassVisitor {
// and equality tests). If so we store the index of this inner class
// entry (plus one) in intVal. This hack allows duplicate detection in
// O(1) time.
Item nameItem = newClassItem(name);
Item nameItem = newStringishItem(CLASS, name);
if (nameItem.intVal == 0) {
++innerClassesCount;
innerClasses.putShort(nameItem.index);
@ -830,7 +854,7 @@ public class ClassWriter extends ClassVisitor {
public final MethodVisitor visitMethod(final int access, final String name,
final String desc, final String signature, final String[] exceptions) {
return new MethodWriter(this, access, name, desc, signature,
exceptions, computeMaxs, computeFrames);
exceptions, compute);
}
@Override
@ -874,7 +898,7 @@ public class ClassWriter extends ClassVisitor {
size += 8 + bootstrapMethods.length;
newUTF8("BootstrapMethods");
}
if (ClassReader.SIGNATURES && signature != 0) {
if (signature != 0) {
++attributeCount;
size += 8;
newUTF8("Signature");
@ -912,26 +936,31 @@ public class ClassWriter extends ClassVisitor {
size += 8 + innerClasses.length;
newUTF8("InnerClasses");
}
if (ClassReader.ANNOTATIONS && anns != null) {
if (anns != null) {
++attributeCount;
size += 8 + anns.getSize();
newUTF8("RuntimeVisibleAnnotations");
}
if (ClassReader.ANNOTATIONS && ianns != null) {
if (ianns != null) {
++attributeCount;
size += 8 + ianns.getSize();
newUTF8("RuntimeInvisibleAnnotations");
}
if (ClassReader.ANNOTATIONS && tanns != null) {
if (tanns != null) {
++attributeCount;
size += 8 + tanns.getSize();
newUTF8("RuntimeVisibleTypeAnnotations");
}
if (ClassReader.ANNOTATIONS && itanns != null) {
if (itanns != null) {
++attributeCount;
size += 8 + itanns.getSize();
newUTF8("RuntimeInvisibleTypeAnnotations");
}
if (moduleWriter != null) {
attributeCount += 1 + moduleWriter.attributeCount;
size += 6 + moduleWriter.size + moduleWriter.attributesSize;
newUTF8("Module");
}
if (attrs != null) {
attributeCount += attrs.getCount();
size += attrs.getSize(this, null, 0, -1, -1);
@ -968,7 +997,7 @@ public class ClassWriter extends ClassVisitor {
bootstrapMethodsCount);
out.putByteArray(bootstrapMethods.data, 0, bootstrapMethods.length);
}
if (ClassReader.SIGNATURES && signature != 0) {
if (signature != 0) {
out.putShort(newUTF8("Signature")).putInt(2).putShort(signature);
}
if (sourceFile != 0) {
@ -979,6 +1008,11 @@ public class ClassWriter extends ClassVisitor {
out.putShort(newUTF8("SourceDebugExtension")).putInt(len);
out.putByteArray(sourceDebug.data, 0, len);
}
if (moduleWriter != null) {
out.putShort(newUTF8("Module"));
moduleWriter.put(out);
moduleWriter.putAttributes(out);
}
if (enclosingMethodOwner != 0) {
out.putShort(newUTF8("EnclosingMethod")).putInt(4);
out.putShort(enclosingMethodOwner).putShort(enclosingMethod);
@ -997,41 +1031,46 @@ public class ClassWriter extends ClassVisitor {
out.putInt(innerClasses.length + 2).putShort(innerClassesCount);
out.putByteArray(innerClasses.data, 0, innerClasses.length);
}
if (ClassReader.ANNOTATIONS && anns != null) {
if (anns != null) {
out.putShort(newUTF8("RuntimeVisibleAnnotations"));
anns.put(out);
}
if (ClassReader.ANNOTATIONS && ianns != null) {
if (ianns != null) {
out.putShort(newUTF8("RuntimeInvisibleAnnotations"));
ianns.put(out);
}
if (ClassReader.ANNOTATIONS && tanns != null) {
if (tanns != null) {
out.putShort(newUTF8("RuntimeVisibleTypeAnnotations"));
tanns.put(out);
}
if (ClassReader.ANNOTATIONS && itanns != null) {
if (itanns != null) {
out.putShort(newUTF8("RuntimeInvisibleTypeAnnotations"));
itanns.put(out);
}
if (attrs != null) {
attrs.put(this, null, 0, -1, -1, out);
}
if (invalidFrames) {
if (hasAsmInsns) {
boolean hasFrames = false;
mb = firstMethod;
while (mb != null) {
hasFrames |= mb.frameCount > 0;
mb = (MethodWriter) mb.mv;
}
anns = null;
ianns = null;
attrs = null;
innerClassesCount = 0;
innerClasses = null;
bootstrapMethodsCount = 0;
bootstrapMethods = null;
moduleWriter = null;
firstField = null;
lastField = null;
firstMethod = null;
lastMethod = null;
computeMaxs = false;
computeFrames = true;
invalidFrames = false;
new ClassReader(out.data).accept(this, ClassReader.SKIP_FRAMES);
compute =
hasFrames ? MethodWriter.INSERTED_FRAMES : MethodWriter.NOTHING;
hasAsmInsns = false;
new ClassReader(out.data).accept(this,
(hasFrames ? ClassReader.EXPAND_FRAMES : 0)
| ClassReader.EXPAND_ASM_INSNS);
return toByteArray();
}
return out.data;
@ -1078,16 +1117,16 @@ public class ClassWriter extends ClassVisitor {
double val = ((Double) cst).doubleValue();
return newDouble(val);
} else if (cst instanceof String) {
return newString((String) cst);
return newStringishItem(STR, (String) cst);
} else if (cst instanceof Type) {
Type t = (Type) cst;
int s = t.getSort();
if (s == Type.OBJECT) {
return newClassItem(t.getInternalName());
return newStringishItem(CLASS, t.getInternalName());
} else if (s == Type.METHOD) {
return newMethodTypeItem(t.getDescriptor());
return newStringishItem(MTYPE, t.getDescriptor());
} else { // s == primitive type or array
return newClassItem(t.getDescriptor());
return newStringishItem(CLASS, t.getDescriptor());
}
} else if (cst instanceof Handle) {
Handle h = (Handle) cst;
@ -1136,20 +1175,21 @@ public class ClassWriter extends ClassVisitor {
}
/**
* Adds a class reference to the constant pool of the class being build.
* Adds a string reference, a class reference, a method type, a module
* or a package to the constant pool of the class being build.
* Does nothing if the constant pool already contains a similar item.
* <i>This method is intended for {@link Attribute} sub classes, and is
* normally not needed by class generators or adapters.</i>
*
* @param type
* a type among STR, CLASS, MTYPE, MODULE or PACKAGE
* @param value
* the internal name of the class.
* @return a new or already existing class reference item.
* string value of the reference.
* @return a new or already existing reference item.
*/
Item newClassItem(final String value) {
key2.set(CLASS, value, null, null);
Item newStringishItem(final int type, final String value) {
key2.set(type, value, null, null);
Item result = get(key2);
if (result == null) {
pool.put12(CLASS, newUTF8(value));
pool.put12(type, newUTF8(value));
result = new Item(index++, key2);
put(result);
}
@ -1167,72 +1207,7 @@ public class ClassWriter extends ClassVisitor {
* @return the index of a new or already existing class reference item.
*/
public int newClass(final String value) {
return newClassItem(value).index;
}
/**
* Adds a module name to the constant pool.
*
* Does nothing if the constant pool already contains a similar item.
* <i>This method is intended for {@link Attribute} sub classes, and is
* normally not needed by class generators or adapters.</i>
*
* @param value
* the module name
* @return the index of a new or already existing module reference item.
*/
public int newModule(String value) {
key2.set(MODULE, value, null, null);
Item result = get(key2);
if (result == null) {
pool.put12(MODULE, newUTF8(value));
result = new Item(index++, key2);
put(result);
}
return result.index;
}
/**
* Adds a package name to the constant pool.
*
* Does nothing if the constant pool already contains a similar item.
* <i>This method is intended for {@link Attribute} sub classes, and is
* normally not needed by class generators or adapters.</i>
*
* @param value
* the internal name of the package.
* @return the index of a new or already existing package reference item.
*/
public int newPackage(String value) {
key2.set(PACKAGE, value, null, null);
Item result = get(key2);
if (result == null) {
pool.put12(PACKAGE, newUTF8(value));
result = new Item(index++, key2);
put(result);
}
return result.index;
}
/**
* Adds a method type reference to the constant pool of the class being
* build. Does nothing if the constant pool already contains a similar item.
* <i>This method is intended for {@link Attribute} sub classes, and is
* normally not needed by class generators or adapters.</i>
*
* @param methodDesc
* method descriptor of the method type.
* @return a new or already existing method type reference item.
*/
Item newMethodTypeItem(final String methodDesc) {
key2.set(MTYPE, methodDesc, null, null);
Item result = get(key2);
if (result == null) {
pool.put12(MTYPE, newUTF8(methodDesc));
result = new Item(index++, key2);
put(result);
}
return result;
return newStringishItem(CLASS, value).index;
}
/**
@ -1247,7 +1222,37 @@ public class ClassWriter extends ClassVisitor {
* item.
*/
public int newMethodType(final String methodDesc) {
return newMethodTypeItem(methodDesc).index;
return newStringishItem(MTYPE, methodDesc).index;
}
/**
* Adds a module reference to the constant pool of the class being
* build. Does nothing if the constant pool already contains a similar item.
* <i>This method is intended for {@link Attribute} sub classes, and is
* normally not needed by class generators or adapters.</i>
*
* @param moduleName
* name of the module.
* @return the index of a new or already existing module reference
* item.
*/
public int newModule(final String moduleName) {
return newStringishItem(MODULE, moduleName).index;
}
/**
* Adds a package reference to the constant pool of the class being
* build. Does nothing if the constant pool already contains a similar item.
* <i>This method is intended for {@link Attribute} sub classes, and is
* normally not needed by class generators or adapters.</i>
*
* @param packageName
* name of the package in its internal form.
* @return the index of a new or already existing module reference
* item.
*/
public int newPackage(final String packageName) {
return newStringishItem(PACKAGE, packageName).index;
}
/**
@ -1628,25 +1633,6 @@ public class ClassWriter extends ClassVisitor {
return result;
}
/**
* Adds a string to the constant pool of the class being build. Does nothing
* if the constant pool already contains a similar item.
*
* @param value
* the String value.
* @return a new or already existing string item.
*/
private Item newString(final String value) {
key2.set(STR, value, null, null);
Item result = get(key2);
if (result == null) {
pool.put12(STR, newUTF8(value));
result = new Item(index++, key2);
put(result);
}
return result;
}
/**
* Adds a name and type to the constant pool of the class being build. Does
* nothing if the constant pool already contains a similar item. <i>This

View File

@ -0,0 +1,85 @@
/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* This file is available under and governed by the GNU General Public
* License version 2 only, as published by the Free Software Foundation.
* However, the following notice accompanied the original version of this
* file:
*
* ASM: a very small and fast Java bytecode manipulation framework
* Copyright (c) 2000-2011 INRIA, France Telecom
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
package jdk.internal.org.objectweb.asm;
/**
* Information about the input stack map frame at the "current" instruction of a
* method. This is implemented as a Frame subclass for a "basic block"
* containing only one instruction.
*
* @author Eric Bruneton
*/
class CurrentFrame extends Frame {
/**
* Sets this CurrentFrame to the input stack map frame of the next "current"
* instruction, i.e. the instruction just after the given one. It is assumed
* that the value of this object when this method is called is the stack map
* frame status just before the given instruction is executed.
*/
@Override
void execute(int opcode, int arg, ClassWriter cw, Item item) {
super.execute(opcode, arg, cw, item);
Frame successor = new Frame();
merge(cw, successor, 0);
set(successor);
owner.inputStackTop = 0;
}
}

View File

@ -69,7 +69,7 @@ public abstract class FieldVisitor {
/**
* The ASM API version implemented by this visitor. The value of this field
* must be one of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
* must be one of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
*/
protected final int api;
@ -84,7 +84,7 @@ public abstract class FieldVisitor {
*
* @param api
* the ASM API version implemented by this visitor. Must be one
* of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
* of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
*/
public FieldVisitor(final int api) {
this(api, null);
@ -95,13 +95,13 @@ public abstract class FieldVisitor {
*
* @param api
* the ASM API version implemented by this visitor. Must be one
* of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
* of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
* @param fv
* the field visitor to which this visitor must delegate method
* calls. May be null.
*/
public FieldVisitor(final int api, final FieldVisitor fv) {
if (api != Opcodes.ASM4 && api != Opcodes.ASM5) {
if (api < Opcodes.ASM4 || api > Opcodes.ASM6) {
throw new IllegalArgumentException();
}
this.api = api;

Some files were not shown because too many files have changed in this diff Show More