mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-28 15:24:43 +02:00
Merge
This commit is contained in:
commit
c71f3cdbe6
1328 changed files with 50430 additions and 32076 deletions
1
.hgtags
1
.hgtags
|
@ -232,3 +232,4 @@ b5ed503c26ad38869c247c5e32debec217fd056b jdk8-b104
|
||||||
74049f7a28b48c14910106a75d9f2504169c352e jdk8-b108
|
74049f7a28b48c14910106a75d9f2504169c352e jdk8-b108
|
||||||
af9a674e12a16da1a4bd53e4990ddb1121a21ef1 jdk8-b109
|
af9a674e12a16da1a4bd53e4990ddb1121a21ef1 jdk8-b109
|
||||||
b5d2bf482a3ea1cca08c994512804ffbc73de0a1 jdk8-b110
|
b5d2bf482a3ea1cca08c994512804ffbc73de0a1 jdk8-b110
|
||||||
|
b9a0f6c693f347a6f4b9bb994957f4eaa05bdedd jdk8-b111
|
||||||
|
|
|
@ -232,3 +232,4 @@ b7e64be81c8a7690703df5711f4fc2375da8a9cb jdk8-b103
|
||||||
9286a6e61291246d88af713f1ef79adeea30fe2e jdk8-b108
|
9286a6e61291246d88af713f1ef79adeea30fe2e jdk8-b108
|
||||||
91f47e8da5c60de58ed195e9b57f3bf192a18f83 jdk8-b109
|
91f47e8da5c60de58ed195e9b57f3bf192a18f83 jdk8-b109
|
||||||
4faa09c7fe555de086dd9048d3c5cc92317d6f45 jdk8-b110
|
4faa09c7fe555de086dd9048d3c5cc92317d6f45 jdk8-b110
|
||||||
|
d086227bfc45d124f09b3bd72a07956b4073bf71 jdk8-b111
|
||||||
|
|
|
@ -707,7 +707,6 @@ AC_DEFUN_ONCE([BASIC_CHECK_SRC_PERMS],
|
||||||
|
|
||||||
AC_DEFUN_ONCE([BASIC_TEST_USABILITY_ISSUES],
|
AC_DEFUN_ONCE([BASIC_TEST_USABILITY_ISSUES],
|
||||||
[
|
[
|
||||||
|
|
||||||
AC_MSG_CHECKING([if build directory is on local disk])
|
AC_MSG_CHECKING([if build directory is on local disk])
|
||||||
BASIC_CHECK_DIR_ON_LOCAL_DISK($OUTPUT_ROOT,
|
BASIC_CHECK_DIR_ON_LOCAL_DISK($OUTPUT_ROOT,
|
||||||
[OUTPUT_DIR_IS_LOCAL="yes"],
|
[OUTPUT_DIR_IS_LOCAL="yes"],
|
||||||
|
@ -734,5 +733,4 @@ else
|
||||||
# Hide it the next time around...
|
# Hide it the next time around...
|
||||||
$TOUCH $SRC_ROOT/build/.hide-configure-performance-hints > /dev/null 2>&1
|
$TOUCH $SRC_ROOT/build/.hide-configure-performance-hints > /dev/null 2>&1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
])
|
])
|
||||||
|
|
|
@ -53,7 +53,6 @@ AC_DEFUN([BPERF_CHECK_CORES],
|
||||||
AC_MSG_RESULT([could not detect number of cores, defaulting to 1])
|
AC_MSG_RESULT([could not detect number of cores, defaulting to 1])
|
||||||
AC_MSG_WARN([This will disable all parallelism from build!])
|
AC_MSG_WARN([This will disable all parallelism from build!])
|
||||||
fi
|
fi
|
||||||
|
|
||||||
])
|
])
|
||||||
|
|
||||||
AC_DEFUN([BPERF_CHECK_MEMORY_SIZE],
|
AC_DEFUN([BPERF_CHECK_MEMORY_SIZE],
|
||||||
|
@ -331,5 +330,4 @@ else
|
||||||
SJAVAC_SERVER_DIR=
|
SJAVAC_SERVER_DIR=
|
||||||
fi
|
fi
|
||||||
AC_SUBST(SJAVAC_SERVER_DIR)
|
AC_SUBST(SJAVAC_SERVER_DIR)
|
||||||
|
|
||||||
])
|
])
|
||||||
|
|
1
common/autoconf/configure
vendored
1
common/autoconf/configure
vendored
|
@ -88,7 +88,6 @@ check_hg_updates() {
|
||||||
check_autoconf_timestamps
|
check_autoconf_timestamps
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3818,7 +3818,7 @@ fi
|
||||||
#CUSTOM_AUTOCONF_INCLUDE
|
#CUSTOM_AUTOCONF_INCLUDE
|
||||||
|
|
||||||
# Do not change or remove the following line, it is needed for consistency checks:
|
# Do not change or remove the following line, it is needed for consistency checks:
|
||||||
DATE_WHEN_GENERATED=1381162713
|
DATE_WHEN_GENERATED=1381407169
|
||||||
|
|
||||||
###############################################################################
|
###############################################################################
|
||||||
#
|
#
|
||||||
|
@ -7135,7 +7135,6 @@ $as_echo "$COMPILE_TYPE" >&6; }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# Continue setting up basic stuff. Most remaining code require fundamental tools.
|
# Continue setting up basic stuff. Most remaining code require fundamental tools.
|
||||||
|
|
||||||
# Locate the directory of this script.
|
# Locate the directory of this script.
|
||||||
|
@ -7847,7 +7846,6 @@ fi
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
###############################################################################
|
###############################################################################
|
||||||
#
|
#
|
||||||
# Set the debug level
|
# Set the debug level
|
||||||
|
@ -16023,7 +16021,6 @@ BOOT_JDK_JVMARGS=$boot_jdk_jvmargs
|
||||||
###############################################################################
|
###############################################################################
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# Where are the sources. Any of these can be overridden
|
# Where are the sources. Any of these can be overridden
|
||||||
# using --with-override-corba and the likes.
|
# using --with-override-corba and the likes.
|
||||||
LANGTOOLS_TOPDIR="$SRC_ROOT/langtools"
|
LANGTOOLS_TOPDIR="$SRC_ROOT/langtools"
|
||||||
|
@ -16316,7 +16313,6 @@ $as_echo "yes with $JDK_TOPDIR" >&6; }
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
BUILD_OUTPUT="$OUTPUT_ROOT"
|
BUILD_OUTPUT="$OUTPUT_ROOT"
|
||||||
|
|
||||||
|
|
||||||
|
@ -18721,6 +18717,7 @@ $as_echo "$as_me: Downloading build dependency devkit from $with_builddeps_serve
|
||||||
if test "x$thelibs" != x; then
|
if test "x$thelibs" != x; then
|
||||||
DEVKIT_LIBS="$thelibs"
|
DEVKIT_LIBS="$thelibs"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Found devkit
|
# Found devkit
|
||||||
PATH="$DEVKIT/bin:$PATH"
|
PATH="$DEVKIT/bin:$PATH"
|
||||||
SYS_ROOT="$DEVKIT/${rewritten_target}/sys-root"
|
SYS_ROOT="$DEVKIT/${rewritten_target}/sys-root"
|
||||||
|
@ -19686,7 +19683,7 @@ $as_echo "$as_me: The result from running with -V was: \"$COMPILER_VERSION_TEST\
|
||||||
fi
|
fi
|
||||||
elif test "x$OPENJDK_TARGET_OS" = xwindows; then
|
elif test "x$OPENJDK_TARGET_OS" = xwindows; then
|
||||||
# First line typically looks something like:
|
# First line typically looks something like:
|
||||||
# Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 16.00.30319.01 for 80x86
|
# Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 16.00.40219.01 for 80x86
|
||||||
COMPILER_VERSION_TEST=`$COMPILER 2>&1 | $HEAD -n 1 | $TR -d '\r'`
|
COMPILER_VERSION_TEST=`$COMPILER 2>&1 | $HEAD -n 1 | $TR -d '\r'`
|
||||||
COMPILER_VERSION=`$ECHO $COMPILER_VERSION_TEST | $SED -n "s/^.*Version \([1-9][0-9.]*\) .*/\1/p"`
|
COMPILER_VERSION=`$ECHO $COMPILER_VERSION_TEST | $SED -n "s/^.*Version \([1-9][0-9.]*\) .*/\1/p"`
|
||||||
COMPILER_VENDOR="Microsoft CL.EXE"
|
COMPILER_VENDOR="Microsoft CL.EXE"
|
||||||
|
@ -21258,7 +21255,7 @@ $as_echo "$as_me: The result from running with -V was: \"$COMPILER_VERSION_TEST\
|
||||||
fi
|
fi
|
||||||
elif test "x$OPENJDK_TARGET_OS" = xwindows; then
|
elif test "x$OPENJDK_TARGET_OS" = xwindows; then
|
||||||
# First line typically looks something like:
|
# First line typically looks something like:
|
||||||
# Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 16.00.30319.01 for 80x86
|
# Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 16.00.40219.01 for 80x86
|
||||||
COMPILER_VERSION_TEST=`$COMPILER 2>&1 | $HEAD -n 1 | $TR -d '\r'`
|
COMPILER_VERSION_TEST=`$COMPILER 2>&1 | $HEAD -n 1 | $TR -d '\r'`
|
||||||
COMPILER_VERSION=`$ECHO $COMPILER_VERSION_TEST | $SED -n "s/^.*Version \([1-9][0-9.]*\) .*/\1/p"`
|
COMPILER_VERSION=`$ECHO $COMPILER_VERSION_TEST | $SED -n "s/^.*Version \([1-9][0-9.]*\) .*/\1/p"`
|
||||||
COMPILER_VENDOR="Microsoft CL.EXE"
|
COMPILER_VENDOR="Microsoft CL.EXE"
|
||||||
|
@ -28937,6 +28934,7 @@ else
|
||||||
$as_echo "no" >&6; }
|
$as_echo "no" >&6; }
|
||||||
as_fn_error $? "The selected compiler $CXX does not support -mstackrealign! Try to put another compiler in the path." "$LINENO" 5
|
as_fn_error $? "The selected compiler $CXX does not support -mstackrealign! Try to put another compiler in the path." "$LINENO" 5
|
||||||
|
|
||||||
|
|
||||||
fi
|
fi
|
||||||
rm -f core conftest.err conftest.$ac_objext \
|
rm -f core conftest.err conftest.$ac_objext \
|
||||||
conftest$ac_exeext conftest.$ac_ext
|
conftest$ac_exeext conftest.$ac_ext
|
||||||
|
@ -29393,9 +29391,7 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
|
||||||
|
|
||||||
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||||
/* end confdefs.h. */
|
/* end confdefs.h. */
|
||||||
|
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
_ACEOF
|
_ACEOF
|
||||||
if ac_fn_c_try_compile "$LINENO"; then :
|
if ac_fn_c_try_compile "$LINENO"; then :
|
||||||
|
|
||||||
|
@ -29421,9 +29417,7 @@ ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
|
||||||
|
|
||||||
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||||
/* end confdefs.h. */
|
/* end confdefs.h. */
|
||||||
|
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
_ACEOF
|
_ACEOF
|
||||||
if ac_fn_cxx_try_compile "$LINENO"; then :
|
if ac_fn_cxx_try_compile "$LINENO"; then :
|
||||||
|
|
||||||
|
@ -29466,9 +29460,7 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
|
||||||
|
|
||||||
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||||
/* end confdefs.h. */
|
/* end confdefs.h. */
|
||||||
|
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
_ACEOF
|
_ACEOF
|
||||||
if ac_fn_c_try_compile "$LINENO"; then :
|
if ac_fn_c_try_compile "$LINENO"; then :
|
||||||
|
|
||||||
|
@ -29494,9 +29486,7 @@ ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
|
||||||
|
|
||||||
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||||
/* end confdefs.h. */
|
/* end confdefs.h. */
|
||||||
|
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
_ACEOF
|
_ACEOF
|
||||||
if ac_fn_cxx_try_compile "$LINENO"; then :
|
if ac_fn_cxx_try_compile "$LINENO"; then :
|
||||||
|
|
||||||
|
@ -30488,9 +30478,11 @@ CFLAGS="$CFLAGS $X_CFLAGS"
|
||||||
for ac_header in X11/extensions/shape.h X11/extensions/Xrender.h X11/extensions/XTest.h X11/Intrinsic.h
|
for ac_header in X11/extensions/shape.h X11/extensions/Xrender.h X11/extensions/XTest.h X11/Intrinsic.h
|
||||||
do :
|
do :
|
||||||
as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
|
as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
|
||||||
ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" " # include <X11/Xlib.h>
|
ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "
|
||||||
|
# include <X11/Xlib.h>
|
||||||
# include <X11/Xutil.h>
|
# include <X11/Xutil.h>
|
||||||
|
|
||||||
|
|
||||||
"
|
"
|
||||||
if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
|
if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
|
||||||
cat >>confdefs.h <<_ACEOF
|
cat >>confdefs.h <<_ACEOF
|
||||||
|
@ -30739,9 +30731,12 @@ if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
|
||||||
cat >>confdefs.h <<_ACEOF
|
cat >>confdefs.h <<_ACEOF
|
||||||
#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
|
#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
|
||||||
_ACEOF
|
_ACEOF
|
||||||
|
|
||||||
CUPS_FOUND=yes
|
CUPS_FOUND=yes
|
||||||
CUPS_CFLAGS=
|
CUPS_CFLAGS=
|
||||||
DEFAULT_CUPS=yes
|
DEFAULT_CUPS=yes
|
||||||
|
|
||||||
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
done
|
done
|
||||||
|
@ -31362,6 +31357,7 @@ $as_echo_n "checking for freetype in some standard locations... " >&6; }
|
||||||
LDFLAGS="$LDFLAGS $DEFAULT_FREETYPE_LIBS"
|
LDFLAGS="$LDFLAGS $DEFAULT_FREETYPE_LIBS"
|
||||||
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||||
/* end confdefs.h. */
|
/* end confdefs.h. */
|
||||||
|
|
||||||
#include<ft2build.h>
|
#include<ft2build.h>
|
||||||
#include FT_FREETYPE_H
|
#include FT_FREETYPE_H
|
||||||
int main() { return 0; }
|
int main() { return 0; }
|
||||||
|
@ -31378,6 +31374,7 @@ else
|
||||||
|
|
||||||
FREETYPE2_FOUND=no
|
FREETYPE2_FOUND=no
|
||||||
|
|
||||||
|
|
||||||
fi
|
fi
|
||||||
rm -f core conftest.err conftest.$ac_objext \
|
rm -f core conftest.err conftest.$ac_objext \
|
||||||
conftest$ac_exeext conftest.$ac_ext
|
conftest$ac_exeext conftest.$ac_ext
|
||||||
|
@ -31473,7 +31470,6 @@ fi
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
###############################################################################
|
###############################################################################
|
||||||
#
|
#
|
||||||
# Check for alsa headers and libraries. Used on Linux/GNU systems.
|
# Check for alsa headers and libraries. Used on Linux/GNU systems.
|
||||||
|
@ -31748,10 +31744,12 @@ if test "x$ac_cv_header_alsa_asoundlib_h" = xyes; then :
|
||||||
cat >>confdefs.h <<_ACEOF
|
cat >>confdefs.h <<_ACEOF
|
||||||
#define HAVE_ALSA_ASOUNDLIB_H 1
|
#define HAVE_ALSA_ASOUNDLIB_H 1
|
||||||
_ACEOF
|
_ACEOF
|
||||||
|
|
||||||
ALSA_FOUND=yes
|
ALSA_FOUND=yes
|
||||||
ALSA_CFLAGS=-Iignoreme
|
ALSA_CFLAGS=-Iignoreme
|
||||||
ALSA_LIBS=-lasound
|
ALSA_LIBS=-lasound
|
||||||
DEFAULT_ALSA=yes
|
DEFAULT_ALSA=yes
|
||||||
|
|
||||||
else
|
else
|
||||||
ALSA_FOUND=no
|
ALSA_FOUND=no
|
||||||
fi
|
fi
|
||||||
|
@ -31794,7 +31792,6 @@ fi
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
###############################################################################
|
###############################################################################
|
||||||
#
|
#
|
||||||
# Check for the jpeg library
|
# Check for the jpeg library
|
||||||
|
@ -32128,6 +32125,7 @@ else
|
||||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: Maths library was not found" >&5
|
{ $as_echo "$as_me:${as_lineno-$LINENO}: Maths library was not found" >&5
|
||||||
$as_echo "$as_me: Maths library was not found" >&6;}
|
$as_echo "$as_me: Maths library was not found" >&6;}
|
||||||
|
|
||||||
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
@ -32188,7 +32186,6 @@ LIBDL="$LIBS"
|
||||||
LIBS="$save_LIBS"
|
LIBS="$save_LIBS"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
###############################################################################
|
###############################################################################
|
||||||
#
|
#
|
||||||
# statically link libstdc++ before C++ ABI is stablized on Linux unless
|
# statically link libstdc++ before C++ ABI is stablized on Linux unless
|
||||||
|
@ -32511,7 +32508,6 @@ fi
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# After we have toolchain and the paths to all libraries (needed by msys), we can compile the fixpath helper
|
# After we have toolchain and the paths to all libraries (needed by msys), we can compile the fixpath helper
|
||||||
|
|
||||||
# When using cygwin or msys, we need a wrapper binary that renames
|
# When using cygwin or msys, we need a wrapper binary that renames
|
||||||
|
@ -32590,7 +32586,6 @@ fi
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if elliptic curve crypto implementation is present" >&5
|
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if elliptic curve crypto implementation is present" >&5
|
||||||
$as_echo_n "checking if elliptic curve crypto implementation is present... " >&6; }
|
$as_echo_n "checking if elliptic curve crypto implementation is present... " >&6; }
|
||||||
|
|
||||||
|
@ -32658,7 +32653,6 @@ $as_echo "could not detect number of cores, defaulting to 1" >&6; }
|
||||||
$as_echo "$as_me: WARNING: This will disable all parallelism from build!" >&2;}
|
$as_echo "$as_me: WARNING: This will disable all parallelism from build!" >&2;}
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
||||||
else
|
else
|
||||||
NUM_CORES=$with_num_cores
|
NUM_CORES=$with_num_cores
|
||||||
fi
|
fi
|
||||||
|
@ -32975,7 +32969,6 @@ fi
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# Can the C/C++ compiler use precompiled headers?
|
# Can the C/C++ compiler use precompiled headers?
|
||||||
|
|
||||||
|
|
||||||
|
@ -33174,7 +33167,6 @@ $as_echo "no, disabling ccaching of precompiled headers" >&6; }
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if build directory is on local disk" >&5
|
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if build directory is on local disk" >&5
|
||||||
$as_echo_n "checking if build directory is on local disk... " >&6; }
|
$as_echo_n "checking if build directory is on local disk... " >&6; }
|
||||||
|
|
||||||
|
@ -33226,7 +33218,6 @@ else
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# At the end, call the custom hook. (Dummy macro if no custom sources available)
|
# At the end, call the custom hook. (Dummy macro if no custom sources available)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -135,7 +135,6 @@ if test "x$OPENJDK_TARGET_OS" = "xmacosx"; then
|
||||||
fi
|
fi
|
||||||
|
|
||||||
AC_SUBST(MACOSX_UNIVERSAL)
|
AC_SUBST(MACOSX_UNIVERSAL)
|
||||||
|
|
||||||
])
|
])
|
||||||
|
|
||||||
AC_DEFUN_ONCE([JDKOPT_SETUP_DEBUG_LEVEL],
|
AC_DEFUN_ONCE([JDKOPT_SETUP_DEBUG_LEVEL],
|
||||||
|
@ -493,7 +492,6 @@ if test "x$OPENJDK_TARGET_OS" = "xwindows"; then
|
||||||
SALIB_NAME="${LIBRARY_PREFIX}sawindbg${SHARED_LIBRARY_SUFFIX}"
|
SALIB_NAME="${LIBRARY_PREFIX}sawindbg${SHARED_LIBRARY_SUFFIX}"
|
||||||
fi
|
fi
|
||||||
AC_SUBST(SALIB_NAME)
|
AC_SUBST(SALIB_NAME)
|
||||||
|
|
||||||
])
|
])
|
||||||
|
|
||||||
AC_DEFUN_ONCE([JDKOPT_SETUP_DEBUG_SYMBOLS],
|
AC_DEFUN_ONCE([JDKOPT_SETUP_DEBUG_SYMBOLS],
|
||||||
|
|
|
@ -188,9 +188,11 @@ CFLAGS="$CFLAGS $X_CFLAGS"
|
||||||
AC_CHECK_HEADERS([X11/extensions/shape.h X11/extensions/Xrender.h X11/extensions/XTest.h X11/Intrinsic.h],
|
AC_CHECK_HEADERS([X11/extensions/shape.h X11/extensions/Xrender.h X11/extensions/XTest.h X11/Intrinsic.h],
|
||||||
[X11_A_OK=yes],
|
[X11_A_OK=yes],
|
||||||
[X11_A_OK=no; break],
|
[X11_A_OK=no; break],
|
||||||
[ # include <X11/Xlib.h>
|
[
|
||||||
|
# include <X11/Xlib.h>
|
||||||
# include <X11/Xutil.h>
|
# include <X11/Xutil.h>
|
||||||
])
|
]
|
||||||
|
)
|
||||||
|
|
||||||
CFLAGS="$OLD_CFLAGS"
|
CFLAGS="$OLD_CFLAGS"
|
||||||
AC_LANG_POP(C)
|
AC_LANG_POP(C)
|
||||||
|
@ -243,9 +245,12 @@ else
|
||||||
if test "x$CUPS_FOUND" = xno; then
|
if test "x$CUPS_FOUND" = xno; then
|
||||||
# Are the cups headers installed in the default /usr/include location?
|
# Are the cups headers installed in the default /usr/include location?
|
||||||
AC_CHECK_HEADERS([cups/cups.h cups/ppd.h],
|
AC_CHECK_HEADERS([cups/cups.h cups/ppd.h],
|
||||||
[CUPS_FOUND=yes
|
[
|
||||||
|
CUPS_FOUND=yes
|
||||||
CUPS_CFLAGS=
|
CUPS_CFLAGS=
|
||||||
DEFAULT_CUPS=yes])
|
DEFAULT_CUPS=yes
|
||||||
|
]
|
||||||
|
)
|
||||||
fi
|
fi
|
||||||
if test "x$CUPS_FOUND" = xno; then
|
if test "x$CUPS_FOUND" = xno; then
|
||||||
# Getting nervous now? Lets poke around for standard Solaris third-party
|
# Getting nervous now? Lets poke around for standard Solaris third-party
|
||||||
|
@ -377,7 +382,8 @@ else
|
||||||
PREV_LDFLAGS="$LDFLAGS"
|
PREV_LDFLAGS="$LDFLAGS"
|
||||||
CXXFLAGS="$CXXFLAGS $DEFAULT_FREETYPE_CFLAGS"
|
CXXFLAGS="$CXXFLAGS $DEFAULT_FREETYPE_CFLAGS"
|
||||||
LDFLAGS="$LDFLAGS $DEFAULT_FREETYPE_LIBS"
|
LDFLAGS="$LDFLAGS $DEFAULT_FREETYPE_LIBS"
|
||||||
AC_LINK_IFELSE([AC_LANG_SOURCE([[#include<ft2build.h>
|
AC_LINK_IFELSE([AC_LANG_SOURCE([[
|
||||||
|
#include<ft2build.h>
|
||||||
#include FT_FREETYPE_H
|
#include FT_FREETYPE_H
|
||||||
int main() { return 0; }
|
int main() { return 0; }
|
||||||
]])],
|
]])],
|
||||||
|
@ -389,7 +395,8 @@ else
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
FREETYPE2_FOUND=no
|
FREETYPE2_FOUND=no
|
||||||
])
|
]
|
||||||
|
)
|
||||||
CXXCFLAGS="$PREV_CXXFLAGS"
|
CXXCFLAGS="$PREV_CXXFLAGS"
|
||||||
LDFLAGS="$PREV_LDFLAGS"
|
LDFLAGS="$PREV_LDFLAGS"
|
||||||
AC_MSG_RESULT([$FREETYPE2_FOUND])
|
AC_MSG_RESULT([$FREETYPE2_FOUND])
|
||||||
|
@ -415,7 +422,6 @@ AC_SUBST(USING_SYSTEM_FT_LIB)
|
||||||
AC_SUBST(FREETYPE2_LIB_PATH)
|
AC_SUBST(FREETYPE2_LIB_PATH)
|
||||||
AC_SUBST(FREETYPE2_CFLAGS)
|
AC_SUBST(FREETYPE2_CFLAGS)
|
||||||
AC_SUBST(FREETYPE2_LIBS)
|
AC_SUBST(FREETYPE2_LIBS)
|
||||||
|
|
||||||
])
|
])
|
||||||
|
|
||||||
AC_DEFUN_ONCE([LIB_SETUP_ALSA],
|
AC_DEFUN_ONCE([LIB_SETUP_ALSA],
|
||||||
|
@ -467,10 +473,12 @@ else
|
||||||
fi
|
fi
|
||||||
if test "x$ALSA_FOUND" = xno; then
|
if test "x$ALSA_FOUND" = xno; then
|
||||||
AC_CHECK_HEADERS([alsa/asoundlib.h],
|
AC_CHECK_HEADERS([alsa/asoundlib.h],
|
||||||
[ALSA_FOUND=yes
|
[
|
||||||
|
ALSA_FOUND=yes
|
||||||
ALSA_CFLAGS=-Iignoreme
|
ALSA_CFLAGS=-Iignoreme
|
||||||
ALSA_LIBS=-lasound
|
ALSA_LIBS=-lasound
|
||||||
DEFAULT_ALSA=yes],
|
DEFAULT_ALSA=yes
|
||||||
|
],
|
||||||
[ALSA_FOUND=no])
|
[ALSA_FOUND=no])
|
||||||
fi
|
fi
|
||||||
if test "x$ALSA_FOUND" = xno; then
|
if test "x$ALSA_FOUND" = xno; then
|
||||||
|
@ -481,7 +489,6 @@ fi
|
||||||
|
|
||||||
AC_SUBST(ALSA_CFLAGS)
|
AC_SUBST(ALSA_CFLAGS)
|
||||||
AC_SUBST(ALSA_LIBS)
|
AC_SUBST(ALSA_LIBS)
|
||||||
|
|
||||||
])
|
])
|
||||||
|
|
||||||
AC_DEFUN_ONCE([LIB_SETUP_MISC_LIBS],
|
AC_DEFUN_ONCE([LIB_SETUP_MISC_LIBS],
|
||||||
|
@ -614,7 +621,8 @@ fi
|
||||||
AC_CHECK_LIB(m, cos, [],
|
AC_CHECK_LIB(m, cos, [],
|
||||||
[
|
[
|
||||||
AC_MSG_NOTICE([Maths library was not found])
|
AC_MSG_NOTICE([Maths library was not found])
|
||||||
])
|
]
|
||||||
|
)
|
||||||
AC_SUBST(LIBM)
|
AC_SUBST(LIBM)
|
||||||
|
|
||||||
###############################################################################
|
###############################################################################
|
||||||
|
@ -627,7 +635,6 @@ AC_CHECK_LIB(dl,dlopen)
|
||||||
LIBDL="$LIBS"
|
LIBDL="$LIBS"
|
||||||
AC_SUBST(LIBDL)
|
AC_SUBST(LIBDL)
|
||||||
LIBS="$save_LIBS"
|
LIBS="$save_LIBS"
|
||||||
|
|
||||||
])
|
])
|
||||||
|
|
||||||
AC_DEFUN_ONCE([LIB_SETUP_STATIC_LINK_LIBSTDCPP],
|
AC_DEFUN_ONCE([LIB_SETUP_STATIC_LINK_LIBSTDCPP],
|
||||||
|
@ -770,5 +777,4 @@ if test "x$OPENJDK_TARGET_OS" = xmacosx && test "x$LIBCXX" = x && test "x$GCC" =
|
||||||
fi
|
fi
|
||||||
|
|
||||||
AC_SUBST(LIBCXX)
|
AC_SUBST(LIBCXX)
|
||||||
|
|
||||||
])
|
])
|
||||||
|
|
|
@ -355,7 +355,6 @@ AC_DEFUN([PLATFORM_SETUP_LEGACY_VARS],
|
||||||
*) ZERO_ARCHDEF=$(echo "${OPENJDK_TARGET_CPU_LEGACY_LIB}" | tr a-z A-Z)
|
*) ZERO_ARCHDEF=$(echo "${OPENJDK_TARGET_CPU_LEGACY_LIB}" | tr a-z A-Z)
|
||||||
esac
|
esac
|
||||||
AC_SUBST(ZERO_ARCHDEF)
|
AC_SUBST(ZERO_ARCHDEF)
|
||||||
|
|
||||||
])
|
])
|
||||||
|
|
||||||
AC_DEFUN([PLATFORM_SET_RELEASE_FILE_OS_VALUES],
|
AC_DEFUN([PLATFORM_SET_RELEASE_FILE_OS_VALUES],
|
||||||
|
|
|
@ -25,7 +25,6 @@
|
||||||
|
|
||||||
AC_DEFUN_ONCE([SRCDIRS_SETUP_TOPDIRS],
|
AC_DEFUN_ONCE([SRCDIRS_SETUP_TOPDIRS],
|
||||||
[
|
[
|
||||||
|
|
||||||
# Where are the sources. Any of these can be overridden
|
# Where are the sources. Any of these can be overridden
|
||||||
# using --with-override-corba and the likes.
|
# using --with-override-corba and the likes.
|
||||||
LANGTOOLS_TOPDIR="$SRC_ROOT/langtools"
|
LANGTOOLS_TOPDIR="$SRC_ROOT/langtools"
|
||||||
|
@ -269,7 +268,6 @@ if test "x$with_override_jdk" != x; then
|
||||||
AC_MSG_CHECKING([if JDK should be overridden])
|
AC_MSG_CHECKING([if JDK should be overridden])
|
||||||
AC_MSG_RESULT([yes with $JDK_TOPDIR])
|
AC_MSG_RESULT([yes with $JDK_TOPDIR])
|
||||||
fi
|
fi
|
||||||
|
|
||||||
])
|
])
|
||||||
|
|
||||||
AC_DEFUN_ONCE([SRCDIRS_SETUP_OUTPUT_DIRS],
|
AC_DEFUN_ONCE([SRCDIRS_SETUP_OUTPUT_DIRS],
|
||||||
|
|
|
@ -46,7 +46,7 @@ AC_DEFUN([TOOLCHAIN_CHECK_COMPILER_VERSION],
|
||||||
fi
|
fi
|
||||||
elif test "x$OPENJDK_TARGET_OS" = xwindows; then
|
elif test "x$OPENJDK_TARGET_OS" = xwindows; then
|
||||||
# First line typically looks something like:
|
# First line typically looks something like:
|
||||||
# Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 16.00.30319.01 for 80x86
|
# Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 16.00.40219.01 for 80x86
|
||||||
COMPILER_VERSION_TEST=`$COMPILER 2>&1 | $HEAD -n 1 | $TR -d '\r'`
|
COMPILER_VERSION_TEST=`$COMPILER 2>&1 | $HEAD -n 1 | $TR -d '\r'`
|
||||||
COMPILER_VERSION=`$ECHO $COMPILER_VERSION_TEST | $SED -n "s/^.*Version \(@<:@1-9@:>@@<:@0-9.@:>@*\) .*/\1/p"`
|
COMPILER_VERSION=`$ECHO $COMPILER_VERSION_TEST | $SED -n "s/^.*Version \(@<:@1-9@:>@@<:@0-9.@:>@*\) .*/\1/p"`
|
||||||
COMPILER_VENDOR="Microsoft CL.EXE"
|
COMPILER_VENDOR="Microsoft CL.EXE"
|
||||||
|
@ -216,7 +216,8 @@ AC_SUBST(BUILD_LD)
|
||||||
# will be found by AC_PROG_CC et al.
|
# will be found by AC_PROG_CC et al.
|
||||||
DEVKIT=
|
DEVKIT=
|
||||||
BDEPS_CHECK_MODULE(DEVKIT, devkit, xxx,
|
BDEPS_CHECK_MODULE(DEVKIT, devkit, xxx,
|
||||||
[# Found devkit
|
[
|
||||||
|
# Found devkit
|
||||||
PATH="$DEVKIT/bin:$PATH"
|
PATH="$DEVKIT/bin:$PATH"
|
||||||
SYS_ROOT="$DEVKIT/${rewritten_target}/sys-root"
|
SYS_ROOT="$DEVKIT/${rewritten_target}/sys-root"
|
||||||
if test "x$x_includes" = "xNONE"; then
|
if test "x$x_includes" = "xNONE"; then
|
||||||
|
@ -617,7 +618,8 @@ if test "x$OPENJDK_TARGET_CPU_BITS" = x32 && test "x$OPENJDK_TARGET_OS" = xmacos
|
||||||
[
|
[
|
||||||
AC_MSG_RESULT([no])
|
AC_MSG_RESULT([no])
|
||||||
AC_MSG_ERROR([The selected compiler $CXX does not support -mstackrealign! Try to put another compiler in the path.])
|
AC_MSG_ERROR([The selected compiler $CXX does not support -mstackrealign! Try to put another compiler in the path.])
|
||||||
])
|
]
|
||||||
|
)
|
||||||
fi
|
fi
|
||||||
|
|
||||||
C_FLAG_DEPS="-MMD -MF"
|
C_FLAG_DEPS="-MMD -MF"
|
||||||
|
@ -1046,18 +1048,16 @@ AC_DEFUN([TOOLCHAIN_COMPILER_CHECK_ARGUMENTS],
|
||||||
saved_cflags="$CFLAGS"
|
saved_cflags="$CFLAGS"
|
||||||
CFLAGS="$CFLAGS $1"
|
CFLAGS="$CFLAGS $1"
|
||||||
AC_LANG_PUSH([C])
|
AC_LANG_PUSH([C])
|
||||||
AC_COMPILE_IFELSE([
|
AC_COMPILE_IFELSE([AC_LANG_SOURCE([[int i;]])], [],
|
||||||
AC_LANG_SOURCE([[int i;]])
|
[supports=no])
|
||||||
], [], [supports=no])
|
|
||||||
AC_LANG_POP([C])
|
AC_LANG_POP([C])
|
||||||
CFLAGS="$saved_cflags"
|
CFLAGS="$saved_cflags"
|
||||||
|
|
||||||
saved_cxxflags="$CXXFLAGS"
|
saved_cxxflags="$CXXFLAGS"
|
||||||
CXXFLAGS="$CXXFLAG $1"
|
CXXFLAGS="$CXXFLAG $1"
|
||||||
AC_LANG_PUSH([C++])
|
AC_LANG_PUSH([C++])
|
||||||
AC_COMPILE_IFELSE([
|
AC_COMPILE_IFELSE([AC_LANG_SOURCE([[int i;]])], [],
|
||||||
AC_LANG_SOURCE([[int i;]])
|
[supports=no])
|
||||||
], [], [supports=no])
|
|
||||||
AC_LANG_POP([C++])
|
AC_LANG_POP([C++])
|
||||||
CXXFLAGS="$saved_cxxflags"
|
CXXFLAGS="$saved_cxxflags"
|
||||||
|
|
||||||
|
|
|
@ -86,7 +86,7 @@ define SetupArchive
|
||||||
# NOTE: $2 is dependencies, not a named argument!
|
# NOTE: $2 is dependencies, not a named argument!
|
||||||
$(foreach i,3 4 5 6 7 8 9 10 11 12 13 14 15, $(if $($i),$1_$(strip $($i)))$(NEWLINE))
|
$(foreach i,3 4 5 6 7 8 9 10 11 12 13 14 15, $(if $($i),$1_$(strip $($i)))$(NEWLINE))
|
||||||
$(call LogSetupMacroEntry,SetupArchive($1),<dependencies>,$3,$4,$5,$6,$7,$8,$9,$(10),$(11),$(12),$(13),$(14),$(15))
|
$(call LogSetupMacroEntry,SetupArchive($1),<dependencies>,$3,$4,$5,$6,$7,$8,$9,$(10),$(11),$(12),$(13),$(14),$(15))
|
||||||
$(if $(findstring $(LOG_LEVEL),debug trace), $(info *[2] <dependencies> = $(strip $2)))
|
$(if $(findstring $(LOG_LEVEL),trace), $(info *[2] <dependencies> = $(strip $2)))
|
||||||
$(if $(16),$(error Internal makefile error: Too many arguments to SetupArchive, please update JavaCompilation.gmk))
|
$(if $(16),$(error Internal makefile error: Too many arguments to SetupArchive, please update JavaCompilation.gmk))
|
||||||
|
|
||||||
$1_JARMAIN:=$(strip $$($1_JARMAIN))
|
$1_JARMAIN:=$(strip $$($1_JARMAIN))
|
||||||
|
@ -111,9 +111,9 @@ define SetupArchive
|
||||||
ifeq ($$(word 20,$$($1_GREP_INCLUDE_PATTERNS)),)
|
ifeq ($$(word 20,$$($1_GREP_INCLUDE_PATTERNS)),)
|
||||||
$1_GREP_INCLUDES:=| $(GREP) $$(patsubst %,$(SPACE)-e$(SPACE)$(DQUOTE)%$(DQUOTE),$$($1_GREP_INCLUDE_PATTERNS))
|
$1_GREP_INCLUDES:=| $(GREP) $$(patsubst %,$(SPACE)-e$(SPACE)$(DQUOTE)%$(DQUOTE),$$($1_GREP_INCLUDE_PATTERNS))
|
||||||
else
|
else
|
||||||
$1_GREP_INCLUDE_OUTPUT:=$(RM) $$($1_BIN)/_the.$$($1_JARNAME)_include && \
|
$1_GREP_INCLUDE_OUTPUT:=$(RM) $$($1_BIN)/_the.$$($1_JARNAME)_include $$(NEWLINE) \
|
||||||
$$(strip $$(call ListPathsSafely,$1_GREP_INCLUDE_PATTERNS,\n, \
|
$$(call ListPathsSafely,$1_GREP_INCLUDE_PATTERNS,\n, \
|
||||||
>> $$($1_BIN)/_the.$$($1_JARNAME)_include))
|
>> $$($1_BIN)/_the.$$($1_JARNAME)_include)
|
||||||
$1_GREP_INCLUDES:=| $(GREP) -f $$($1_BIN)/_the.$$($1_JARNAME)_include
|
$1_GREP_INCLUDES:=| $(GREP) -f $$($1_BIN)/_the.$$($1_JARNAME)_include
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
@ -124,9 +124,9 @@ define SetupArchive
|
||||||
ifeq ($$(word 20,$$($1_GREP_EXCLUDE_PATTERNS)),)
|
ifeq ($$(word 20,$$($1_GREP_EXCLUDE_PATTERNS)),)
|
||||||
$1_GREP_EXCLUDES:=| $(GREP) -v $$(patsubst %,$(SPACE)-e$(SPACE)$(DQUOTE)%$(DQUOTE),$$($1_GREP_EXCLUDE_PATTERNS))
|
$1_GREP_EXCLUDES:=| $(GREP) -v $$(patsubst %,$(SPACE)-e$(SPACE)$(DQUOTE)%$(DQUOTE),$$($1_GREP_EXCLUDE_PATTERNS))
|
||||||
else
|
else
|
||||||
$1_GREP_EXCLUDE_OUTPUT=$(RM) $$($1_BIN)/_the.$$($1_JARNAME)_exclude && \
|
$1_GREP_EXCLUDE_OUTPUT=$(RM) $$($1_BIN)/_the.$$($1_JARNAME)_exclude $$(NEWLINE) \
|
||||||
$$(strip $$(call ListPathsSafely,$1_GREP_EXCLUDE_PATTERNS,\n, \
|
$$(call ListPathsSafely,$1_GREP_EXCLUDE_PATTERNS,\n, \
|
||||||
>> $$($1_BIN)/_the.$$($1_JARNAME)_exclude))
|
>> $$($1_BIN)/_the.$$($1_JARNAME)_exclude)
|
||||||
$1_GREP_EXCLUDES:=| $(GREP) -v -f $$($1_BIN)/_the.$$($1_JARNAME)_exclude
|
$1_GREP_EXCLUDES:=| $(GREP) -v -f $$($1_BIN)/_the.$$($1_JARNAME)_exclude
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
|
@ -56,7 +56,8 @@ define ListPathsSafely_If
|
||||||
endef
|
endef
|
||||||
|
|
||||||
define ListPathsSafely_Printf
|
define ListPathsSafely_Printf
|
||||||
$(if $(strip $($1_LPS$4)),printf -- "$(strip $($1_LPS$4))\n" | $(decompress_paths) $3)
|
$(if $(strip $($1_LPS$4)),$(if $(findstring $(LOG_LEVEL),trace),,@)printf \
|
||||||
|
-- "$(strip $($1_LPS$4))\n" | $(decompress_paths) $3)
|
||||||
endef
|
endef
|
||||||
|
|
||||||
# Receipt example:
|
# Receipt example:
|
||||||
|
@ -66,6 +67,7 @@ endef
|
||||||
# if instead , , (a space) is supplied, then spaces remain spaces.
|
# if instead , , (a space) is supplied, then spaces remain spaces.
|
||||||
define ListPathsSafely
|
define ListPathsSafely
|
||||||
$(if $(word 16001,$($1)),$(error Cannot list safely more than 16000 paths. $1 has $(words $($1)) paths!))
|
$(if $(word 16001,$($1)),$(error Cannot list safely more than 16000 paths. $1 has $(words $($1)) paths!))
|
||||||
|
$(ECHO) $(LOG_DEBUG) Writing $(words $($1)) paths to '$3'
|
||||||
$(call ListPathsSafely_If,$1,$2,1,250)
|
$(call ListPathsSafely_If,$1,$2,1,250)
|
||||||
$(call ListPathsSafely_If,$1,$2,251,500)
|
$(call ListPathsSafely_If,$1,$2,251,500)
|
||||||
$(call ListPathsSafely_If,$1,$2,501,750)
|
$(call ListPathsSafely_If,$1,$2,501,750)
|
||||||
|
|
|
@ -119,5 +119,3 @@ clean :
|
||||||
|
|
||||||
FORCE :
|
FORCE :
|
||||||
.PHONY : $(configs) $(platforms)
|
.PHONY : $(configs) $(platforms)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -41,7 +41,6 @@ EXCLUDE_PKGS = \
|
||||||
org.w3c.dom.stylesheets \
|
org.w3c.dom.stylesheets \
|
||||||
org.w3c.dom.traversal \
|
org.w3c.dom.traversal \
|
||||||
org.w3c.dom.ranges \
|
org.w3c.dom.ranges \
|
||||||
org.w3c.dom.views \
|
|
||||||
org.omg.stub.javax.management.remote.rmi
|
org.omg.stub.javax.management.remote.rmi
|
||||||
|
|
||||||
#
|
#
|
||||||
|
@ -295,6 +294,7 @@ CORE_PKGS = \
|
||||||
org.w3c.dom.events \
|
org.w3c.dom.events \
|
||||||
org.w3c.dom.bootstrap \
|
org.w3c.dom.bootstrap \
|
||||||
org.w3c.dom.ls \
|
org.w3c.dom.ls \
|
||||||
|
org.w3c.dom.views \
|
||||||
org.xml.sax \
|
org.xml.sax \
|
||||||
org.xml.sax.ext \
|
org.xml.sax.ext \
|
||||||
org.xml.sax.helpers
|
org.xml.sax.helpers
|
||||||
|
|
|
@ -116,8 +116,7 @@ BUG_SUBMIT_LINE = <a href="$(BUG_SUBMIT_URL)">Submit a bug or feature</a>
|
||||||
# Url to devdocs page
|
# Url to devdocs page
|
||||||
# Was: http://java.sun.com/javase/6/webnotes/devdocs-vs-specs.html
|
# Was: http://java.sun.com/javase/6/webnotes/devdocs-vs-specs.html
|
||||||
DEV_DOCS_URL-7 = http://download.oracle.com/javase/7/docs/index.html
|
DEV_DOCS_URL-7 = http://download.oracle.com/javase/7/docs/index.html
|
||||||
# This isn't added in old build yet.
|
DEV_DOCS_URL-8 = http://download.oracle.com/javase/8/docs/index.html
|
||||||
#DEV_DOCS_URL-8 = http://download.oracle.com/javase/7/docs/index.html
|
|
||||||
DEV_DOCS_URL = $(DEV_DOCS_URL-$(JDK_MINOR_VERSION))
|
DEV_DOCS_URL = $(DEV_DOCS_URL-$(JDK_MINOR_VERSION))
|
||||||
DOCS_BASE_URL = http://download.oracle.com/javase/7/docs
|
DOCS_BASE_URL = http://download.oracle.com/javase/7/docs
|
||||||
|
|
||||||
|
@ -295,6 +294,7 @@ contained herein are not final and are subject to change. \
|
||||||
The information is being made available to you solely for purpose of \
|
The information is being made available to you solely for purpose of \
|
||||||
evaluation. \
|
evaluation. \
|
||||||
</div> </div>
|
</div> </div>
|
||||||
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
#################################################################
|
#################################################################
|
||||||
|
|
|
@ -232,3 +232,4 @@ d411c60a8c2fe8fdc572af907775e90f7eefd513 jdk8-b104
|
||||||
a4bb3b4500164748a9c33b2283cfda76d89f25ab jdk8-b108
|
a4bb3b4500164748a9c33b2283cfda76d89f25ab jdk8-b108
|
||||||
428428cf5e06163322144cfb5367e1faa86acf20 jdk8-b109
|
428428cf5e06163322144cfb5367e1faa86acf20 jdk8-b109
|
||||||
3d2b7ce93c5c2e3db748f29c3d29620a8b3b748a jdk8-b110
|
3d2b7ce93c5c2e3db748f29c3d29620a8b3b748a jdk8-b110
|
||||||
|
85c1c94e723582f9a1dd0251502c42b73d6deea7 jdk8-b111
|
||||||
|
|
|
@ -144,6 +144,7 @@ $(CORBA_OUTPUTDIR)/logwrappers/_the_wrappers.d : $(CORBA_OUTPUTDIR)/btjars/logut
|
||||||
-include $(CORBA_OUTPUTDIR)/logwrappers/_the_wrappers.d
|
-include $(CORBA_OUTPUTDIR)/logwrappers/_the_wrappers.d
|
||||||
|
|
||||||
ifeq ($(LOGWRAPPERS_ARE_CREATED), yes)
|
ifeq ($(LOGWRAPPERS_ARE_CREATED), yes)
|
||||||
|
|
||||||
$(eval $(call SetupIdlCompilation,BUILD_IDLS, \
|
$(eval $(call SetupIdlCompilation,BUILD_IDLS, \
|
||||||
IDLJ := $(JAVA) -jar $(CORBA_OUTPUTDIR)/btjars/idlj.jar, \
|
IDLJ := $(JAVA) -jar $(CORBA_OUTPUTDIR)/btjars/idlj.jar, \
|
||||||
SRC := $(CORBA_TOPDIR)/src/share/classes, \
|
SRC := $(CORBA_TOPDIR)/src/share/classes, \
|
||||||
|
@ -166,6 +167,7 @@ ifeq ($(LOGWRAPPERS_ARE_CREATED),yes)
|
||||||
-include $(CORBA_OUTPUTDIR)/gensrc/_the_idls.d
|
-include $(CORBA_OUTPUTDIR)/gensrc/_the_idls.d
|
||||||
|
|
||||||
ifeq ($(IDLS_ARE_CREATED), yes)
|
ifeq ($(IDLS_ARE_CREATED), yes)
|
||||||
|
|
||||||
$(eval $(call SetupJavaCompilation,BUILD_CORBA, \
|
$(eval $(call SetupJavaCompilation,BUILD_CORBA, \
|
||||||
SETUP := GENERATE_NEWBYTECODE, \
|
SETUP := GENERATE_NEWBYTECODE, \
|
||||||
SRC := $(CORBA_TOPDIR)/src/share/classes $(CORBA_OUTPUTDIR)/gensrc $(CORBA_OUTPUTDIR)/logwrappers, \
|
SRC := $(CORBA_TOPDIR)/src/share/classes $(CORBA_OUTPUTDIR)/gensrc $(CORBA_OUTPUTDIR)/logwrappers, \
|
||||||
|
|
|
@ -384,3 +384,5 @@ c81dd5393a5e333df7cb1f6621f5897ada6522b5 jdk8-b109
|
||||||
6209b0ed51c086d4127bac0e086c8f326d1764d7 jdk8-b110
|
6209b0ed51c086d4127bac0e086c8f326d1764d7 jdk8-b110
|
||||||
562a3d356de67670b4172b82aca2d30743449e04 hs25-b53
|
562a3d356de67670b4172b82aca2d30743449e04 hs25-b53
|
||||||
f6962730bbde82f279a0ae3a1c14bc5e58096c6e jdk8-b111
|
f6962730bbde82f279a0ae3a1c14bc5e58096c6e jdk8-b111
|
||||||
|
4a845c7a463844cead9e1e1641d6bcfb8a77f1c7 hs25-b54
|
||||||
|
0ed9a90f45e1b392c671005f9ee22ce1acf02984 jdk8-b112
|
||||||
|
|
|
@ -44,6 +44,7 @@
|
||||||
// close all file descriptors
|
// close all file descriptors
|
||||||
static void close_files(struct ps_prochandle* ph) {
|
static void close_files(struct ps_prochandle* ph) {
|
||||||
lib_info* lib = NULL;
|
lib_info* lib = NULL;
|
||||||
|
|
||||||
// close core file descriptor
|
// close core file descriptor
|
||||||
if (ph->core->core_fd >= 0)
|
if (ph->core->core_fd >= 0)
|
||||||
close(ph->core->core_fd);
|
close(ph->core->core_fd);
|
||||||
|
@ -149,8 +150,7 @@ static map_info* add_class_share_map_info(struct ps_prochandle* ph, off_t offset
|
||||||
|
|
||||||
// Return the map_info for the given virtual address. We keep a sorted
|
// Return the map_info for the given virtual address. We keep a sorted
|
||||||
// array of pointers in ph->map_array, so we can binary search.
|
// array of pointers in ph->map_array, so we can binary search.
|
||||||
static map_info* core_lookup(struct ps_prochandle *ph, uintptr_t addr)
|
static map_info* core_lookup(struct ps_prochandle *ph, uintptr_t addr) {
|
||||||
{
|
|
||||||
int mid, lo = 0, hi = ph->core->num_maps - 1;
|
int mid, lo = 0, hi = ph->core->num_maps - 1;
|
||||||
map_info *mp;
|
map_info *mp;
|
||||||
|
|
||||||
|
@ -230,9 +230,9 @@ struct FileMapHeader {
|
||||||
size_t _used; // for setting space top on read
|
size_t _used; // for setting space top on read
|
||||||
|
|
||||||
// 4991491 NOTICE These are C++ bool's in filemap.hpp and must match up with
|
// 4991491 NOTICE These are C++ bool's in filemap.hpp and must match up with
|
||||||
// the C type matching the C++ bool type on any given platform. For
|
// the C type matching the C++ bool type on any given platform.
|
||||||
// Hotspot on BSD we assume the corresponding C type is char but
|
// We assume the corresponding C type is char but licensees
|
||||||
// licensees on BSD versions may need to adjust the type of these fields.
|
// may need to adjust the type of these fields.
|
||||||
char _read_only; // read only space?
|
char _read_only; // read only space?
|
||||||
char _allow_exec; // executable code in space?
|
char _allow_exec; // executable code in space?
|
||||||
|
|
||||||
|
@ -286,10 +286,12 @@ static bool read_string(struct ps_prochandle* ph, uintptr_t addr, char* buf, siz
|
||||||
#define USE_SHARED_SPACES_SYM "_UseSharedSpaces"
|
#define USE_SHARED_SPACES_SYM "_UseSharedSpaces"
|
||||||
// mangled name of Arguments::SharedArchivePath
|
// mangled name of Arguments::SharedArchivePath
|
||||||
#define SHARED_ARCHIVE_PATH_SYM "_ZN9Arguments17SharedArchivePathE"
|
#define SHARED_ARCHIVE_PATH_SYM "_ZN9Arguments17SharedArchivePathE"
|
||||||
|
#define LIBJVM_NAME "/libjvm.dylib"
|
||||||
#else
|
#else
|
||||||
#define USE_SHARED_SPACES_SYM "UseSharedSpaces"
|
#define USE_SHARED_SPACES_SYM "UseSharedSpaces"
|
||||||
// mangled name of Arguments::SharedArchivePath
|
// mangled name of Arguments::SharedArchivePath
|
||||||
#define SHARED_ARCHIVE_PATH_SYM "__ZN9Arguments17SharedArchivePathE"
|
#define SHARED_ARCHIVE_PATH_SYM "__ZN9Arguments17SharedArchivePathE"
|
||||||
|
#define LIBJVM_NAME "/libjvm.so"
|
||||||
#endif // __APPLE_
|
#endif // __APPLE_
|
||||||
|
|
||||||
static bool init_classsharing_workaround(struct ps_prochandle* ph) {
|
static bool init_classsharing_workaround(struct ps_prochandle* ph) {
|
||||||
|
@ -300,12 +302,7 @@ static bool init_classsharing_workaround(struct ps_prochandle* ph) {
|
||||||
// we are iterating over shared objects from the core dump. look for
|
// we are iterating over shared objects from the core dump. look for
|
||||||
// libjvm.so.
|
// libjvm.so.
|
||||||
const char *jvm_name = 0;
|
const char *jvm_name = 0;
|
||||||
#ifdef __APPLE__
|
if ((jvm_name = strstr(lib->name, LIBJVM_NAME)) != 0) {
|
||||||
if ((jvm_name = strstr(lib->name, "/libjvm.dylib")) != 0)
|
|
||||||
#else
|
|
||||||
if ((jvm_name = strstr(lib->name, "/libjvm.so")) != 0)
|
|
||||||
#endif // __APPLE__
|
|
||||||
{
|
|
||||||
char classes_jsa[PATH_MAX];
|
char classes_jsa[PATH_MAX];
|
||||||
struct FileMapHeader header;
|
struct FileMapHeader header;
|
||||||
int fd = -1;
|
int fd = -1;
|
||||||
|
@ -1121,7 +1118,7 @@ static bool read_core_segments(struct ps_prochandle* ph, ELF_EHDR* core_ehdr) {
|
||||||
* contains a set of saved /proc structures), and PT_LOAD (which
|
* contains a set of saved /proc structures), and PT_LOAD (which
|
||||||
* represents a memory mapping from the process's address space).
|
* represents a memory mapping from the process's address space).
|
||||||
*
|
*
|
||||||
* Difference b/w Solaris PT_NOTE and BSD PT_NOTE:
|
* Difference b/w Solaris PT_NOTE and Linux/BSD PT_NOTE:
|
||||||
*
|
*
|
||||||
* In Solaris there are two PT_NOTE segments the first PT_NOTE (if present)
|
* In Solaris there are two PT_NOTE segments the first PT_NOTE (if present)
|
||||||
* contains /proc structs in the pre-2.6 unstructured /proc format. the last
|
* contains /proc structs in the pre-2.6 unstructured /proc format. the last
|
||||||
|
@ -1171,17 +1168,46 @@ static bool read_lib_segments(struct ps_prochandle* ph, int lib_fd, ELF_EHDR* li
|
||||||
ELF_PHDR* phbuf;
|
ELF_PHDR* phbuf;
|
||||||
ELF_PHDR* lib_php = NULL;
|
ELF_PHDR* lib_php = NULL;
|
||||||
|
|
||||||
if ((phbuf = read_program_header_table(lib_fd, lib_ehdr)) == NULL)
|
int page_size=sysconf(_SC_PAGE_SIZE);
|
||||||
|
|
||||||
|
if ((phbuf = read_program_header_table(lib_fd, lib_ehdr)) == NULL) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// we want to process only PT_LOAD segments that are not writable.
|
// we want to process only PT_LOAD segments that are not writable.
|
||||||
// i.e., text segments. The read/write/exec (data) segments would
|
// i.e., text segments. The read/write/exec (data) segments would
|
||||||
// have been already added from core file segments.
|
// have been already added from core file segments.
|
||||||
for (lib_php = phbuf, i = 0; i < lib_ehdr->e_phnum; i++) {
|
for (lib_php = phbuf, i = 0; i < lib_ehdr->e_phnum; i++) {
|
||||||
if ((lib_php->p_type == PT_LOAD) && !(lib_php->p_flags & PF_W) && (lib_php->p_filesz != 0)) {
|
if ((lib_php->p_type == PT_LOAD) && !(lib_php->p_flags & PF_W) && (lib_php->p_filesz != 0)) {
|
||||||
if (add_map_info(ph, lib_fd, lib_php->p_offset, lib_php->p_vaddr + lib_base, lib_php->p_filesz) == NULL)
|
|
||||||
|
uintptr_t target_vaddr = lib_php->p_vaddr + lib_base;
|
||||||
|
map_info *existing_map = core_lookup(ph, target_vaddr);
|
||||||
|
|
||||||
|
if (existing_map == NULL){
|
||||||
|
if (add_map_info(ph, lib_fd, lib_php->p_offset,
|
||||||
|
target_vaddr, lib_php->p_filesz) == NULL) {
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
if ((existing_map->memsz != page_size) &&
|
||||||
|
(existing_map->fd != lib_fd) &&
|
||||||
|
(existing_map->memsz != lib_php->p_filesz)){
|
||||||
|
|
||||||
|
print_debug("address conflict @ 0x%lx (size = %ld, flags = %d\n)",
|
||||||
|
target_vaddr, lib_php->p_filesz, lib_php->p_flags);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* replace PT_LOAD segment with library segment */
|
||||||
|
print_debug("overwrote with new address mapping (memsz %ld -> %ld)\n",
|
||||||
|
existing_map->memsz, lib_php->p_filesz);
|
||||||
|
|
||||||
|
existing_map->fd = lib_fd;
|
||||||
|
existing_map->offset = lib_php->p_offset;
|
||||||
|
existing_map->memsz = lib_php->p_filesz;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
lib_php++;
|
lib_php++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1192,7 +1218,7 @@ err:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// process segments from interpreter (ld-elf.so.1)
|
// process segments from interpreter (ld.so or ld-linux.so or ld-elf.so)
|
||||||
static bool read_interp_segments(struct ps_prochandle* ph) {
|
static bool read_interp_segments(struct ps_prochandle* ph) {
|
||||||
ELF_EHDR interp_ehdr;
|
ELF_EHDR interp_ehdr;
|
||||||
|
|
||||||
|
@ -1309,26 +1335,28 @@ static bool read_shared_lib_info(struct ps_prochandle* ph) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// read ld_base address from struct r_debug
|
// read ld_base address from struct r_debug
|
||||||
// XXX: There is no r_ldbase member on BSD
|
#if 0 // There is no r_ldbase member on BSD
|
||||||
/*
|
|
||||||
if (ps_pread(ph, (psaddr_t) debug_base + LD_BASE_OFFSET, &ld_base_addr,
|
if (ps_pread(ph, (psaddr_t) debug_base + LD_BASE_OFFSET, &ld_base_addr,
|
||||||
sizeof(uintptr_t)) != PS_OK) {
|
sizeof(uintptr_t)) != PS_OK) {
|
||||||
print_debug("can't read ld base address\n");
|
print_debug("can't read ld base address\n");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
ph->core->ld_base_addr = ld_base_addr;
|
ph->core->ld_base_addr = ld_base_addr;
|
||||||
*/
|
#else
|
||||||
ph->core->ld_base_addr = 0;
|
ph->core->ld_base_addr = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
print_debug("interpreter base address is 0x%lx\n", ld_base_addr);
|
print_debug("interpreter base address is 0x%lx\n", ld_base_addr);
|
||||||
|
|
||||||
// now read segments from interp (i.e ld-elf.so.1)
|
// now read segments from interp (i.e ld.so or ld-linux.so or ld-elf.so)
|
||||||
if (read_interp_segments(ph) != true)
|
if (read_interp_segments(ph) != true) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// after adding interpreter (ld.so) mappings sort again
|
// after adding interpreter (ld.so) mappings sort again
|
||||||
if (sort_map_array(ph) != true)
|
if (sort_map_array(ph) != true) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
print_debug("first link map is at 0x%lx\n", first_link_map_addr);
|
print_debug("first link map is at 0x%lx\n", first_link_map_addr);
|
||||||
|
|
||||||
|
@ -1380,8 +1408,9 @@ static bool read_shared_lib_info(struct ps_prochandle* ph) {
|
||||||
add_lib_info_fd(ph, lib_name, lib_fd, lib_base);
|
add_lib_info_fd(ph, lib_name, lib_fd, lib_base);
|
||||||
// Map info is added for the library (lib_name) so
|
// Map info is added for the library (lib_name) so
|
||||||
// we need to re-sort it before calling the p_pdread.
|
// we need to re-sort it before calling the p_pdread.
|
||||||
if (sort_map_array(ph) != true)
|
if (sort_map_array(ph) != true) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
print_debug("can't read ELF header for shared object %s\n", lib_name);
|
print_debug("can't read ELF header for shared object %s\n", lib_name);
|
||||||
close(lib_fd);
|
close(lib_fd);
|
||||||
|
@ -1408,7 +1437,7 @@ struct ps_prochandle* Pgrab_core(const char* exec_file, const char* core_file) {
|
||||||
|
|
||||||
struct ps_prochandle* ph = (struct ps_prochandle*) calloc(1, sizeof(struct ps_prochandle));
|
struct ps_prochandle* ph = (struct ps_prochandle*) calloc(1, sizeof(struct ps_prochandle));
|
||||||
if (ph == NULL) {
|
if (ph == NULL) {
|
||||||
print_debug("cant allocate ps_prochandle\n");
|
print_debug("can't allocate ps_prochandle\n");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1449,33 +1478,40 @@ struct ps_prochandle* Pgrab_core(const char* exec_file, const char* core_file) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// process core file segments
|
// process core file segments
|
||||||
if (read_core_segments(ph, &core_ehdr) != true)
|
if (read_core_segments(ph, &core_ehdr) != true) {
|
||||||
goto err;
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
// process exec file segments
|
// process exec file segments
|
||||||
if (read_exec_segments(ph, &exec_ehdr) != true)
|
if (read_exec_segments(ph, &exec_ehdr) != true) {
|
||||||
goto err;
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
// exec file is also treated like a shared object for symbol search
|
// exec file is also treated like a shared object for symbol search
|
||||||
if (add_lib_info_fd(ph, exec_file, ph->core->exec_fd,
|
if (add_lib_info_fd(ph, exec_file, ph->core->exec_fd,
|
||||||
(uintptr_t)0 + find_base_address(ph->core->exec_fd, &exec_ehdr)) == NULL)
|
(uintptr_t)0 + find_base_address(ph->core->exec_fd, &exec_ehdr)) == NULL) {
|
||||||
goto err;
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
// allocate and sort maps into map_array, we need to do this
|
// allocate and sort maps into map_array, we need to do this
|
||||||
// here because read_shared_lib_info needs to read from debuggee
|
// here because read_shared_lib_info needs to read from debuggee
|
||||||
// address space
|
// address space
|
||||||
if (sort_map_array(ph) != true)
|
if (sort_map_array(ph) != true) {
|
||||||
goto err;
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
if (read_shared_lib_info(ph) != true)
|
if (read_shared_lib_info(ph) != true) {
|
||||||
goto err;
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
// sort again because we have added more mappings from shared objects
|
// sort again because we have added more mappings from shared objects
|
||||||
if (sort_map_array(ph) != true)
|
if (sort_map_array(ph) != true) {
|
||||||
goto err;
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
if (init_classsharing_workaround(ph) != true)
|
if (init_classsharing_workaround(ph) != true) {
|
||||||
goto err;
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
print_debug("Leave Pgrab_core\n");
|
print_debug("Leave Pgrab_core\n");
|
||||||
return ph;
|
return ph;
|
||||||
|
|
|
@ -41,7 +41,7 @@
|
||||||
// ps_prochandle cleanup helper functions
|
// ps_prochandle cleanup helper functions
|
||||||
|
|
||||||
// close all file descriptors
|
// close all file descriptors
|
||||||
static void close_elf_files(struct ps_prochandle* ph) {
|
static void close_files(struct ps_prochandle* ph) {
|
||||||
lib_info* lib = NULL;
|
lib_info* lib = NULL;
|
||||||
|
|
||||||
// close core file descriptor
|
// close core file descriptor
|
||||||
|
@ -64,7 +64,9 @@ static void close_elf_files(struct ps_prochandle* ph) {
|
||||||
lib = ph->libs;
|
lib = ph->libs;
|
||||||
while (lib) {
|
while (lib) {
|
||||||
int fd = lib->fd;
|
int fd = lib->fd;
|
||||||
if (fd >= 0 && fd != ph->core->exec_fd) close(fd);
|
if (fd >= 0 && fd != ph->core->exec_fd) {
|
||||||
|
close(fd);
|
||||||
|
}
|
||||||
lib = lib->next;
|
lib = lib->next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -94,7 +96,7 @@ static void destroy_map_info(struct ps_prochandle* ph) {
|
||||||
// ps_prochandle operations
|
// ps_prochandle operations
|
||||||
static void core_release(struct ps_prochandle* ph) {
|
static void core_release(struct ps_prochandle* ph) {
|
||||||
if (ph->core) {
|
if (ph->core) {
|
||||||
close_elf_files(ph);
|
close_files(ph);
|
||||||
destroy_map_info(ph);
|
destroy_map_info(ph);
|
||||||
free(ph->core);
|
free(ph->core);
|
||||||
}
|
}
|
||||||
|
@ -132,40 +134,43 @@ static map_info* add_map_info(struct ps_prochandle* ph, int fd, off_t offset,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Part of the class sharing workaround
|
// Part of the class sharing workaround
|
||||||
static void add_class_share_map_info(struct ps_prochandle* ph, off_t offset,
|
static map_info* add_class_share_map_info(struct ps_prochandle* ph, off_t offset,
|
||||||
uintptr_t vaddr, size_t memsz) {
|
uintptr_t vaddr, size_t memsz) {
|
||||||
map_info* map;
|
map_info* map;
|
||||||
if ((map = allocate_init_map(ph->core->classes_jsa_fd,
|
if ((map = allocate_init_map(ph->core->classes_jsa_fd,
|
||||||
offset, vaddr, memsz)) == NULL) {
|
offset, vaddr, memsz)) == NULL) {
|
||||||
return;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
map->next = ph->core->class_share_maps;
|
map->next = ph->core->class_share_maps;
|
||||||
ph->core->class_share_maps = map;
|
ph->core->class_share_maps = map;
|
||||||
|
return map;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return the map_info for the given virtual address. We keep a sorted
|
// Return the map_info for the given virtual address. We keep a sorted
|
||||||
// array of pointers in ph->map_array, so we can binary search.
|
// array of pointers in ph->map_array, so we can binary search.
|
||||||
static map_info* core_lookup(struct ps_prochandle *ph, uintptr_t addr)
|
static map_info* core_lookup(struct ps_prochandle *ph, uintptr_t addr) {
|
||||||
{
|
|
||||||
int mid, lo = 0, hi = ph->core->num_maps - 1;
|
int mid, lo = 0, hi = ph->core->num_maps - 1;
|
||||||
map_info *mp;
|
map_info *mp;
|
||||||
|
|
||||||
while (hi - lo > 1) {
|
while (hi - lo > 1) {
|
||||||
mid = (lo + hi) / 2;
|
mid = (lo + hi) / 2;
|
||||||
if (addr >= ph->core->map_array[mid]->vaddr)
|
if (addr >= ph->core->map_array[mid]->vaddr) {
|
||||||
lo = mid;
|
lo = mid;
|
||||||
else
|
} else {
|
||||||
hi = mid;
|
hi = mid;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (addr < ph->core->map_array[hi]->vaddr)
|
if (addr < ph->core->map_array[hi]->vaddr) {
|
||||||
mp = ph->core->map_array[lo];
|
mp = ph->core->map_array[lo];
|
||||||
else
|
} else {
|
||||||
mp = ph->core->map_array[hi];
|
mp = ph->core->map_array[hi];
|
||||||
|
}
|
||||||
|
|
||||||
if (addr >= mp->vaddr && addr < mp->vaddr + mp->memsz)
|
if (addr >= mp->vaddr && addr < mp->vaddr + mp->memsz) {
|
||||||
return (mp);
|
return (mp);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Part of the class sharing workaround
|
// Part of the class sharing workaround
|
||||||
|
@ -176,13 +181,11 @@ static map_info* core_lookup(struct ps_prochandle *ph, uintptr_t addr)
|
||||||
// want to prefer class sharing data to data from core.
|
// want to prefer class sharing data to data from core.
|
||||||
mp = ph->core->class_share_maps;
|
mp = ph->core->class_share_maps;
|
||||||
if (mp) {
|
if (mp) {
|
||||||
print_debug("can't locate map_info at 0x%lx, trying class share maps\n",
|
print_debug("can't locate map_info at 0x%lx, trying class share maps\n", addr);
|
||||||
addr);
|
|
||||||
}
|
}
|
||||||
while (mp) {
|
while (mp) {
|
||||||
if (addr >= mp->vaddr && addr < mp->vaddr + mp->memsz) {
|
if (addr >= mp->vaddr && addr < mp->vaddr + mp->memsz) {
|
||||||
print_debug("located map_info at 0x%lx from class share maps\n",
|
print_debug("located map_info at 0x%lx from class share maps\n", addr);
|
||||||
addr);
|
|
||||||
return (mp);
|
return (mp);
|
||||||
}
|
}
|
||||||
mp = mp->next;
|
mp = mp->next;
|
||||||
|
@ -226,9 +229,9 @@ struct FileMapHeader {
|
||||||
size_t _used; // for setting space top on read
|
size_t _used; // for setting space top on read
|
||||||
|
|
||||||
// 4991491 NOTICE These are C++ bool's in filemap.hpp and must match up with
|
// 4991491 NOTICE These are C++ bool's in filemap.hpp and must match up with
|
||||||
// the C type matching the C++ bool type on any given platform. For
|
// the C type matching the C++ bool type on any given platform.
|
||||||
// Hotspot on Linux we assume the corresponding C type is char but
|
// We assume the corresponding C type is char but licensees
|
||||||
// licensees on Linux versions may need to adjust the type of these fields.
|
// may need to adjust the type of these fields.
|
||||||
char _read_only; // read only space?
|
char _read_only; // read only space?
|
||||||
char _allow_exec; // executable code in space?
|
char _allow_exec; // executable code in space?
|
||||||
|
|
||||||
|
@ -249,7 +252,7 @@ static bool read_jboolean(struct ps_prochandle* ph, uintptr_t addr, jboolean* pv
|
||||||
|
|
||||||
static bool read_pointer(struct ps_prochandle* ph, uintptr_t addr, uintptr_t* pvalue) {
|
static bool read_pointer(struct ps_prochandle* ph, uintptr_t addr, uintptr_t* pvalue) {
|
||||||
uintptr_t uip;
|
uintptr_t uip;
|
||||||
if (ps_pdread(ph, (psaddr_t) addr, &uip, sizeof(uip)) == PS_OK) {
|
if (ps_pdread(ph, (psaddr_t) addr, (char *)&uip, sizeof(uip)) == PS_OK) {
|
||||||
*pvalue = uip;
|
*pvalue = uip;
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
|
@ -263,12 +266,15 @@ static bool read_string(struct ps_prochandle* ph, uintptr_t addr, char* buf, siz
|
||||||
char c = ' ';
|
char c = ' ';
|
||||||
|
|
||||||
while (c != '\0') {
|
while (c != '\0') {
|
||||||
if (ps_pdread(ph, (psaddr_t) addr, &c, sizeof(char)) != PS_OK)
|
if (ps_pdread(ph, (psaddr_t) addr, &c, sizeof(char)) != PS_OK) {
|
||||||
return false;
|
return false;
|
||||||
if (i < size - 1)
|
}
|
||||||
|
if (i < size - 1) {
|
||||||
buf[i] = c;
|
buf[i] = c;
|
||||||
else // smaller buffer
|
} else {
|
||||||
|
// smaller buffer
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
i++; addr++;
|
i++; addr++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -279,6 +285,7 @@ static bool read_string(struct ps_prochandle* ph, uintptr_t addr, char* buf, siz
|
||||||
#define USE_SHARED_SPACES_SYM "UseSharedSpaces"
|
#define USE_SHARED_SPACES_SYM "UseSharedSpaces"
|
||||||
// mangled name of Arguments::SharedArchivePath
|
// mangled name of Arguments::SharedArchivePath
|
||||||
#define SHARED_ARCHIVE_PATH_SYM "_ZN9Arguments17SharedArchivePathE"
|
#define SHARED_ARCHIVE_PATH_SYM "_ZN9Arguments17SharedArchivePathE"
|
||||||
|
#define LIBJVM_NAME "/libjvm.so"
|
||||||
|
|
||||||
static bool init_classsharing_workaround(struct ps_prochandle* ph) {
|
static bool init_classsharing_workaround(struct ps_prochandle* ph) {
|
||||||
lib_info* lib = ph->libs;
|
lib_info* lib = ph->libs;
|
||||||
|
@ -286,11 +293,12 @@ static bool init_classsharing_workaround(struct ps_prochandle* ph) {
|
||||||
// we are iterating over shared objects from the core dump. look for
|
// we are iterating over shared objects from the core dump. look for
|
||||||
// libjvm.so.
|
// libjvm.so.
|
||||||
const char *jvm_name = 0;
|
const char *jvm_name = 0;
|
||||||
if ((jvm_name = strstr(lib->name, "/libjvm.so")) != 0) {
|
if ((jvm_name = strstr(lib->name, LIBJVM_NAME)) != 0) {
|
||||||
char classes_jsa[PATH_MAX];
|
char classes_jsa[PATH_MAX];
|
||||||
struct FileMapHeader header;
|
struct FileMapHeader header;
|
||||||
|
int fd = -1;
|
||||||
|
int m = 0;
|
||||||
size_t n = 0;
|
size_t n = 0;
|
||||||
int fd = -1, m = 0;
|
|
||||||
uintptr_t base = 0, useSharedSpacesAddr = 0;
|
uintptr_t base = 0, useSharedSpacesAddr = 0;
|
||||||
uintptr_t sharedArchivePathAddrAddr = 0, sharedArchivePathAddr = 0;
|
uintptr_t sharedArchivePathAddrAddr = 0, sharedArchivePathAddr = 0;
|
||||||
jboolean useSharedSpaces = 0;
|
jboolean useSharedSpaces = 0;
|
||||||
|
@ -399,8 +407,9 @@ static int core_cmp_mapping(const void *lhsp, const void *rhsp)
|
||||||
const map_info *lhs = *((const map_info **)lhsp);
|
const map_info *lhs = *((const map_info **)lhsp);
|
||||||
const map_info *rhs = *((const map_info **)rhsp);
|
const map_info *rhs = *((const map_info **)rhsp);
|
||||||
|
|
||||||
if (lhs->vaddr == rhs->vaddr)
|
if (lhs->vaddr == rhs->vaddr) {
|
||||||
return (0);
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
return (lhs->vaddr < rhs->vaddr ? -1 : 1);
|
return (lhs->vaddr < rhs->vaddr ? -1 : 1);
|
||||||
}
|
}
|
||||||
|
@ -427,7 +436,10 @@ static bool sort_map_array(struct ps_prochandle* ph) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// sort is called twice. If this is second time, clear map array
|
// sort is called twice. If this is second time, clear map array
|
||||||
if (ph->core->map_array) free(ph->core->map_array);
|
if (ph->core->map_array) {
|
||||||
|
free(ph->core->map_array);
|
||||||
|
}
|
||||||
|
|
||||||
ph->core->map_array = array;
|
ph->core->map_array = array;
|
||||||
// sort the map_info array by base virtual address.
|
// sort the map_info array by base virtual address.
|
||||||
qsort(ph->core->map_array, ph->core->num_maps, sizeof (map_info*),
|
qsort(ph->core->map_array, ph->core->num_maps, sizeof (map_info*),
|
||||||
|
@ -460,16 +472,18 @@ static bool core_read_data(struct ps_prochandle* ph, uintptr_t addr, char *buf,
|
||||||
off_t off;
|
off_t off;
|
||||||
int fd;
|
int fd;
|
||||||
|
|
||||||
if (mp == NULL)
|
if (mp == NULL) {
|
||||||
break; /* No mapping for this address */
|
break; /* No mapping for this address */
|
||||||
|
}
|
||||||
|
|
||||||
fd = mp->fd;
|
fd = mp->fd;
|
||||||
mapoff = addr - mp->vaddr;
|
mapoff = addr - mp->vaddr;
|
||||||
len = MIN(resid, mp->memsz - mapoff);
|
len = MIN(resid, mp->memsz - mapoff);
|
||||||
off = mp->offset + mapoff;
|
off = mp->offset + mapoff;
|
||||||
|
|
||||||
if ((len = pread(fd, buf, len, off)) <= 0)
|
if ((len = pread(fd, buf, len, off)) <= 0) {
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
resid -= len;
|
resid -= len;
|
||||||
addr += len;
|
addr += len;
|
||||||
|
@ -625,9 +639,10 @@ static bool core_handle_note(struct ps_prochandle* ph, ELF_PHDR* note_phdr) {
|
||||||
notep->n_type, notep->n_descsz);
|
notep->n_type, notep->n_descsz);
|
||||||
|
|
||||||
if (notep->n_type == NT_PRSTATUS) {
|
if (notep->n_type == NT_PRSTATUS) {
|
||||||
if (core_handle_prstatus(ph, descdata, notep->n_descsz) != true)
|
if (core_handle_prstatus(ph, descdata, notep->n_descsz) != true) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
p = descdata + ROUNDUP(notep->n_descsz, 4);
|
p = descdata + ROUNDUP(notep->n_descsz, 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -654,7 +669,7 @@ static bool read_core_segments(struct ps_prochandle* ph, ELF_EHDR* core_ehdr) {
|
||||||
* contains a set of saved /proc structures), and PT_LOAD (which
|
* contains a set of saved /proc structures), and PT_LOAD (which
|
||||||
* represents a memory mapping from the process's address space).
|
* represents a memory mapping from the process's address space).
|
||||||
*
|
*
|
||||||
* Difference b/w Solaris PT_NOTE and Linux PT_NOTE:
|
* Difference b/w Solaris PT_NOTE and Linux/BSD PT_NOTE:
|
||||||
*
|
*
|
||||||
* In Solaris there are two PT_NOTE segments the first PT_NOTE (if present)
|
* In Solaris there are two PT_NOTE segments the first PT_NOTE (if present)
|
||||||
* contains /proc structs in the pre-2.6 unstructured /proc format. the last
|
* contains /proc structs in the pre-2.6 unstructured /proc format. the last
|
||||||
|
@ -674,7 +689,9 @@ static bool read_core_segments(struct ps_prochandle* ph, ELF_EHDR* core_ehdr) {
|
||||||
for (core_php = phbuf, i = 0; i < core_ehdr->e_phnum; i++) {
|
for (core_php = phbuf, i = 0; i < core_ehdr->e_phnum; i++) {
|
||||||
switch (core_php->p_type) {
|
switch (core_php->p_type) {
|
||||||
case PT_NOTE:
|
case PT_NOTE:
|
||||||
if (core_handle_note(ph, core_php) != true) goto err;
|
if (core_handle_note(ph, core_php) != true) {
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PT_LOAD: {
|
case PT_LOAD: {
|
||||||
|
@ -879,13 +896,15 @@ static bool read_shared_lib_info(struct ps_prochandle* ph) {
|
||||||
|
|
||||||
print_debug("interpreter base address is 0x%lx\n", ld_base_addr);
|
print_debug("interpreter base address is 0x%lx\n", ld_base_addr);
|
||||||
|
|
||||||
// now read segments from interp (i.e ld.so or ld-linux.so)
|
// now read segments from interp (i.e ld.so or ld-linux.so or ld-elf.so)
|
||||||
if (read_interp_segments(ph) != true)
|
if (read_interp_segments(ph) != true) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// after adding interpreter (ld.so) mappings sort again
|
// after adding interpreter (ld.so) mappings sort again
|
||||||
if (sort_map_array(ph) != true)
|
if (sort_map_array(ph) != true) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
print_debug("first link map is at 0x%lx\n", first_link_map_addr);
|
print_debug("first link map is at 0x%lx\n", first_link_map_addr);
|
||||||
|
|
||||||
|
@ -1008,33 +1027,40 @@ struct ps_prochandle* Pgrab_core(const char* exec_file, const char* core_file) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// process core file segments
|
// process core file segments
|
||||||
if (read_core_segments(ph, &core_ehdr) != true)
|
if (read_core_segments(ph, &core_ehdr) != true) {
|
||||||
goto err;
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
// process exec file segments
|
// process exec file segments
|
||||||
if (read_exec_segments(ph, &exec_ehdr) != true)
|
if (read_exec_segments(ph, &exec_ehdr) != true) {
|
||||||
goto err;
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
// exec file is also treated like a shared object for symbol search
|
// exec file is also treated like a shared object for symbol search
|
||||||
if (add_lib_info_fd(ph, exec_file, ph->core->exec_fd,
|
if (add_lib_info_fd(ph, exec_file, ph->core->exec_fd,
|
||||||
(uintptr_t)0 + find_base_address(ph->core->exec_fd, &exec_ehdr)) == NULL)
|
(uintptr_t)0 + find_base_address(ph->core->exec_fd, &exec_ehdr)) == NULL) {
|
||||||
goto err;
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
// allocate and sort maps into map_array, we need to do this
|
// allocate and sort maps into map_array, we need to do this
|
||||||
// here because read_shared_lib_info needs to read from debuggee
|
// here because read_shared_lib_info needs to read from debuggee
|
||||||
// address space
|
// address space
|
||||||
if (sort_map_array(ph) != true)
|
if (sort_map_array(ph) != true) {
|
||||||
goto err;
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
if (read_shared_lib_info(ph) != true)
|
if (read_shared_lib_info(ph) != true) {
|
||||||
goto err;
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
// sort again because we have added more mappings from shared objects
|
// sort again because we have added more mappings from shared objects
|
||||||
if (sort_map_array(ph) != true)
|
if (sort_map_array(ph) != true) {
|
||||||
goto err;
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
if (init_classsharing_workaround(ph) != true)
|
if (init_classsharing_workaround(ph) != true) {
|
||||||
goto err;
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
return ph;
|
return ph;
|
||||||
|
|
||||||
|
|
|
@ -67,6 +67,13 @@ public class Disassembler {
|
||||||
String libname = "hsdis";
|
String libname = "hsdis";
|
||||||
String arch = System.getProperty("os.arch");
|
String arch = System.getProperty("os.arch");
|
||||||
if (os.lastIndexOf("Windows", 0) != -1) {
|
if (os.lastIndexOf("Windows", 0) != -1) {
|
||||||
|
if (arch.equals("x86")) {
|
||||||
|
libname += "-i386";
|
||||||
|
} else if (arch.equals("amd64")) {
|
||||||
|
libname += "-amd64";
|
||||||
|
} else {
|
||||||
|
libname += "-" + arch;
|
||||||
|
}
|
||||||
path.append(sep + "bin" + sep);
|
path.append(sep + "bin" + sep);
|
||||||
libname += ".dll";
|
libname += ".dll";
|
||||||
} else if (os.lastIndexOf("SunOS", 0) != -1) {
|
} else if (os.lastIndexOf("SunOS", 0) != -1) {
|
||||||
|
|
|
@ -0,0 +1,56 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
package sun.jvm.hotspot.memory;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
import sun.jvm.hotspot.debugger.*;
|
||||||
|
import sun.jvm.hotspot.oops.*;
|
||||||
|
import sun.jvm.hotspot.runtime.*;
|
||||||
|
import sun.jvm.hotspot.types.*;
|
||||||
|
|
||||||
|
public class ProtectionDomainCacheEntry extends VMObject {
|
||||||
|
private static sun.jvm.hotspot.types.OopField protectionDomainField;
|
||||||
|
|
||||||
|
static {
|
||||||
|
VM.registerVMInitializedObserver(new Observer() {
|
||||||
|
public void update(Observable o, Object data) {
|
||||||
|
initialize(VM.getVM().getTypeDataBase());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private static synchronized void initialize(TypeDataBase db) {
|
||||||
|
Type type = db.lookupType("ProtectionDomainCacheEntry");
|
||||||
|
protectionDomainField = type.getOopField("_literal");
|
||||||
|
}
|
||||||
|
|
||||||
|
public ProtectionDomainCacheEntry(Address addr) {
|
||||||
|
super(addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Oop protectionDomain() {
|
||||||
|
return VM.getVM().getObjectHeap().newOop(protectionDomainField.getValue(addr));
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2001, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -32,7 +32,7 @@ import sun.jvm.hotspot.types.*;
|
||||||
|
|
||||||
public class ProtectionDomainEntry extends VMObject {
|
public class ProtectionDomainEntry extends VMObject {
|
||||||
private static AddressField nextField;
|
private static AddressField nextField;
|
||||||
private static sun.jvm.hotspot.types.OopField protectionDomainField;
|
private static AddressField pdCacheField;
|
||||||
|
|
||||||
static {
|
static {
|
||||||
VM.registerVMInitializedObserver(new Observer() {
|
VM.registerVMInitializedObserver(new Observer() {
|
||||||
|
@ -46,7 +46,7 @@ public class ProtectionDomainEntry extends VMObject {
|
||||||
Type type = db.lookupType("ProtectionDomainEntry");
|
Type type = db.lookupType("ProtectionDomainEntry");
|
||||||
|
|
||||||
nextField = type.getAddressField("_next");
|
nextField = type.getAddressField("_next");
|
||||||
protectionDomainField = type.getOopField("_protection_domain");
|
pdCacheField = type.getAddressField("_pd_cache");
|
||||||
}
|
}
|
||||||
|
|
||||||
public ProtectionDomainEntry(Address addr) {
|
public ProtectionDomainEntry(Address addr) {
|
||||||
|
@ -54,10 +54,12 @@ public class ProtectionDomainEntry extends VMObject {
|
||||||
}
|
}
|
||||||
|
|
||||||
public ProtectionDomainEntry next() {
|
public ProtectionDomainEntry next() {
|
||||||
return (ProtectionDomainEntry) VMObjectFactory.newObject(ProtectionDomainEntry.class, addr);
|
return (ProtectionDomainEntry) VMObjectFactory.newObject(ProtectionDomainEntry.class, nextField.getValue(addr));
|
||||||
}
|
}
|
||||||
|
|
||||||
public Oop protectionDomain() {
|
public Oop protectionDomain() {
|
||||||
return VM.getVM().getObjectHeap().newOop(protectionDomainField.getValue(addr));
|
ProtectionDomainCacheEntry pd_cache = (ProtectionDomainCacheEntry)
|
||||||
|
VMObjectFactory.newObject(ProtectionDomainCacheEntry.class, pdCacheField.getValue(addr));
|
||||||
|
return pd_cache.protectionDomain();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,12 +44,10 @@ public class SymbolTable extends sun.jvm.hotspot.utilities.Hashtable {
|
||||||
private static synchronized void initialize(TypeDataBase db) {
|
private static synchronized void initialize(TypeDataBase db) {
|
||||||
Type type = db.lookupType("SymbolTable");
|
Type type = db.lookupType("SymbolTable");
|
||||||
theTableField = type.getAddressField("_the_table");
|
theTableField = type.getAddressField("_the_table");
|
||||||
symbolTableSize = db.lookupIntConstant("SymbolTable::symbol_table_size").intValue();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fields
|
// Fields
|
||||||
private static AddressField theTableField;
|
private static AddressField theTableField;
|
||||||
private static int symbolTableSize;
|
|
||||||
|
|
||||||
// Accessors
|
// Accessors
|
||||||
public static SymbolTable getTheTable() {
|
public static SymbolTable getTheTable() {
|
||||||
|
@ -57,10 +55,6 @@ public class SymbolTable extends sun.jvm.hotspot.utilities.Hashtable {
|
||||||
return (SymbolTable) VMObjectFactory.newObject(SymbolTable.class, tmp);
|
return (SymbolTable) VMObjectFactory.newObject(SymbolTable.class, tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int getSymbolTableSize() {
|
|
||||||
return symbolTableSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
public SymbolTable(Address addr) {
|
public SymbolTable(Address addr) {
|
||||||
super(addr);
|
super(addr);
|
||||||
}
|
}
|
||||||
|
|
|
@ -59,6 +59,7 @@ public abstract class AbstractHeapGraphWriter implements HeapGraphWriter {
|
||||||
|
|
||||||
public boolean doObj(Oop oop) {
|
public boolean doObj(Oop oop) {
|
||||||
try {
|
try {
|
||||||
|
writeHeapRecordPrologue();
|
||||||
if (oop instanceof TypeArray) {
|
if (oop instanceof TypeArray) {
|
||||||
writePrimitiveArray((TypeArray)oop);
|
writePrimitiveArray((TypeArray)oop);
|
||||||
} else if (oop instanceof ObjArray) {
|
} else if (oop instanceof ObjArray) {
|
||||||
|
@ -97,6 +98,7 @@ public abstract class AbstractHeapGraphWriter implements HeapGraphWriter {
|
||||||
// not-a-Java-visible oop
|
// not-a-Java-visible oop
|
||||||
writeInternalObject(oop);
|
writeInternalObject(oop);
|
||||||
}
|
}
|
||||||
|
writeHeapRecordEpilogue();
|
||||||
} catch (IOException exp) {
|
} catch (IOException exp) {
|
||||||
throw new RuntimeException(exp);
|
throw new RuntimeException(exp);
|
||||||
}
|
}
|
||||||
|
@ -416,6 +418,12 @@ public abstract class AbstractHeapGraphWriter implements HeapGraphWriter {
|
||||||
protected void writeHeapFooter() throws IOException {
|
protected void writeHeapFooter() throws IOException {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void writeHeapRecordPrologue() throws IOException {
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void writeHeapRecordEpilogue() throws IOException {
|
||||||
|
}
|
||||||
|
|
||||||
// HeapVisitor, OopVisitor methods can't throw any non-runtime
|
// HeapVisitor, OopVisitor methods can't throw any non-runtime
|
||||||
// exception. But, derived class write methods (which are called
|
// exception. But, derived class write methods (which are called
|
||||||
// from visitor callbacks) may throw IOException. Hence, we throw
|
// from visitor callbacks) may throw IOException. Hence, we throw
|
||||||
|
|
|
@ -44,7 +44,7 @@ import sun.jvm.hotspot.runtime.*;
|
||||||
* WARNING: This format is still under development, and is subject to
|
* WARNING: This format is still under development, and is subject to
|
||||||
* change without notice.
|
* change without notice.
|
||||||
*
|
*
|
||||||
* header "JAVA PROFILE 1.0.1" (0-terminated)
|
* header "JAVA PROFILE 1.0.1" or "JAVA PROFILE 1.0.2" (0-terminated)
|
||||||
* u4 size of identifiers. Identifiers are used to represent
|
* u4 size of identifiers. Identifiers are used to represent
|
||||||
* UTF8 strings, objects, stack traces, etc. They usually
|
* UTF8 strings, objects, stack traces, etc. They usually
|
||||||
* have the same size as host pointers. For example, on
|
* have the same size as host pointers. For example, on
|
||||||
|
@ -292,11 +292,34 @@ import sun.jvm.hotspot.runtime.*;
|
||||||
* 0x00000002: cpu sampling on/off
|
* 0x00000002: cpu sampling on/off
|
||||||
* u2 stack trace depth
|
* u2 stack trace depth
|
||||||
*
|
*
|
||||||
|
*
|
||||||
|
* When the header is "JAVA PROFILE 1.0.2" a heap dump can optionally
|
||||||
|
* be generated as a sequence of heap dump segments. This sequence is
|
||||||
|
* terminated by an end record. The additional tags allowed by format
|
||||||
|
* "JAVA PROFILE 1.0.2" are:
|
||||||
|
*
|
||||||
|
* HPROF_HEAP_DUMP_SEGMENT denote a heap dump segment
|
||||||
|
*
|
||||||
|
* [heap dump sub-records]*
|
||||||
|
* The same sub-record types allowed by HPROF_HEAP_DUMP
|
||||||
|
*
|
||||||
|
* HPROF_HEAP_DUMP_END denotes the end of a heap dump
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class HeapHprofBinWriter extends AbstractHeapGraphWriter {
|
public class HeapHprofBinWriter extends AbstractHeapGraphWriter {
|
||||||
|
|
||||||
|
// The heap size threshold used to determine if segmented format
|
||||||
|
// ("JAVA PROFILE 1.0.2") should be used.
|
||||||
|
private static final long HPROF_SEGMENTED_HEAP_DUMP_THRESHOLD = 2L * 0x40000000;
|
||||||
|
|
||||||
|
// The approximate size of a heap segment. Used to calculate when to create
|
||||||
|
// a new segment.
|
||||||
|
private static final long HPROF_SEGMENTED_HEAP_DUMP_SEGMENT_SIZE = 1L * 0x40000000;
|
||||||
|
|
||||||
// hprof binary file header
|
// hprof binary file header
|
||||||
private static final String HPROF_HEADER = "JAVA PROFILE 1.0.1";
|
private static final String HPROF_HEADER_1_0_1 = "JAVA PROFILE 1.0.1";
|
||||||
|
private static final String HPROF_HEADER_1_0_2 = "JAVA PROFILE 1.0.2";
|
||||||
|
|
||||||
// constants in enum HprofTag
|
// constants in enum HprofTag
|
||||||
private static final int HPROF_UTF8 = 0x01;
|
private static final int HPROF_UTF8 = 0x01;
|
||||||
|
@ -312,6 +335,10 @@ public class HeapHprofBinWriter extends AbstractHeapGraphWriter {
|
||||||
private static final int HPROF_CPU_SAMPLES = 0x0D;
|
private static final int HPROF_CPU_SAMPLES = 0x0D;
|
||||||
private static final int HPROF_CONTROL_SETTINGS = 0x0E;
|
private static final int HPROF_CONTROL_SETTINGS = 0x0E;
|
||||||
|
|
||||||
|
// 1.0.2 record types
|
||||||
|
private static final int HPROF_HEAP_DUMP_SEGMENT = 0x1C;
|
||||||
|
private static final int HPROF_HEAP_DUMP_END = 0x2C;
|
||||||
|
|
||||||
// Heap dump constants
|
// Heap dump constants
|
||||||
// constants in enum HprofGcTag
|
// constants in enum HprofGcTag
|
||||||
private static final int HPROF_GC_ROOT_UNKNOWN = 0xFF;
|
private static final int HPROF_GC_ROOT_UNKNOWN = 0xFF;
|
||||||
|
@ -352,11 +379,9 @@ public class HeapHprofBinWriter extends AbstractHeapGraphWriter {
|
||||||
private static final int JVM_SIGNATURE_ARRAY = '[';
|
private static final int JVM_SIGNATURE_ARRAY = '[';
|
||||||
private static final int JVM_SIGNATURE_CLASS = 'L';
|
private static final int JVM_SIGNATURE_CLASS = 'L';
|
||||||
|
|
||||||
|
|
||||||
public synchronized void write(String fileName) throws IOException {
|
public synchronized void write(String fileName) throws IOException {
|
||||||
// open file stream and create buffered data output stream
|
// open file stream and create buffered data output stream
|
||||||
FileOutputStream fos = new FileOutputStream(fileName);
|
fos = new FileOutputStream(fileName);
|
||||||
FileChannel chn = fos.getChannel();
|
|
||||||
out = new DataOutputStream(new BufferedOutputStream(fos));
|
out = new DataOutputStream(new BufferedOutputStream(fos));
|
||||||
|
|
||||||
VM vm = VM.getVM();
|
VM vm = VM.getVM();
|
||||||
|
@ -385,6 +410,9 @@ public class HeapHprofBinWriter extends AbstractHeapGraphWriter {
|
||||||
FLOAT_SIZE = objectHeap.getFloatSize();
|
FLOAT_SIZE = objectHeap.getFloatSize();
|
||||||
DOUBLE_SIZE = objectHeap.getDoubleSize();
|
DOUBLE_SIZE = objectHeap.getDoubleSize();
|
||||||
|
|
||||||
|
// Check weather we should dump the heap as segments
|
||||||
|
useSegmentedHeapDump = vm.getUniverse().heap().used() > HPROF_SEGMENTED_HEAP_DUMP_THRESHOLD;
|
||||||
|
|
||||||
// hprof bin format header
|
// hprof bin format header
|
||||||
writeFileHeader();
|
writeFileHeader();
|
||||||
|
|
||||||
|
@ -394,38 +422,87 @@ public class HeapHprofBinWriter extends AbstractHeapGraphWriter {
|
||||||
|
|
||||||
// hprof UTF-8 symbols section
|
// hprof UTF-8 symbols section
|
||||||
writeSymbols();
|
writeSymbols();
|
||||||
|
|
||||||
// HPROF_LOAD_CLASS records for all classes
|
// HPROF_LOAD_CLASS records for all classes
|
||||||
writeClasses();
|
writeClasses();
|
||||||
|
|
||||||
// write heap data now
|
|
||||||
out.writeByte((byte)HPROF_HEAP_DUMP);
|
|
||||||
out.writeInt(0); // relative timestamp
|
|
||||||
|
|
||||||
// remember position of dump length, we will fixup
|
|
||||||
// length later - hprof format requires length.
|
|
||||||
out.flush();
|
|
||||||
long dumpStart = chn.position();
|
|
||||||
|
|
||||||
// write dummy length of 0 and we'll fix it later.
|
|
||||||
out.writeInt(0);
|
|
||||||
|
|
||||||
// write CLASS_DUMP records
|
// write CLASS_DUMP records
|
||||||
writeClassDumpRecords();
|
writeClassDumpRecords();
|
||||||
|
|
||||||
// this will write heap data into the buffer stream
|
// this will write heap data into the buffer stream
|
||||||
super.write();
|
super.write();
|
||||||
|
|
||||||
|
// flush buffer stream.
|
||||||
|
out.flush();
|
||||||
|
|
||||||
|
// Fill in final length
|
||||||
|
fillInHeapRecordLength();
|
||||||
|
|
||||||
|
if (useSegmentedHeapDump) {
|
||||||
|
// Write heap segment-end record
|
||||||
|
out.writeByte((byte) HPROF_HEAP_DUMP_END);
|
||||||
|
out.writeInt(0);
|
||||||
|
out.writeInt(0);
|
||||||
|
}
|
||||||
|
|
||||||
// flush buffer stream and throw it.
|
// flush buffer stream and throw it.
|
||||||
out.flush();
|
out.flush();
|
||||||
out = null;
|
out = null;
|
||||||
|
|
||||||
|
// close the file stream
|
||||||
|
fos.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void writeHeapRecordPrologue() throws IOException {
|
||||||
|
if (currentSegmentStart == 0) {
|
||||||
|
// write heap data header, depending on heap size use segmented heap
|
||||||
|
// format
|
||||||
|
out.writeByte((byte) (useSegmentedHeapDump ? HPROF_HEAP_DUMP_SEGMENT
|
||||||
|
: HPROF_HEAP_DUMP));
|
||||||
|
out.writeInt(0);
|
||||||
|
|
||||||
|
// remember position of dump length, we will fixup
|
||||||
|
// length later - hprof format requires length.
|
||||||
|
out.flush();
|
||||||
|
currentSegmentStart = fos.getChannel().position();
|
||||||
|
|
||||||
|
// write dummy length of 0 and we'll fix it later.
|
||||||
|
out.writeInt(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void writeHeapRecordEpilogue() throws IOException {
|
||||||
|
if (useSegmentedHeapDump) {
|
||||||
|
out.flush();
|
||||||
|
if ((fos.getChannel().position() - currentSegmentStart - 4) >= HPROF_SEGMENTED_HEAP_DUMP_SEGMENT_SIZE) {
|
||||||
|
fillInHeapRecordLength();
|
||||||
|
currentSegmentStart = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void fillInHeapRecordLength() throws IOException {
|
||||||
|
|
||||||
// now get current position to calculate length
|
// now get current position to calculate length
|
||||||
long dumpEnd = chn.position();
|
long dumpEnd = fos.getChannel().position();
|
||||||
|
|
||||||
// calculate length of heap data
|
// calculate length of heap data
|
||||||
int dumpLen = (int) (dumpEnd - dumpStart - 4);
|
long dumpLenLong = (dumpEnd - currentSegmentStart - 4L);
|
||||||
|
|
||||||
|
// Check length boundary, overflow could happen but is _very_ unlikely
|
||||||
|
if(dumpLenLong >= (4L * 0x40000000)){
|
||||||
|
throw new RuntimeException("Heap segment size overflow.");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save the current position
|
||||||
|
long currentPosition = fos.getChannel().position();
|
||||||
|
|
||||||
// seek the position to write length
|
// seek the position to write length
|
||||||
chn.position(dumpStart);
|
fos.getChannel().position(currentSegmentStart);
|
||||||
|
|
||||||
|
int dumpLen = (int) dumpLenLong;
|
||||||
|
|
||||||
// write length as integer
|
// write length as integer
|
||||||
fos.write((dumpLen >>> 24) & 0xFF);
|
fos.write((dumpLen >>> 24) & 0xFF);
|
||||||
|
@ -433,8 +510,8 @@ public class HeapHprofBinWriter extends AbstractHeapGraphWriter {
|
||||||
fos.write((dumpLen >>> 8) & 0xFF);
|
fos.write((dumpLen >>> 8) & 0xFF);
|
||||||
fos.write((dumpLen >>> 0) & 0xFF);
|
fos.write((dumpLen >>> 0) & 0xFF);
|
||||||
|
|
||||||
// close the file stream
|
//Reset to previous current position
|
||||||
fos.close();
|
fos.getChannel().position(currentPosition);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void writeClassDumpRecords() throws IOException {
|
private void writeClassDumpRecords() throws IOException {
|
||||||
|
@ -443,7 +520,9 @@ public class HeapHprofBinWriter extends AbstractHeapGraphWriter {
|
||||||
sysDict.allClassesDo(new SystemDictionary.ClassVisitor() {
|
sysDict.allClassesDo(new SystemDictionary.ClassVisitor() {
|
||||||
public void visit(Klass k) {
|
public void visit(Klass k) {
|
||||||
try {
|
try {
|
||||||
|
writeHeapRecordPrologue();
|
||||||
writeClassDumpRecord(k);
|
writeClassDumpRecord(k);
|
||||||
|
writeHeapRecordEpilogue();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
|
@ -884,7 +963,12 @@ public class HeapHprofBinWriter extends AbstractHeapGraphWriter {
|
||||||
// writes hprof binary file header
|
// writes hprof binary file header
|
||||||
private void writeFileHeader() throws IOException {
|
private void writeFileHeader() throws IOException {
|
||||||
// version string
|
// version string
|
||||||
out.writeBytes(HPROF_HEADER);
|
if(useSegmentedHeapDump) {
|
||||||
|
out.writeBytes(HPROF_HEADER_1_0_2);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
out.writeBytes(HPROF_HEADER_1_0_1);
|
||||||
|
}
|
||||||
out.writeByte((byte)'\0');
|
out.writeByte((byte)'\0');
|
||||||
|
|
||||||
// write identifier size. we use pointers as identifiers.
|
// write identifier size. we use pointers as identifiers.
|
||||||
|
@ -976,6 +1060,7 @@ public class HeapHprofBinWriter extends AbstractHeapGraphWriter {
|
||||||
private static final int EMPTY_FRAME_DEPTH = -1;
|
private static final int EMPTY_FRAME_DEPTH = -1;
|
||||||
|
|
||||||
private DataOutputStream out;
|
private DataOutputStream out;
|
||||||
|
private FileOutputStream fos;
|
||||||
private Debugger dbg;
|
private Debugger dbg;
|
||||||
private ObjectHeap objectHeap;
|
private ObjectHeap objectHeap;
|
||||||
private SymbolTable symTbl;
|
private SymbolTable symTbl;
|
||||||
|
@ -983,6 +1068,10 @@ public class HeapHprofBinWriter extends AbstractHeapGraphWriter {
|
||||||
// oopSize of the debuggee
|
// oopSize of the debuggee
|
||||||
private int OBJ_ID_SIZE;
|
private int OBJ_ID_SIZE;
|
||||||
|
|
||||||
|
// Added for hprof file format 1.0.2 support
|
||||||
|
private boolean useSegmentedHeapDump;
|
||||||
|
private long currentSegmentStart;
|
||||||
|
|
||||||
private long BOOLEAN_BASE_OFFSET;
|
private long BOOLEAN_BASE_OFFSET;
|
||||||
private long BYTE_BASE_OFFSET;
|
private long BYTE_BASE_OFFSET;
|
||||||
private long CHAR_BASE_OFFSET;
|
private long CHAR_BASE_OFFSET;
|
||||||
|
@ -1005,6 +1094,7 @@ public class HeapHprofBinWriter extends AbstractHeapGraphWriter {
|
||||||
private static class ClassData {
|
private static class ClassData {
|
||||||
int instSize;
|
int instSize;
|
||||||
List fields;
|
List fields;
|
||||||
|
|
||||||
ClassData(int instSize, List fields) {
|
ClassData(int instSize, List fields) {
|
||||||
this.instSize = instSize;
|
this.instSize = instSize;
|
||||||
this.fields = fields;
|
this.fields = fields;
|
||||||
|
|
|
@ -35,7 +35,7 @@ HOTSPOT_VM_COPYRIGHT=Copyright 2013
|
||||||
|
|
||||||
HS_MAJOR_VER=25
|
HS_MAJOR_VER=25
|
||||||
HS_MINOR_VER=0
|
HS_MINOR_VER=0
|
||||||
HS_BUILD_NUMBER=53
|
HS_BUILD_NUMBER=54
|
||||||
|
|
||||||
JDK_MAJOR_VER=1
|
JDK_MAJOR_VER=1
|
||||||
JDK_MINOR_VER=8
|
JDK_MINOR_VER=8
|
||||||
|
|
|
@ -44,6 +44,7 @@ CXX=cl.exe
|
||||||
# /GS Inserts security stack checks in some functions (VS2005 default)
|
# /GS Inserts security stack checks in some functions (VS2005 default)
|
||||||
# /Oi Use intrinsics (in /O2)
|
# /Oi Use intrinsics (in /O2)
|
||||||
# /Od Disable all optimizations
|
# /Od Disable all optimizations
|
||||||
|
# /MP Use multiple cores for compilation
|
||||||
#
|
#
|
||||||
# NOTE: Normally following any of the above with a '-' will turn off that flag
|
# NOTE: Normally following any of the above with a '-' will turn off that flag
|
||||||
#
|
#
|
||||||
|
@ -208,6 +209,7 @@ FASTDEBUG_OPT_OPTION = /O2 /Oy-
|
||||||
DEBUG_OPT_OPTION = /Od
|
DEBUG_OPT_OPTION = /Od
|
||||||
GX_OPTION = /EHsc
|
GX_OPTION = /EHsc
|
||||||
LD_FLAGS = /manifest $(LD_FLAGS)
|
LD_FLAGS = /manifest $(LD_FLAGS)
|
||||||
|
MP_FLAG = /MP
|
||||||
# Manifest Tool - used in VS2005 and later to adjust manifests stored
|
# Manifest Tool - used in VS2005 and later to adjust manifests stored
|
||||||
# as resources inside build artifacts.
|
# as resources inside build artifacts.
|
||||||
!if "x$(MT)" == "x"
|
!if "x$(MT)" == "x"
|
||||||
|
@ -222,6 +224,7 @@ FASTDEBUG_OPT_OPTION = /O2 /Oy-
|
||||||
DEBUG_OPT_OPTION = /Od
|
DEBUG_OPT_OPTION = /Od
|
||||||
GX_OPTION = /EHsc
|
GX_OPTION = /EHsc
|
||||||
LD_FLAGS = /manifest $(LD_FLAGS)
|
LD_FLAGS = /manifest $(LD_FLAGS)
|
||||||
|
MP_FLAG = /MP
|
||||||
# Manifest Tool - used in VS2005 and later to adjust manifests stored
|
# Manifest Tool - used in VS2005 and later to adjust manifests stored
|
||||||
# as resources inside build artifacts.
|
# as resources inside build artifacts.
|
||||||
!if "x$(MT)" == "x"
|
!if "x$(MT)" == "x"
|
||||||
|
@ -238,6 +241,7 @@ FASTDEBUG_OPT_OPTION = /O2 /Oy-
|
||||||
DEBUG_OPT_OPTION = /Od
|
DEBUG_OPT_OPTION = /Od
|
||||||
GX_OPTION = /EHsc
|
GX_OPTION = /EHsc
|
||||||
LD_FLAGS = /manifest $(LD_FLAGS)
|
LD_FLAGS = /manifest $(LD_FLAGS)
|
||||||
|
MP_FLAG = /MP
|
||||||
# Manifest Tool - used in VS2005 and later to adjust manifests stored
|
# Manifest Tool - used in VS2005 and later to adjust manifests stored
|
||||||
# as resources inside build artifacts.
|
# as resources inside build artifacts.
|
||||||
!if "x$(MT)" == "x"
|
!if "x$(MT)" == "x"
|
||||||
|
@ -250,6 +254,8 @@ SAFESEH_FLAG = /SAFESEH
|
||||||
LD_FLAGS = $(SAFESEH_FLAG) $(LD_FLAGS)
|
LD_FLAGS = $(SAFESEH_FLAG) $(LD_FLAGS)
|
||||||
!endif
|
!endif
|
||||||
|
|
||||||
|
CXX_FLAGS = $(CXX_FLAGS) $(MP_FLAG)
|
||||||
|
|
||||||
# If NO_OPTIMIZATIONS is defined in the environment, turn everything off
|
# If NO_OPTIMIZATIONS is defined in the environment, turn everything off
|
||||||
!ifdef NO_OPTIMIZATIONS
|
!ifdef NO_OPTIMIZATIONS
|
||||||
PRODUCT_OPT_OPTION = $(DEBUG_OPT_OPTION)
|
PRODUCT_OPT_OPTION = $(DEBUG_OPT_OPTION)
|
||||||
|
|
|
@ -38,7 +38,7 @@ default:: $(BUILD_PCH_FILE) $(AOUT) checkAndBuildSA
|
||||||
!include ../local.make
|
!include ../local.make
|
||||||
!include compile.make
|
!include compile.make
|
||||||
|
|
||||||
CXX_FLAGS=$(CXX_FLAGS) $(FASTDEBUG_OPT_OPTION) /D "CHECK_UNHANDLED_OOPS"
|
CXX_FLAGS=$(CXX_FLAGS) $(FASTDEBUG_OPT_OPTION)
|
||||||
|
|
||||||
!include $(WorkSpace)/make/windows/makefiles/vm.make
|
!include $(WorkSpace)/make/windows/makefiles/vm.make
|
||||||
!include local.make
|
!include local.make
|
||||||
|
|
|
@ -102,7 +102,10 @@ SA_CFLAGS = $(SA_CFLAGS) -ZI
|
||||||
!if "$(MT)" != ""
|
!if "$(MT)" != ""
|
||||||
SA_LD_FLAGS = -manifest $(SA_LD_FLAGS)
|
SA_LD_FLAGS = -manifest $(SA_LD_FLAGS)
|
||||||
!endif
|
!endif
|
||||||
SASRCFILE = $(AGENT_DIR)/src/os/win32/windbg/sawindbg.cpp
|
|
||||||
|
SASRCFILES = $(AGENT_DIR)/src/os/win32/windbg/sawindbg.cpp \
|
||||||
|
$(AGENT_DIR)/src/share/native/sadis.c
|
||||||
|
|
||||||
SA_LFLAGS = $(SA_LD_FLAGS) -nologo -subsystem:console -machine:$(MACHINE)
|
SA_LFLAGS = $(SA_LD_FLAGS) -nologo -subsystem:console -machine:$(MACHINE)
|
||||||
!if "$(ENABLE_FULL_DEBUG_SYMBOLS)" == "1"
|
!if "$(ENABLE_FULL_DEBUG_SYMBOLS)" == "1"
|
||||||
SA_LFLAGS = $(SA_LFLAGS) -map -debug
|
SA_LFLAGS = $(SA_LFLAGS) -map -debug
|
||||||
|
@ -111,22 +114,24 @@ SA_LFLAGS = $(SA_LFLAGS) -map -debug
|
||||||
SA_LFLAGS = $(SAFESEH_FLAG) $(SA_LFLAGS)
|
SA_LFLAGS = $(SAFESEH_FLAG) $(SA_LFLAGS)
|
||||||
!endif
|
!endif
|
||||||
|
|
||||||
|
SA_CFLAGS = $(SA_CFLAGS) $(MP_FLAG)
|
||||||
|
|
||||||
# Note that we do not keep sawindbj.obj around as it would then
|
# Note that we do not keep sawindbj.obj around as it would then
|
||||||
# get included in the dumpbin command in build_vm_def.sh
|
# get included in the dumpbin command in build_vm_def.sh
|
||||||
|
|
||||||
# In VS2005 or VS2008 the link command creates a .manifest file that we want
|
# In VS2005 or VS2008 the link command creates a .manifest file that we want
|
||||||
# to insert into the linked artifact so we do not need to track it separately.
|
# to insert into the linked artifact so we do not need to track it separately.
|
||||||
# Use ";#2" for .dll and ";#1" for .exe in the MT command below:
|
# Use ";#2" for .dll and ";#1" for .exe in the MT command below:
|
||||||
$(SAWINDBG): $(SASRCFILE)
|
$(SAWINDBG): $(SASRCFILES)
|
||||||
set INCLUDE=$(SA_INCLUDE)$(INCLUDE)
|
set INCLUDE=$(SA_INCLUDE)$(INCLUDE)
|
||||||
$(CXX) @<<
|
$(CXX) @<<
|
||||||
-I"$(BootStrapDir)/include" -I"$(BootStrapDir)/include/win32"
|
-I"$(BootStrapDir)/include" -I"$(BootStrapDir)/include/win32"
|
||||||
-I"$(GENERATED)" $(SA_CFLAGS)
|
-I"$(GENERATED)" $(SA_CFLAGS)
|
||||||
$(SASRCFILE)
|
$(SASRCFILES)
|
||||||
-out:$*.obj
|
-out:$*.obj
|
||||||
<<
|
<<
|
||||||
set LIB=$(SA_LIB)$(LIB)
|
set LIB=$(SA_LIB)$(LIB)
|
||||||
$(LD) -out:$@ -DLL $*.obj dbgeng.lib $(SA_LFLAGS)
|
$(LD) -out:$@ -DLL sawindbg.obj sadis.obj dbgeng.lib $(SA_LFLAGS)
|
||||||
!if "$(MT)" != ""
|
!if "$(MT)" != ""
|
||||||
$(MT) -manifest $(@F).manifest -outputresource:$(@F);#2
|
$(MT) -manifest $(@F).manifest -outputresource:$(@F);#2
|
||||||
!endif
|
!endif
|
||||||
|
|
|
@ -37,6 +37,9 @@
|
||||||
#include "runtime/vframeArray.hpp"
|
#include "runtime/vframeArray.hpp"
|
||||||
#include "utilities/macros.hpp"
|
#include "utilities/macros.hpp"
|
||||||
#include "vmreg_sparc.inline.hpp"
|
#include "vmreg_sparc.inline.hpp"
|
||||||
|
#if INCLUDE_ALL_GCS
|
||||||
|
#include "gc_implementation/g1/g1SATBCardTableModRefBS.hpp"
|
||||||
|
#endif
|
||||||
|
|
||||||
// Implementation of StubAssembler
|
// Implementation of StubAssembler
|
||||||
|
|
||||||
|
@ -912,7 +915,7 @@ OopMapSet* Runtime1::generate_code_for(StubID id, StubAssembler* sasm) {
|
||||||
Register tmp2 = G3_scratch;
|
Register tmp2 = G3_scratch;
|
||||||
jbyte* byte_map_base = ((CardTableModRefBS*)bs)->byte_map_base;
|
jbyte* byte_map_base = ((CardTableModRefBS*)bs)->byte_map_base;
|
||||||
|
|
||||||
Label not_already_dirty, restart, refill;
|
Label not_already_dirty, restart, refill, young_card;
|
||||||
|
|
||||||
#ifdef _LP64
|
#ifdef _LP64
|
||||||
__ srlx(addr, CardTableModRefBS::card_shift, addr);
|
__ srlx(addr, CardTableModRefBS::card_shift, addr);
|
||||||
|
@ -924,9 +927,15 @@ OopMapSet* Runtime1::generate_code_for(StubID id, StubAssembler* sasm) {
|
||||||
__ set(rs, cardtable); // cardtable := <card table base>
|
__ set(rs, cardtable); // cardtable := <card table base>
|
||||||
__ ldub(addr, cardtable, tmp); // tmp := [addr + cardtable]
|
__ ldub(addr, cardtable, tmp); // tmp := [addr + cardtable]
|
||||||
|
|
||||||
|
__ cmp_and_br_short(tmp, G1SATBCardTableModRefBS::g1_young_card_val(), Assembler::equal, Assembler::pt, young_card);
|
||||||
|
|
||||||
|
__ membar(Assembler::Membar_mask_bits(Assembler::StoreLoad));
|
||||||
|
__ ldub(addr, cardtable, tmp); // tmp := [addr + cardtable]
|
||||||
|
|
||||||
assert(CardTableModRefBS::dirty_card_val() == 0, "otherwise check this code");
|
assert(CardTableModRefBS::dirty_card_val() == 0, "otherwise check this code");
|
||||||
__ cmp_and_br_short(tmp, G0, Assembler::notEqual, Assembler::pt, not_already_dirty);
|
__ cmp_and_br_short(tmp, G0, Assembler::notEqual, Assembler::pt, not_already_dirty);
|
||||||
|
|
||||||
|
__ bind(young_card);
|
||||||
// We didn't take the branch, so we're already dirty: return.
|
// We didn't take the branch, so we're already dirty: return.
|
||||||
// Use return-from-leaf
|
// Use return-from-leaf
|
||||||
__ retl();
|
__ retl();
|
||||||
|
|
|
@ -3752,7 +3752,7 @@ static void generate_dirty_card_log_enqueue(jbyte* byte_map_base) {
|
||||||
#define __ masm.
|
#define __ masm.
|
||||||
address start = __ pc();
|
address start = __ pc();
|
||||||
|
|
||||||
Label not_already_dirty, restart, refill;
|
Label not_already_dirty, restart, refill, young_card;
|
||||||
|
|
||||||
#ifdef _LP64
|
#ifdef _LP64
|
||||||
__ srlx(O0, CardTableModRefBS::card_shift, O0);
|
__ srlx(O0, CardTableModRefBS::card_shift, O0);
|
||||||
|
@ -3763,9 +3763,15 @@ static void generate_dirty_card_log_enqueue(jbyte* byte_map_base) {
|
||||||
__ set(addrlit, O1); // O1 := <card table base>
|
__ set(addrlit, O1); // O1 := <card table base>
|
||||||
__ ldub(O0, O1, O2); // O2 := [O0 + O1]
|
__ ldub(O0, O1, O2); // O2 := [O0 + O1]
|
||||||
|
|
||||||
|
__ cmp_and_br_short(O2, G1SATBCardTableModRefBS::g1_young_card_val(), Assembler::equal, Assembler::pt, young_card);
|
||||||
|
|
||||||
|
__ membar(Assembler::Membar_mask_bits(Assembler::StoreLoad));
|
||||||
|
__ ldub(O0, O1, O2); // O2 := [O0 + O1]
|
||||||
|
|
||||||
assert(CardTableModRefBS::dirty_card_val() == 0, "otherwise check this code");
|
assert(CardTableModRefBS::dirty_card_val() == 0, "otherwise check this code");
|
||||||
__ cmp_and_br_short(O2, G0, Assembler::notEqual, Assembler::pt, not_already_dirty);
|
__ cmp_and_br_short(O2, G0, Assembler::notEqual, Assembler::pt, not_already_dirty);
|
||||||
|
|
||||||
|
__ bind(young_card);
|
||||||
// We didn't take the branch, so we're already dirty: return.
|
// We didn't take the branch, so we're already dirty: return.
|
||||||
// Use return-from-leaf
|
// Use return-from-leaf
|
||||||
__ retl();
|
__ retl();
|
||||||
|
|
|
@ -38,6 +38,9 @@
|
||||||
#include "runtime/vframeArray.hpp"
|
#include "runtime/vframeArray.hpp"
|
||||||
#include "utilities/macros.hpp"
|
#include "utilities/macros.hpp"
|
||||||
#include "vmreg_x86.inline.hpp"
|
#include "vmreg_x86.inline.hpp"
|
||||||
|
#if INCLUDE_ALL_GCS
|
||||||
|
#include "gc_implementation/g1/g1SATBCardTableModRefBS.hpp"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
// Implementation of StubAssembler
|
// Implementation of StubAssembler
|
||||||
|
@ -1753,13 +1756,17 @@ OopMapSet* Runtime1::generate_code_for(StubID id, StubAssembler* sasm) {
|
||||||
__ leal(card_addr, __ as_Address(ArrayAddress(cardtable, index)));
|
__ leal(card_addr, __ as_Address(ArrayAddress(cardtable, index)));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
__ cmpb(Address(card_addr, 0), 0);
|
__ cmpb(Address(card_addr, 0), (int)G1SATBCardTableModRefBS::g1_young_card_val());
|
||||||
|
__ jcc(Assembler::equal, done);
|
||||||
|
|
||||||
|
__ membar(Assembler::Membar_mask_bits(Assembler::StoreLoad));
|
||||||
|
__ cmpb(Address(card_addr, 0), (int)CardTableModRefBS::dirty_card_val());
|
||||||
__ jcc(Assembler::equal, done);
|
__ jcc(Assembler::equal, done);
|
||||||
|
|
||||||
// storing region crossing non-NULL, card is clean.
|
// storing region crossing non-NULL, card is clean.
|
||||||
// dirty card and log.
|
// dirty card and log.
|
||||||
|
|
||||||
__ movb(Address(card_addr, 0), 0);
|
__ movb(Address(card_addr, 0), (int)CardTableModRefBS::dirty_card_val());
|
||||||
|
|
||||||
__ cmpl(queue_index, 0);
|
__ cmpl(queue_index, 0);
|
||||||
__ jcc(Assembler::equal, runtime);
|
__ jcc(Assembler::equal, runtime);
|
||||||
|
|
|
@ -3389,13 +3389,18 @@ void MacroAssembler::g1_write_barrier_post(Register store_addr,
|
||||||
const Register card_addr = tmp;
|
const Register card_addr = tmp;
|
||||||
lea(card_addr, as_Address(ArrayAddress(cardtable, index)));
|
lea(card_addr, as_Address(ArrayAddress(cardtable, index)));
|
||||||
#endif
|
#endif
|
||||||
cmpb(Address(card_addr, 0), 0);
|
cmpb(Address(card_addr, 0), (int)G1SATBCardTableModRefBS::g1_young_card_val());
|
||||||
jcc(Assembler::equal, done);
|
jcc(Assembler::equal, done);
|
||||||
|
|
||||||
|
membar(Assembler::Membar_mask_bits(Assembler::StoreLoad));
|
||||||
|
cmpb(Address(card_addr, 0), (int)CardTableModRefBS::dirty_card_val());
|
||||||
|
jcc(Assembler::equal, done);
|
||||||
|
|
||||||
|
|
||||||
// storing a region crossing, non-NULL oop, card is clean.
|
// storing a region crossing, non-NULL oop, card is clean.
|
||||||
// dirty card and log.
|
// dirty card and log.
|
||||||
|
|
||||||
movb(Address(card_addr, 0), 0);
|
movb(Address(card_addr, 0), (int)CardTableModRefBS::dirty_card_val());
|
||||||
|
|
||||||
cmpl(queue_index, 0);
|
cmpl(queue_index, 0);
|
||||||
jcc(Assembler::equal, runtime);
|
jcc(Assembler::equal, runtime);
|
||||||
|
|
|
@ -42,7 +42,7 @@
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
typedef thread_t thread_id_t;
|
typedef thread_t thread_id_t;
|
||||||
#else
|
#else
|
||||||
typedef pthread_t thread_id_t;
|
typedef pid_t thread_id_t;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// _pthread_id is the pthread id, which is used by library calls
|
// _pthread_id is the pthread id, which is used by library calls
|
||||||
|
|
|
@ -100,6 +100,7 @@
|
||||||
# include <stdint.h>
|
# include <stdint.h>
|
||||||
# include <inttypes.h>
|
# include <inttypes.h>
|
||||||
# include <sys/ioctl.h>
|
# include <sys/ioctl.h>
|
||||||
|
# include <sys/syscall.h>
|
||||||
|
|
||||||
#if defined(__FreeBSD__) || defined(__NetBSD__)
|
#if defined(__FreeBSD__) || defined(__NetBSD__)
|
||||||
# include <elf.h>
|
# include <elf.h>
|
||||||
|
@ -152,6 +153,7 @@ sigset_t SR_sigset;
|
||||||
// utility functions
|
// utility functions
|
||||||
|
|
||||||
static int SR_initialize();
|
static int SR_initialize();
|
||||||
|
static void unpackTime(timespec* absTime, bool isAbsolute, jlong time);
|
||||||
|
|
||||||
julong os::available_memory() {
|
julong os::available_memory() {
|
||||||
return Bsd::available_memory();
|
return Bsd::available_memory();
|
||||||
|
@ -247,7 +249,17 @@ void os::Bsd::initialize_system_info() {
|
||||||
* since it returns a 64 bit value)
|
* since it returns a 64 bit value)
|
||||||
*/
|
*/
|
||||||
mib[0] = CTL_HW;
|
mib[0] = CTL_HW;
|
||||||
|
|
||||||
|
#if defined (HW_MEMSIZE) // Apple
|
||||||
mib[1] = HW_MEMSIZE;
|
mib[1] = HW_MEMSIZE;
|
||||||
|
#elif defined(HW_PHYSMEM) // Most of BSD
|
||||||
|
mib[1] = HW_PHYSMEM;
|
||||||
|
#elif defined(HW_REALMEM) // Old FreeBSD
|
||||||
|
mib[1] = HW_REALMEM;
|
||||||
|
#else
|
||||||
|
#error No ways to get physmem
|
||||||
|
#endif
|
||||||
|
|
||||||
len = sizeof(mem_val);
|
len = sizeof(mem_val);
|
||||||
if (sysctl(mib, 2, &mem_val, &len, NULL, 0) != -1) {
|
if (sysctl(mib, 2, &mem_val, &len, NULL, 0) != -1) {
|
||||||
assert(len == sizeof(mem_val), "unexpected data size");
|
assert(len == sizeof(mem_val), "unexpected data size");
|
||||||
|
@ -679,18 +691,12 @@ static void *java_start(Thread *thread) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef __APPLE__
|
osthread->set_thread_id(os::Bsd::gettid());
|
||||||
// thread_id is mach thread on macos, which pthreads graciously caches and provides for us
|
|
||||||
mach_port_t thread_id = ::pthread_mach_thread_np(::pthread_self());
|
|
||||||
guarantee(thread_id != 0, "thread id missing from pthreads");
|
|
||||||
osthread->set_thread_id(thread_id);
|
|
||||||
|
|
||||||
uint64_t unique_thread_id = locate_unique_thread_id(thread_id);
|
#ifdef __APPLE__
|
||||||
|
uint64_t unique_thread_id = locate_unique_thread_id(osthread->thread_id());
|
||||||
guarantee(unique_thread_id != 0, "unique thread id was not found");
|
guarantee(unique_thread_id != 0, "unique thread id was not found");
|
||||||
osthread->set_unique_thread_id(unique_thread_id);
|
osthread->set_unique_thread_id(unique_thread_id);
|
||||||
#else
|
|
||||||
// thread_id is pthread_id on BSD
|
|
||||||
osthread->set_thread_id(::pthread_self());
|
|
||||||
#endif
|
#endif
|
||||||
// initialize signal mask for this thread
|
// initialize signal mask for this thread
|
||||||
os::Bsd::hotspot_sigmask(thread);
|
os::Bsd::hotspot_sigmask(thread);
|
||||||
|
@ -847,18 +853,13 @@ bool os::create_attached_thread(JavaThread* thread) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
osthread->set_thread_id(os::Bsd::gettid());
|
||||||
|
|
||||||
// Store pthread info into the OSThread
|
// Store pthread info into the OSThread
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
// thread_id is mach thread on macos, which pthreads graciously caches and provides for us
|
uint64_t unique_thread_id = locate_unique_thread_id(osthread->thread_id());
|
||||||
mach_port_t thread_id = ::pthread_mach_thread_np(::pthread_self());
|
|
||||||
guarantee(thread_id != 0, "just checking");
|
|
||||||
osthread->set_thread_id(thread_id);
|
|
||||||
|
|
||||||
uint64_t unique_thread_id = locate_unique_thread_id(thread_id);
|
|
||||||
guarantee(unique_thread_id != 0, "just checking");
|
guarantee(unique_thread_id != 0, "just checking");
|
||||||
osthread->set_unique_thread_id(unique_thread_id);
|
osthread->set_unique_thread_id(unique_thread_id);
|
||||||
#else
|
|
||||||
osthread->set_thread_id(::pthread_self());
|
|
||||||
#endif
|
#endif
|
||||||
osthread->set_pthread_id(::pthread_self());
|
osthread->set_pthread_id(::pthread_self());
|
||||||
|
|
||||||
|
@ -1125,6 +1126,30 @@ size_t os::lasterror(char *buf, size_t len) {
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Information of current thread in variety of formats
|
||||||
|
pid_t os::Bsd::gettid() {
|
||||||
|
int retval = -1;
|
||||||
|
|
||||||
|
#ifdef __APPLE__ //XNU kernel
|
||||||
|
// despite the fact mach port is actually not a thread id use it
|
||||||
|
// instead of syscall(SYS_thread_selfid) as it certainly fits to u4
|
||||||
|
retval = ::pthread_mach_thread_np(::pthread_self());
|
||||||
|
guarantee(retval != 0, "just checking");
|
||||||
|
return retval;
|
||||||
|
|
||||||
|
#elif __FreeBSD__
|
||||||
|
retval = syscall(SYS_thr_self);
|
||||||
|
#elif __OpenBSD__
|
||||||
|
retval = syscall(SYS_getthrid);
|
||||||
|
#elif __NetBSD__
|
||||||
|
retval = (pid_t) syscall(SYS__lwp_self);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (retval == -1) {
|
||||||
|
return getpid();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
intx os::current_thread_id() {
|
intx os::current_thread_id() {
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
return (intx)::pthread_mach_thread_np(::pthread_self());
|
return (intx)::pthread_mach_thread_np(::pthread_self());
|
||||||
|
@ -1132,6 +1157,7 @@ intx os::current_thread_id() {
|
||||||
return (intx)::pthread_self();
|
return (intx)::pthread_self();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
int os::current_process_id() {
|
int os::current_process_id() {
|
||||||
|
|
||||||
// Under the old bsd thread library, bsd gives each thread
|
// Under the old bsd thread library, bsd gives each thread
|
||||||
|
@ -1904,7 +1930,7 @@ class Semaphore : public StackObj {
|
||||||
bool timedwait(unsigned int sec, int nsec);
|
bool timedwait(unsigned int sec, int nsec);
|
||||||
private:
|
private:
|
||||||
jlong currenttime() const;
|
jlong currenttime() const;
|
||||||
semaphore_t _semaphore;
|
os_semaphore_t _semaphore;
|
||||||
};
|
};
|
||||||
|
|
||||||
Semaphore::Semaphore() : _semaphore(0) {
|
Semaphore::Semaphore() : _semaphore(0) {
|
||||||
|
@ -1972,7 +1998,7 @@ bool Semaphore::trywait() {
|
||||||
|
|
||||||
bool Semaphore::timedwait(unsigned int sec, int nsec) {
|
bool Semaphore::timedwait(unsigned int sec, int nsec) {
|
||||||
struct timespec ts;
|
struct timespec ts;
|
||||||
jlong endtime = unpackTime(&ts, false, (sec * NANOSECS_PER_SEC) + nsec);
|
unpackTime(&ts, false, (sec * NANOSECS_PER_SEC) + nsec);
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
int result = sem_timedwait(&_semaphore, &ts);
|
int result = sem_timedwait(&_semaphore, &ts);
|
||||||
|
|
|
@ -84,6 +84,7 @@ class Bsd {
|
||||||
static void hotspot_sigmask(Thread* thread);
|
static void hotspot_sigmask(Thread* thread);
|
||||||
|
|
||||||
static bool is_initial_thread(void);
|
static bool is_initial_thread(void);
|
||||||
|
static pid_t gettid();
|
||||||
|
|
||||||
static int page_size(void) { return _page_size; }
|
static int page_size(void) { return _page_size; }
|
||||||
static void set_page_size(int val) { _page_size = val; }
|
static void set_page_size(int val) { _page_size = val; }
|
||||||
|
|
|
@ -53,7 +53,7 @@
|
||||||
// Defines Linux-specific default values. The flags are available on all
|
// Defines Linux-specific default values. The flags are available on all
|
||||||
// platforms, but they may have different default values on other platforms.
|
// platforms, but they may have different default values on other platforms.
|
||||||
//
|
//
|
||||||
define_pd_global(bool, UseLargePages, true);
|
define_pd_global(bool, UseLargePages, false);
|
||||||
define_pd_global(bool, UseLargePagesIndividualAllocation, false);
|
define_pd_global(bool, UseLargePagesIndividualAllocation, false);
|
||||||
define_pd_global(bool, UseOSErrorReporting, false);
|
define_pd_global(bool, UseOSErrorReporting, false);
|
||||||
define_pd_global(bool, UseThreadPriorities, true) ;
|
define_pd_global(bool, UseThreadPriorities, true) ;
|
||||||
|
|
|
@ -3361,13 +3361,15 @@ bool os::Linux::setup_large_page_type(size_t page_size) {
|
||||||
if (FLAG_IS_DEFAULT(UseHugeTLBFS) &&
|
if (FLAG_IS_DEFAULT(UseHugeTLBFS) &&
|
||||||
FLAG_IS_DEFAULT(UseSHM) &&
|
FLAG_IS_DEFAULT(UseSHM) &&
|
||||||
FLAG_IS_DEFAULT(UseTransparentHugePages)) {
|
FLAG_IS_DEFAULT(UseTransparentHugePages)) {
|
||||||
// If UseLargePages is specified on the command line try all methods,
|
|
||||||
// if it's default, then try only UseTransparentHugePages.
|
// The type of large pages has not been specified by the user.
|
||||||
if (FLAG_IS_DEFAULT(UseLargePages)) {
|
|
||||||
UseTransparentHugePages = true;
|
// Try UseHugeTLBFS and then UseSHM.
|
||||||
} else {
|
UseHugeTLBFS = UseSHM = true;
|
||||||
UseHugeTLBFS = UseTransparentHugePages = UseSHM = true;
|
|
||||||
}
|
// Don't try UseTransparentHugePages since there are known
|
||||||
|
// performance issues with it turned on. This might change in the future.
|
||||||
|
UseTransparentHugePages = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (UseTransparentHugePages) {
|
if (UseTransparentHugePages) {
|
||||||
|
@ -3393,9 +3395,19 @@ bool os::Linux::setup_large_page_type(size_t page_size) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void os::large_page_init() {
|
void os::large_page_init() {
|
||||||
if (!UseLargePages) {
|
if (!UseLargePages &&
|
||||||
UseHugeTLBFS = false;
|
!UseTransparentHugePages &&
|
||||||
|
!UseHugeTLBFS &&
|
||||||
|
!UseSHM) {
|
||||||
|
// Not using large pages.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!FLAG_IS_DEFAULT(UseLargePages) && !UseLargePages) {
|
||||||
|
// The user explicitly turned off large pages.
|
||||||
|
// Ignore the rest of the large pages flags.
|
||||||
UseTransparentHugePages = false;
|
UseTransparentHugePages = false;
|
||||||
|
UseHugeTLBFS = false;
|
||||||
UseSHM = false;
|
UseSHM = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -4080,8 +4080,7 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
|
||||||
|
|
||||||
// Generate any default methods - default methods are interface methods
|
// Generate any default methods - default methods are interface methods
|
||||||
// that have a default implementation. This is new with Lambda project.
|
// that have a default implementation. This is new with Lambda project.
|
||||||
if (has_default_methods && !access_flags.is_interface() &&
|
if (has_default_methods && !access_flags.is_interface() ) {
|
||||||
local_interfaces->length() > 0) {
|
|
||||||
DefaultMethods::generate_default_methods(
|
DefaultMethods::generate_default_methods(
|
||||||
this_klass(), &all_mirandas, CHECK_(nullHandle));
|
this_klass(), &all_mirandas, CHECK_(nullHandle));
|
||||||
}
|
}
|
||||||
|
|
|
@ -345,7 +345,6 @@ class MethodFamily : public ResourceObj {
|
||||||
}
|
}
|
||||||
|
|
||||||
Symbol* generate_no_defaults_message(TRAPS) const;
|
Symbol* generate_no_defaults_message(TRAPS) const;
|
||||||
Symbol* generate_abstract_method_message(Method* method, TRAPS) const;
|
|
||||||
Symbol* generate_conflicts_message(GrowableArray<Method*>* methods, TRAPS) const;
|
Symbol* generate_conflicts_message(GrowableArray<Method*>* methods, TRAPS) const;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -404,20 +403,19 @@ class MethodFamily : public ResourceObj {
|
||||||
_exception_message = generate_no_defaults_message(CHECK);
|
_exception_message = generate_no_defaults_message(CHECK);
|
||||||
_exception_name = vmSymbols::java_lang_AbstractMethodError();
|
_exception_name = vmSymbols::java_lang_AbstractMethodError();
|
||||||
} else if (qualified_methods.length() == 1) {
|
} else if (qualified_methods.length() == 1) {
|
||||||
|
// leave abstract methods alone, they will be found via normal search path
|
||||||
Method* method = qualified_methods.at(0);
|
Method* method = qualified_methods.at(0);
|
||||||
if (method->is_abstract()) {
|
if (!method->is_abstract()) {
|
||||||
_exception_message = generate_abstract_method_message(method, CHECK);
|
|
||||||
_exception_name = vmSymbols::java_lang_AbstractMethodError();
|
|
||||||
} else {
|
|
||||||
_selected_target = qualified_methods.at(0);
|
_selected_target = qualified_methods.at(0);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
_exception_message = generate_conflicts_message(&qualified_methods,CHECK);
|
_exception_message = generate_conflicts_message(&qualified_methods,CHECK);
|
||||||
_exception_name = vmSymbols::java_lang_IncompatibleClassChangeError();
|
_exception_name = vmSymbols::java_lang_IncompatibleClassChangeError();
|
||||||
|
if (TraceDefaultMethods) {
|
||||||
|
_exception_message->print_value_on(tty);
|
||||||
|
tty->print_cr("");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
assert((has_target() ^ throws_exception()) == 1,
|
|
||||||
"One and only one must be true");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool contains_signature(Symbol* query) {
|
bool contains_signature(Symbol* query) {
|
||||||
|
@ -475,20 +473,6 @@ Symbol* MethodFamily::generate_no_defaults_message(TRAPS) const {
|
||||||
return SymbolTable::new_symbol("No qualifying defaults found", CHECK_NULL);
|
return SymbolTable::new_symbol("No qualifying defaults found", CHECK_NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
Symbol* MethodFamily::generate_abstract_method_message(Method* method, TRAPS) const {
|
|
||||||
Symbol* klass = method->klass_name();
|
|
||||||
Symbol* name = method->name();
|
|
||||||
Symbol* sig = method->signature();
|
|
||||||
stringStream ss;
|
|
||||||
ss.print("Method ");
|
|
||||||
ss.write((const char*)klass->bytes(), klass->utf8_length());
|
|
||||||
ss.print(".");
|
|
||||||
ss.write((const char*)name->bytes(), name->utf8_length());
|
|
||||||
ss.write((const char*)sig->bytes(), sig->utf8_length());
|
|
||||||
ss.print(" is abstract");
|
|
||||||
return SymbolTable::new_symbol(ss.base(), (int)ss.size(), CHECK_NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
Symbol* MethodFamily::generate_conflicts_message(GrowableArray<Method*>* methods, TRAPS) const {
|
Symbol* MethodFamily::generate_conflicts_message(GrowableArray<Method*>* methods, TRAPS) const {
|
||||||
stringStream ss;
|
stringStream ss;
|
||||||
ss.print("Conflicting default methods:");
|
ss.print("Conflicting default methods:");
|
||||||
|
@ -595,6 +579,18 @@ class EmptyVtableSlot : public ResourceObj {
|
||||||
#endif // ndef PRODUCT
|
#endif // ndef PRODUCT
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static bool already_in_vtable_slots(GrowableArray<EmptyVtableSlot*>* slots, Method* m) {
|
||||||
|
bool found = false;
|
||||||
|
for (int j = 0; j < slots->length(); ++j) {
|
||||||
|
if (slots->at(j)->name() == m->name() &&
|
||||||
|
slots->at(j)->signature() == m->signature() ) {
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return found;
|
||||||
|
}
|
||||||
|
|
||||||
static GrowableArray<EmptyVtableSlot*>* find_empty_vtable_slots(
|
static GrowableArray<EmptyVtableSlot*>* find_empty_vtable_slots(
|
||||||
InstanceKlass* klass, GrowableArray<Method*>* mirandas, TRAPS) {
|
InstanceKlass* klass, GrowableArray<Method*>* mirandas, TRAPS) {
|
||||||
|
|
||||||
|
@ -604,8 +600,10 @@ static GrowableArray<EmptyVtableSlot*>* find_empty_vtable_slots(
|
||||||
|
|
||||||
// All miranda methods are obvious candidates
|
// All miranda methods are obvious candidates
|
||||||
for (int i = 0; i < mirandas->length(); ++i) {
|
for (int i = 0; i < mirandas->length(); ++i) {
|
||||||
EmptyVtableSlot* slot = new EmptyVtableSlot(mirandas->at(i));
|
Method* m = mirandas->at(i);
|
||||||
slots->append(slot);
|
if (!already_in_vtable_slots(slots, m)) {
|
||||||
|
slots->append(new EmptyVtableSlot(m));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Also any overpasses in our superclasses, that we haven't implemented.
|
// Also any overpasses in our superclasses, that we haven't implemented.
|
||||||
|
@ -621,10 +619,29 @@ static GrowableArray<EmptyVtableSlot*>* find_empty_vtable_slots(
|
||||||
// unless we have a real implementation of it in the current class.
|
// unless we have a real implementation of it in the current class.
|
||||||
Method* impl = klass->lookup_method(m->name(), m->signature());
|
Method* impl = klass->lookup_method(m->name(), m->signature());
|
||||||
if (impl == NULL || impl->is_overpass()) {
|
if (impl == NULL || impl->is_overpass()) {
|
||||||
|
if (!already_in_vtable_slots(slots, m)) {
|
||||||
slots->append(new EmptyVtableSlot(m));
|
slots->append(new EmptyVtableSlot(m));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// also any default methods in our superclasses
|
||||||
|
if (super->default_methods() != NULL) {
|
||||||
|
for (int i = 0; i < super->default_methods()->length(); ++i) {
|
||||||
|
Method* m = super->default_methods()->at(i);
|
||||||
|
// m is a method that would have been a miranda if not for the
|
||||||
|
// default method processing that occurred on behalf of our superclass,
|
||||||
|
// so it's a method we want to re-examine in this new context. That is,
|
||||||
|
// unless we have a real implementation of it in the current class.
|
||||||
|
Method* impl = klass->lookup_method(m->name(), m->signature());
|
||||||
|
if (impl == NULL || impl->is_overpass()) {
|
||||||
|
if (!already_in_vtable_slots(slots, m)) {
|
||||||
|
slots->append(new EmptyVtableSlot(m));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
super = super->java_super();
|
super = super->java_super();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -679,7 +696,7 @@ class FindMethodsByErasedSig : public HierarchyVisitor<FindMethodsByErasedSig> {
|
||||||
// private interface methods are not candidates for default methods
|
// private interface methods are not candidates for default methods
|
||||||
// invokespecial to private interface methods doesn't use default method logic
|
// invokespecial to private interface methods doesn't use default method logic
|
||||||
// future: take access controls into account for superclass methods
|
// future: take access controls into account for superclass methods
|
||||||
if (m != NULL && (!iklass->is_interface() || m->is_public())) {
|
if (m != NULL && !m->is_static() && (!iklass->is_interface() || m->is_public())) {
|
||||||
if (_family == NULL) {
|
if (_family == NULL) {
|
||||||
_family = new StatefulMethodFamily();
|
_family = new StatefulMethodFamily();
|
||||||
}
|
}
|
||||||
|
@ -700,7 +717,7 @@ class FindMethodsByErasedSig : public HierarchyVisitor<FindMethodsByErasedSig> {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static void create_overpasses(
|
static void create_defaults_and_exceptions(
|
||||||
GrowableArray<EmptyVtableSlot*>* slots, InstanceKlass* klass, TRAPS);
|
GrowableArray<EmptyVtableSlot*>* slots, InstanceKlass* klass, TRAPS);
|
||||||
|
|
||||||
static void generate_erased_defaults(
|
static void generate_erased_defaults(
|
||||||
|
@ -721,6 +738,8 @@ static void generate_erased_defaults(
|
||||||
|
|
||||||
static void merge_in_new_methods(InstanceKlass* klass,
|
static void merge_in_new_methods(InstanceKlass* klass,
|
||||||
GrowableArray<Method*>* new_methods, TRAPS);
|
GrowableArray<Method*>* new_methods, TRAPS);
|
||||||
|
static void create_default_methods( InstanceKlass* klass,
|
||||||
|
GrowableArray<Method*>* new_methods, TRAPS);
|
||||||
|
|
||||||
// This is the guts of the default methods implementation. This is called just
|
// This is the guts of the default methods implementation. This is called just
|
||||||
// after the classfile has been parsed if some ancestor has default methods.
|
// after the classfile has been parsed if some ancestor has default methods.
|
||||||
|
@ -782,7 +801,7 @@ void DefaultMethods::generate_default_methods(
|
||||||
}
|
}
|
||||||
#endif // ndef PRODUCT
|
#endif // ndef PRODUCT
|
||||||
|
|
||||||
create_overpasses(empty_slots, klass, CHECK);
|
create_defaults_and_exceptions(empty_slots, klass, CHECK);
|
||||||
|
|
||||||
#ifndef PRODUCT
|
#ifndef PRODUCT
|
||||||
if (TraceDefaultMethods) {
|
if (TraceDefaultMethods) {
|
||||||
|
@ -791,66 +810,6 @@ void DefaultMethods::generate_default_methods(
|
||||||
#endif // ndef PRODUCT
|
#endif // ndef PRODUCT
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef ASSERT
|
|
||||||
// Return true is broad type is a covariant return of narrow type
|
|
||||||
static bool covariant_return_type(BasicType narrow, BasicType broad) {
|
|
||||||
if (narrow == broad) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (broad == T_OBJECT) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static int assemble_redirect(
|
|
||||||
BytecodeConstantPool* cp, BytecodeBuffer* buffer,
|
|
||||||
Symbol* incoming, Method* target, TRAPS) {
|
|
||||||
|
|
||||||
BytecodeAssembler assem(buffer, cp);
|
|
||||||
|
|
||||||
SignatureStream in(incoming, true);
|
|
||||||
SignatureStream out(target->signature(), true);
|
|
||||||
u2 parameter_count = 0;
|
|
||||||
|
|
||||||
assem.aload(parameter_count++); // load 'this'
|
|
||||||
|
|
||||||
while (!in.at_return_type()) {
|
|
||||||
assert(!out.at_return_type(), "Parameter counts do not match");
|
|
||||||
BasicType bt = in.type();
|
|
||||||
assert(out.type() == bt, "Parameter types are not compatible");
|
|
||||||
assem.load(bt, parameter_count);
|
|
||||||
if (in.is_object() && in.as_symbol(THREAD) != out.as_symbol(THREAD)) {
|
|
||||||
assem.checkcast(out.as_symbol(THREAD));
|
|
||||||
} else if (bt == T_LONG || bt == T_DOUBLE) {
|
|
||||||
++parameter_count; // longs and doubles use two slots
|
|
||||||
}
|
|
||||||
++parameter_count;
|
|
||||||
in.next();
|
|
||||||
out.next();
|
|
||||||
}
|
|
||||||
assert(out.at_return_type(), "Parameter counts do not match");
|
|
||||||
assert(covariant_return_type(out.type(), in.type()), "Return types are not compatible");
|
|
||||||
|
|
||||||
if (parameter_count == 1 && (in.type() == T_LONG || in.type() == T_DOUBLE)) {
|
|
||||||
++parameter_count; // need room for return value
|
|
||||||
}
|
|
||||||
if (target->method_holder()->is_interface()) {
|
|
||||||
assem.invokespecial(target);
|
|
||||||
} else {
|
|
||||||
assem.invokevirtual(target);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (in.is_object() && in.as_symbol(THREAD) != out.as_symbol(THREAD)) {
|
|
||||||
assem.checkcast(in.as_symbol(THREAD));
|
|
||||||
}
|
|
||||||
assem._return(in.type());
|
|
||||||
return parameter_count;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int assemble_method_error(
|
static int assemble_method_error(
|
||||||
BytecodeConstantPool* cp, BytecodeBuffer* buffer, Symbol* errorName, Symbol* message, TRAPS) {
|
BytecodeConstantPool* cp, BytecodeBuffer* buffer, Symbol* errorName, Symbol* message, TRAPS) {
|
||||||
|
|
||||||
|
@ -924,18 +883,18 @@ static void switchover_constant_pool(BytecodeConstantPool* bpool,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// A "bridge" is a method created by javac to bridge the gap between
|
// Create default_methods list for the current class.
|
||||||
// an implementation and a generically-compatible, but different, signature.
|
// With the VM only processing erased signatures, the VM only
|
||||||
// Bridges have actual bytecode implementation in classfiles.
|
// creates an overpass in a conflict case or a case with no candidates.
|
||||||
// An "overpass", on the other hand, performs the same function as a bridge
|
// This allows virtual methods to override the overpass, but ensures
|
||||||
// but does not occur in a classfile; the VM creates overpass itself,
|
// that a local method search will find the exception rather than an abstract
|
||||||
// when it needs a path to get from a call site to an default method, and
|
// or default method that is not a valid candidate.
|
||||||
// a bridge doesn't exist.
|
static void create_defaults_and_exceptions(
|
||||||
static void create_overpasses(
|
|
||||||
GrowableArray<EmptyVtableSlot*>* slots,
|
GrowableArray<EmptyVtableSlot*>* slots,
|
||||||
InstanceKlass* klass, TRAPS) {
|
InstanceKlass* klass, TRAPS) {
|
||||||
|
|
||||||
GrowableArray<Method*> overpasses;
|
GrowableArray<Method*> overpasses;
|
||||||
|
GrowableArray<Method*> defaults;
|
||||||
BytecodeConstantPool bpool(klass->constants());
|
BytecodeConstantPool bpool(klass->constants());
|
||||||
|
|
||||||
for (int i = 0; i < slots->length(); ++i) {
|
for (int i = 0; i < slots->length(); ++i) {
|
||||||
|
@ -943,7 +902,6 @@ static void create_overpasses(
|
||||||
|
|
||||||
if (slot->is_bound()) {
|
if (slot->is_bound()) {
|
||||||
MethodFamily* method = slot->get_binding();
|
MethodFamily* method = slot->get_binding();
|
||||||
int max_stack = 0;
|
|
||||||
BytecodeBuffer buffer;
|
BytecodeBuffer buffer;
|
||||||
|
|
||||||
#ifndef PRODUCT
|
#ifndef PRODUCT
|
||||||
|
@ -953,26 +911,27 @@ static void create_overpasses(
|
||||||
tty->print_cr("");
|
tty->print_cr("");
|
||||||
if (method->has_target()) {
|
if (method->has_target()) {
|
||||||
method->print_selected(tty, 1);
|
method->print_selected(tty, 1);
|
||||||
} else {
|
} else if (method->throws_exception()) {
|
||||||
method->print_exception(tty, 1);
|
method->print_exception(tty, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif // ndef PRODUCT
|
#endif // ndef PRODUCT
|
||||||
|
|
||||||
if (method->has_target()) {
|
if (method->has_target()) {
|
||||||
Method* selected = method->get_selected_target();
|
Method* selected = method->get_selected_target();
|
||||||
if (selected->method_holder()->is_interface()) {
|
if (selected->method_holder()->is_interface()) {
|
||||||
max_stack = assemble_redirect(
|
defaults.push(selected);
|
||||||
&bpool, &buffer, slot->signature(), selected, CHECK);
|
|
||||||
}
|
}
|
||||||
} else if (method->throws_exception()) {
|
} else if (method->throws_exception()) {
|
||||||
max_stack = assemble_method_error(&bpool, &buffer, method->get_exception_name(), method->get_exception_message(), CHECK);
|
int max_stack = assemble_method_error(&bpool, &buffer,
|
||||||
}
|
method->get_exception_name(), method->get_exception_message(), CHECK);
|
||||||
if (max_stack != 0) {
|
|
||||||
AccessFlags flags = accessFlags_from(
|
AccessFlags flags = accessFlags_from(
|
||||||
JVM_ACC_PUBLIC | JVM_ACC_SYNTHETIC | JVM_ACC_BRIDGE);
|
JVM_ACC_PUBLIC | JVM_ACC_SYNTHETIC | JVM_ACC_BRIDGE);
|
||||||
Method* m = new_method(&bpool, &buffer, slot->name(), slot->signature(),
|
Method* m = new_method(&bpool, &buffer, slot->name(), slot->signature(),
|
||||||
flags, max_stack, slot->size_of_parameters(),
|
flags, max_stack, slot->size_of_parameters(),
|
||||||
ConstMethod::OVERPASS, CHECK);
|
ConstMethod::OVERPASS, CHECK);
|
||||||
|
// We push to the methods list:
|
||||||
|
// overpass methods which are exception throwing methods
|
||||||
if (m != NULL) {
|
if (m != NULL) {
|
||||||
overpasses.push(m);
|
overpasses.push(m);
|
||||||
}
|
}
|
||||||
|
@ -983,12 +942,32 @@ static void create_overpasses(
|
||||||
#ifndef PRODUCT
|
#ifndef PRODUCT
|
||||||
if (TraceDefaultMethods) {
|
if (TraceDefaultMethods) {
|
||||||
tty->print_cr("Created %d overpass methods", overpasses.length());
|
tty->print_cr("Created %d overpass methods", overpasses.length());
|
||||||
|
tty->print_cr("Created %d default methods", defaults.length());
|
||||||
}
|
}
|
||||||
#endif // ndef PRODUCT
|
#endif // ndef PRODUCT
|
||||||
|
|
||||||
|
if (overpasses.length() > 0) {
|
||||||
switchover_constant_pool(&bpool, klass, &overpasses, CHECK);
|
switchover_constant_pool(&bpool, klass, &overpasses, CHECK);
|
||||||
merge_in_new_methods(klass, &overpasses, CHECK);
|
merge_in_new_methods(klass, &overpasses, CHECK);
|
||||||
}
|
}
|
||||||
|
if (defaults.length() > 0) {
|
||||||
|
create_default_methods(klass, &defaults, CHECK);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void create_default_methods( InstanceKlass* klass,
|
||||||
|
GrowableArray<Method*>* new_methods, TRAPS) {
|
||||||
|
|
||||||
|
int new_size = new_methods->length();
|
||||||
|
Array<Method*>* total_default_methods = MetadataFactory::new_array<Method*>(
|
||||||
|
klass->class_loader_data(), new_size, NULL, CHECK);
|
||||||
|
for (int index = 0; index < new_size; index++ ) {
|
||||||
|
total_default_methods->at_put(index, new_methods->at(index));
|
||||||
|
}
|
||||||
|
Method::sort_methods(total_default_methods, false, false);
|
||||||
|
|
||||||
|
klass->set_default_methods(total_default_methods);
|
||||||
|
}
|
||||||
|
|
||||||
static void sort_methods(GrowableArray<Method*>* methods) {
|
static void sort_methods(GrowableArray<Method*>* methods) {
|
||||||
// Note that this must sort using the same key as is used for sorting
|
// Note that this must sort using the same key as is used for sorting
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -25,6 +25,7 @@
|
||||||
#include "precompiled.hpp"
|
#include "precompiled.hpp"
|
||||||
#include "classfile/dictionary.hpp"
|
#include "classfile/dictionary.hpp"
|
||||||
#include "classfile/systemDictionary.hpp"
|
#include "classfile/systemDictionary.hpp"
|
||||||
|
#include "memory/iterator.hpp"
|
||||||
#include "oops/oop.inline.hpp"
|
#include "oops/oop.inline.hpp"
|
||||||
#include "prims/jvmtiRedefineClassesTrace.hpp"
|
#include "prims/jvmtiRedefineClassesTrace.hpp"
|
||||||
#include "utilities/hashtable.inline.hpp"
|
#include "utilities/hashtable.inline.hpp"
|
||||||
|
@ -38,17 +39,21 @@ Dictionary::Dictionary(int table_size)
|
||||||
: TwoOopHashtable<Klass*, mtClass>(table_size, sizeof(DictionaryEntry)) {
|
: TwoOopHashtable<Klass*, mtClass>(table_size, sizeof(DictionaryEntry)) {
|
||||||
_current_class_index = 0;
|
_current_class_index = 0;
|
||||||
_current_class_entry = NULL;
|
_current_class_entry = NULL;
|
||||||
|
_pd_cache_table = new ProtectionDomainCacheTable(defaultProtectionDomainCacheSize);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Dictionary::Dictionary(int table_size, HashtableBucket<mtClass>* t,
|
Dictionary::Dictionary(int table_size, HashtableBucket<mtClass>* t,
|
||||||
int number_of_entries)
|
int number_of_entries)
|
||||||
: TwoOopHashtable<Klass*, mtClass>(table_size, sizeof(DictionaryEntry), t, number_of_entries) {
|
: TwoOopHashtable<Klass*, mtClass>(table_size, sizeof(DictionaryEntry), t, number_of_entries) {
|
||||||
_current_class_index = 0;
|
_current_class_index = 0;
|
||||||
_current_class_entry = NULL;
|
_current_class_entry = NULL;
|
||||||
|
_pd_cache_table = new ProtectionDomainCacheTable(defaultProtectionDomainCacheSize);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
ProtectionDomainCacheEntry* Dictionary::cache_get(oop protection_domain) {
|
||||||
|
return _pd_cache_table->get(protection_domain);
|
||||||
|
}
|
||||||
|
|
||||||
DictionaryEntry* Dictionary::new_entry(unsigned int hash, Klass* klass,
|
DictionaryEntry* Dictionary::new_entry(unsigned int hash, Klass* klass,
|
||||||
ClassLoaderData* loader_data) {
|
ClassLoaderData* loader_data) {
|
||||||
|
@ -105,11 +110,12 @@ bool DictionaryEntry::contains_protection_domain(oop protection_domain) const {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void DictionaryEntry::add_protection_domain(oop protection_domain) {
|
void DictionaryEntry::add_protection_domain(Dictionary* dict, oop protection_domain) {
|
||||||
assert_locked_or_safepoint(SystemDictionary_lock);
|
assert_locked_or_safepoint(SystemDictionary_lock);
|
||||||
if (!contains_protection_domain(protection_domain)) {
|
if (!contains_protection_domain(protection_domain)) {
|
||||||
|
ProtectionDomainCacheEntry* entry = dict->cache_get(protection_domain);
|
||||||
ProtectionDomainEntry* new_head =
|
ProtectionDomainEntry* new_head =
|
||||||
new ProtectionDomainEntry(protection_domain, _pd_set);
|
new ProtectionDomainEntry(entry, _pd_set);
|
||||||
// Warning: Preserve store ordering. The SystemDictionary is read
|
// Warning: Preserve store ordering. The SystemDictionary is read
|
||||||
// without locks. The new ProtectionDomainEntry must be
|
// without locks. The new ProtectionDomainEntry must be
|
||||||
// complete before other threads can be allowed to see it
|
// complete before other threads can be allowed to see it
|
||||||
|
@ -193,7 +199,10 @@ bool Dictionary::do_unloading() {
|
||||||
|
|
||||||
|
|
||||||
void Dictionary::always_strong_oops_do(OopClosure* blk) {
|
void Dictionary::always_strong_oops_do(OopClosure* blk) {
|
||||||
// Follow all system classes and temporary placeholders in dictionary
|
// Follow all system classes and temporary placeholders in dictionary; only
|
||||||
|
// protection domain oops contain references into the heap. In a first
|
||||||
|
// pass over the system dictionary determine which need to be treated as
|
||||||
|
// strongly reachable and mark them as such.
|
||||||
for (int index = 0; index < table_size(); index++) {
|
for (int index = 0; index < table_size(); index++) {
|
||||||
for (DictionaryEntry *probe = bucket(index);
|
for (DictionaryEntry *probe = bucket(index);
|
||||||
probe != NULL;
|
probe != NULL;
|
||||||
|
@ -201,10 +210,13 @@ void Dictionary::always_strong_oops_do(OopClosure* blk) {
|
||||||
Klass* e = probe->klass();
|
Klass* e = probe->klass();
|
||||||
ClassLoaderData* loader_data = probe->loader_data();
|
ClassLoaderData* loader_data = probe->loader_data();
|
||||||
if (is_strongly_reachable(loader_data, e)) {
|
if (is_strongly_reachable(loader_data, e)) {
|
||||||
probe->protection_domain_set_oops_do(blk);
|
probe->set_strongly_reachable();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Then iterate over the protection domain cache to apply the closure on the
|
||||||
|
// previously marked ones.
|
||||||
|
_pd_cache_table->always_strong_oops_do(blk);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -266,17 +278,11 @@ void Dictionary::classes_do(void f(Klass*, ClassLoaderData*)) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Dictionary::oops_do(OopClosure* f) {
|
void Dictionary::oops_do(OopClosure* f) {
|
||||||
for (int index = 0; index < table_size(); index++) {
|
// Only the protection domain oops contain references into the heap. Iterate
|
||||||
for (DictionaryEntry* probe = bucket(index);
|
// over all of them.
|
||||||
probe != NULL;
|
_pd_cache_table->oops_do(f);
|
||||||
probe = probe->next()) {
|
|
||||||
probe->protection_domain_set_oops_do(f);
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Dictionary::methods_do(void f(Method*)) {
|
void Dictionary::methods_do(void f(Method*)) {
|
||||||
for (int index = 0; index < table_size(); index++) {
|
for (int index = 0; index < table_size(); index++) {
|
||||||
|
@ -292,6 +298,11 @@ void Dictionary::methods_do(void f(Method*)) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Dictionary::unlink(BoolObjectClosure* is_alive) {
|
||||||
|
// Only the protection domain cache table may contain references to the heap
|
||||||
|
// that need to be unlinked.
|
||||||
|
_pd_cache_table->unlink(is_alive);
|
||||||
|
}
|
||||||
|
|
||||||
Klass* Dictionary::try_get_next_class() {
|
Klass* Dictionary::try_get_next_class() {
|
||||||
while (true) {
|
while (true) {
|
||||||
|
@ -306,7 +317,6 @@ Klass* Dictionary::try_get_next_class() {
|
||||||
// never reached
|
// never reached
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Add a loaded class to the system dictionary.
|
// Add a loaded class to the system dictionary.
|
||||||
// Readers of the SystemDictionary aren't always locked, so _buckets
|
// Readers of the SystemDictionary aren't always locked, so _buckets
|
||||||
// is volatile. The store of the next field in the constructor is
|
// is volatile. The store of the next field in the constructor is
|
||||||
|
@ -396,7 +406,7 @@ void Dictionary::add_protection_domain(int index, unsigned int hash,
|
||||||
assert(protection_domain() != NULL,
|
assert(protection_domain() != NULL,
|
||||||
"real protection domain should be present");
|
"real protection domain should be present");
|
||||||
|
|
||||||
entry->add_protection_domain(protection_domain());
|
entry->add_protection_domain(this, protection_domain());
|
||||||
|
|
||||||
assert(entry->contains_protection_domain(protection_domain()),
|
assert(entry->contains_protection_domain(protection_domain()),
|
||||||
"now protection domain should be present");
|
"now protection domain should be present");
|
||||||
|
@ -446,6 +456,146 @@ void Dictionary::reorder_dictionary() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ProtectionDomainCacheTable::ProtectionDomainCacheTable(int table_size)
|
||||||
|
: Hashtable<oop, mtClass>(table_size, sizeof(ProtectionDomainCacheEntry))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProtectionDomainCacheTable::unlink(BoolObjectClosure* is_alive) {
|
||||||
|
assert(SafepointSynchronize::is_at_safepoint(), "must be");
|
||||||
|
for (int i = 0; i < table_size(); ++i) {
|
||||||
|
ProtectionDomainCacheEntry** p = bucket_addr(i);
|
||||||
|
ProtectionDomainCacheEntry* entry = bucket(i);
|
||||||
|
while (entry != NULL) {
|
||||||
|
if (is_alive->do_object_b(entry->literal())) {
|
||||||
|
p = entry->next_addr();
|
||||||
|
} else {
|
||||||
|
*p = entry->next();
|
||||||
|
free_entry(entry);
|
||||||
|
}
|
||||||
|
entry = *p;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProtectionDomainCacheTable::oops_do(OopClosure* f) {
|
||||||
|
for (int index = 0; index < table_size(); index++) {
|
||||||
|
for (ProtectionDomainCacheEntry* probe = bucket(index);
|
||||||
|
probe != NULL;
|
||||||
|
probe = probe->next()) {
|
||||||
|
probe->oops_do(f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint ProtectionDomainCacheTable::bucket_size() {
|
||||||
|
return sizeof(ProtectionDomainCacheEntry);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef PRODUCT
|
||||||
|
void ProtectionDomainCacheTable::print() {
|
||||||
|
tty->print_cr("Protection domain cache table (table_size=%d, classes=%d)",
|
||||||
|
table_size(), number_of_entries());
|
||||||
|
for (int index = 0; index < table_size(); index++) {
|
||||||
|
for (ProtectionDomainCacheEntry* probe = bucket(index);
|
||||||
|
probe != NULL;
|
||||||
|
probe = probe->next()) {
|
||||||
|
probe->print();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProtectionDomainCacheEntry::print() {
|
||||||
|
tty->print_cr("entry "PTR_FORMAT" value "PTR_FORMAT" strongly_reachable %d next "PTR_FORMAT,
|
||||||
|
this, (void*)literal(), _strongly_reachable, next());
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void ProtectionDomainCacheTable::verify() {
|
||||||
|
int element_count = 0;
|
||||||
|
for (int index = 0; index < table_size(); index++) {
|
||||||
|
for (ProtectionDomainCacheEntry* probe = bucket(index);
|
||||||
|
probe != NULL;
|
||||||
|
probe = probe->next()) {
|
||||||
|
probe->verify();
|
||||||
|
element_count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
guarantee(number_of_entries() == element_count,
|
||||||
|
"Verify of protection domain cache table failed");
|
||||||
|
debug_only(verify_lookup_length((double)number_of_entries() / table_size()));
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProtectionDomainCacheEntry::verify() {
|
||||||
|
guarantee(literal()->is_oop(), "must be an oop");
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProtectionDomainCacheTable::always_strong_oops_do(OopClosure* f) {
|
||||||
|
// the caller marked the protection domain cache entries that we need to apply
|
||||||
|
// the closure on. Only process them.
|
||||||
|
for (int index = 0; index < table_size(); index++) {
|
||||||
|
for (ProtectionDomainCacheEntry* probe = bucket(index);
|
||||||
|
probe != NULL;
|
||||||
|
probe = probe->next()) {
|
||||||
|
if (probe->is_strongly_reachable()) {
|
||||||
|
probe->reset_strongly_reachable();
|
||||||
|
probe->oops_do(f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ProtectionDomainCacheEntry* ProtectionDomainCacheTable::get(oop protection_domain) {
|
||||||
|
unsigned int hash = compute_hash(protection_domain);
|
||||||
|
int index = hash_to_index(hash);
|
||||||
|
|
||||||
|
ProtectionDomainCacheEntry* entry = find_entry(index, protection_domain);
|
||||||
|
if (entry == NULL) {
|
||||||
|
entry = add_entry(index, hash, protection_domain);
|
||||||
|
}
|
||||||
|
return entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
ProtectionDomainCacheEntry* ProtectionDomainCacheTable::find_entry(int index, oop protection_domain) {
|
||||||
|
for (ProtectionDomainCacheEntry* e = bucket(index); e != NULL; e = e->next()) {
|
||||||
|
if (e->protection_domain() == protection_domain) {
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
ProtectionDomainCacheEntry* ProtectionDomainCacheTable::add_entry(int index, unsigned int hash, oop protection_domain) {
|
||||||
|
assert_locked_or_safepoint(SystemDictionary_lock);
|
||||||
|
assert(index == index_for(protection_domain), "incorrect index?");
|
||||||
|
assert(find_entry(index, protection_domain) == NULL, "no double entry");
|
||||||
|
|
||||||
|
ProtectionDomainCacheEntry* p = new_entry(hash, protection_domain);
|
||||||
|
Hashtable<oop, mtClass>::add_entry(index, p);
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProtectionDomainCacheTable::free(ProtectionDomainCacheEntry* to_delete) {
|
||||||
|
unsigned int hash = compute_hash(to_delete->protection_domain());
|
||||||
|
int index = hash_to_index(hash);
|
||||||
|
|
||||||
|
ProtectionDomainCacheEntry** p = bucket_addr(index);
|
||||||
|
ProtectionDomainCacheEntry* entry = bucket(index);
|
||||||
|
while (true) {
|
||||||
|
assert(entry != NULL, "sanity");
|
||||||
|
|
||||||
|
if (entry == to_delete) {
|
||||||
|
*p = entry->next();
|
||||||
|
Hashtable<oop, mtClass>::free_entry(entry);
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
p = entry->next_addr();
|
||||||
|
entry = *p;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
SymbolPropertyTable::SymbolPropertyTable(int table_size)
|
SymbolPropertyTable::SymbolPropertyTable(int table_size)
|
||||||
: Hashtable<Symbol*, mtSymbol>(table_size, sizeof(SymbolPropertyEntry))
|
: Hashtable<Symbol*, mtSymbol>(table_size, sizeof(SymbolPropertyEntry))
|
||||||
{
|
{
|
||||||
|
@ -532,11 +682,13 @@ void Dictionary::print() {
|
||||||
tty->cr();
|
tty->cr();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
tty->cr();
|
||||||
|
_pd_cache_table->print();
|
||||||
|
tty->cr();
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
void Dictionary::verify() {
|
void Dictionary::verify() {
|
||||||
guarantee(number_of_entries() >= 0, "Verify of system dictionary failed");
|
guarantee(number_of_entries() >= 0, "Verify of system dictionary failed");
|
||||||
|
|
||||||
|
@ -563,5 +715,7 @@ void Dictionary::verify() {
|
||||||
guarantee(number_of_entries() == element_count,
|
guarantee(number_of_entries() == element_count,
|
||||||
"Verify of system dictionary failed");
|
"Verify of system dictionary failed");
|
||||||
debug_only(verify_lookup_length((double)number_of_entries() / table_size()));
|
debug_only(verify_lookup_length((double)number_of_entries() / table_size()));
|
||||||
|
|
||||||
|
_pd_cache_table->verify();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -27,11 +27,14 @@
|
||||||
|
|
||||||
#include "classfile/systemDictionary.hpp"
|
#include "classfile/systemDictionary.hpp"
|
||||||
#include "oops/instanceKlass.hpp"
|
#include "oops/instanceKlass.hpp"
|
||||||
#include "oops/oop.hpp"
|
#include "oops/oop.inline.hpp"
|
||||||
#include "utilities/hashtable.hpp"
|
#include "utilities/hashtable.hpp"
|
||||||
|
|
||||||
class DictionaryEntry;
|
class DictionaryEntry;
|
||||||
class PSPromotionManager;
|
class PSPromotionManager;
|
||||||
|
class ProtectionDomainCacheTable;
|
||||||
|
class ProtectionDomainCacheEntry;
|
||||||
|
class BoolObjectClosure;
|
||||||
|
|
||||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
// The data structure for the system dictionary (and the shared system
|
// The data structure for the system dictionary (and the shared system
|
||||||
|
@ -45,6 +48,8 @@ private:
|
||||||
// pointer to the current hash table entry.
|
// pointer to the current hash table entry.
|
||||||
static DictionaryEntry* _current_class_entry;
|
static DictionaryEntry* _current_class_entry;
|
||||||
|
|
||||||
|
ProtectionDomainCacheTable* _pd_cache_table;
|
||||||
|
|
||||||
DictionaryEntry* get_entry(int index, unsigned int hash,
|
DictionaryEntry* get_entry(int index, unsigned int hash,
|
||||||
Symbol* name, ClassLoaderData* loader_data);
|
Symbol* name, ClassLoaderData* loader_data);
|
||||||
|
|
||||||
|
@ -93,6 +98,7 @@ public:
|
||||||
|
|
||||||
void methods_do(void f(Method*));
|
void methods_do(void f(Method*));
|
||||||
|
|
||||||
|
void unlink(BoolObjectClosure* is_alive);
|
||||||
|
|
||||||
// Classes loaded by the bootstrap loader are always strongly reachable.
|
// Classes loaded by the bootstrap loader are always strongly reachable.
|
||||||
// If we're not doing class unloading, all classes are strongly reachable.
|
// If we're not doing class unloading, all classes are strongly reachable.
|
||||||
|
@ -118,6 +124,7 @@ public:
|
||||||
// Sharing support
|
// Sharing support
|
||||||
void reorder_dictionary();
|
void reorder_dictionary();
|
||||||
|
|
||||||
|
ProtectionDomainCacheEntry* cache_get(oop protection_domain);
|
||||||
|
|
||||||
#ifndef PRODUCT
|
#ifndef PRODUCT
|
||||||
void print();
|
void print();
|
||||||
|
@ -126,21 +133,112 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
// The following classes can be in dictionary.cpp, but we need these
|
// The following classes can be in dictionary.cpp, but we need these
|
||||||
// to be in header file so that SA's vmStructs can access.
|
// to be in header file so that SA's vmStructs can access them.
|
||||||
|
class ProtectionDomainCacheEntry : public HashtableEntry<oop, mtClass> {
|
||||||
|
friend class VMStructs;
|
||||||
|
private:
|
||||||
|
// Flag indicating whether this protection domain entry is strongly reachable.
|
||||||
|
// Used during iterating over the system dictionary to remember oops that need
|
||||||
|
// to be updated.
|
||||||
|
bool _strongly_reachable;
|
||||||
|
public:
|
||||||
|
oop protection_domain() { return literal(); }
|
||||||
|
|
||||||
|
void init() {
|
||||||
|
_strongly_reachable = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ProtectionDomainCacheEntry* next() {
|
||||||
|
return (ProtectionDomainCacheEntry*)HashtableEntry<oop, mtClass>::next();
|
||||||
|
}
|
||||||
|
|
||||||
|
ProtectionDomainCacheEntry** next_addr() {
|
||||||
|
return (ProtectionDomainCacheEntry**)HashtableEntry<oop, mtClass>::next_addr();
|
||||||
|
}
|
||||||
|
|
||||||
|
void oops_do(OopClosure* f) {
|
||||||
|
f->do_oop(literal_addr());
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_strongly_reachable() { _strongly_reachable = true; }
|
||||||
|
bool is_strongly_reachable() { return _strongly_reachable; }
|
||||||
|
void reset_strongly_reachable() { _strongly_reachable = false; }
|
||||||
|
|
||||||
|
void print() PRODUCT_RETURN;
|
||||||
|
void verify();
|
||||||
|
};
|
||||||
|
|
||||||
|
// The ProtectionDomainCacheTable contains all protection domain oops. The system
|
||||||
|
// dictionary entries reference its entries instead of having references to oops
|
||||||
|
// directly.
|
||||||
|
// This is used to speed up system dictionary iteration: the oops in the
|
||||||
|
// protection domain are the only ones referring the Java heap. So when there is
|
||||||
|
// need to update these, instead of going over every entry of the system dictionary,
|
||||||
|
// we only need to iterate over this set.
|
||||||
|
// The amount of different protection domains used is typically magnitudes smaller
|
||||||
|
// than the number of system dictionary entries (loaded classes).
|
||||||
|
class ProtectionDomainCacheTable : public Hashtable<oop, mtClass> {
|
||||||
|
friend class VMStructs;
|
||||||
|
private:
|
||||||
|
ProtectionDomainCacheEntry* bucket(int i) {
|
||||||
|
return (ProtectionDomainCacheEntry*) Hashtable<oop, mtClass>::bucket(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
// The following method is not MT-safe and must be done under lock.
|
||||||
|
ProtectionDomainCacheEntry** bucket_addr(int i) {
|
||||||
|
return (ProtectionDomainCacheEntry**) Hashtable<oop, mtClass>::bucket_addr(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
ProtectionDomainCacheEntry* new_entry(unsigned int hash, oop protection_domain) {
|
||||||
|
ProtectionDomainCacheEntry* entry = (ProtectionDomainCacheEntry*) Hashtable<oop, mtClass>::new_entry(hash, protection_domain);
|
||||||
|
entry->init();
|
||||||
|
return entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned int compute_hash(oop protection_domain) {
|
||||||
|
return (unsigned int)(protection_domain->identity_hash());
|
||||||
|
}
|
||||||
|
|
||||||
|
int index_for(oop protection_domain) {
|
||||||
|
return hash_to_index(compute_hash(protection_domain));
|
||||||
|
}
|
||||||
|
|
||||||
|
ProtectionDomainCacheEntry* add_entry(int index, unsigned int hash, oop protection_domain);
|
||||||
|
ProtectionDomainCacheEntry* find_entry(int index, oop protection_domain);
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
ProtectionDomainCacheTable(int table_size);
|
||||||
|
|
||||||
|
ProtectionDomainCacheEntry* get(oop protection_domain);
|
||||||
|
void free(ProtectionDomainCacheEntry* entry);
|
||||||
|
|
||||||
|
void unlink(BoolObjectClosure* cl);
|
||||||
|
|
||||||
|
// GC support
|
||||||
|
void oops_do(OopClosure* f);
|
||||||
|
void always_strong_oops_do(OopClosure* f);
|
||||||
|
|
||||||
|
static uint bucket_size();
|
||||||
|
|
||||||
|
void print() PRODUCT_RETURN;
|
||||||
|
void verify();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
class ProtectionDomainEntry :public CHeapObj<mtClass> {
|
class ProtectionDomainEntry :public CHeapObj<mtClass> {
|
||||||
friend class VMStructs;
|
friend class VMStructs;
|
||||||
public:
|
public:
|
||||||
ProtectionDomainEntry* _next;
|
ProtectionDomainEntry* _next;
|
||||||
oop _protection_domain;
|
ProtectionDomainCacheEntry* _pd_cache;
|
||||||
|
|
||||||
ProtectionDomainEntry(oop protection_domain, ProtectionDomainEntry* next) {
|
ProtectionDomainEntry(ProtectionDomainCacheEntry* pd_cache, ProtectionDomainEntry* next) {
|
||||||
_protection_domain = protection_domain;
|
_pd_cache = pd_cache;
|
||||||
_next = next;
|
_next = next;
|
||||||
}
|
}
|
||||||
|
|
||||||
ProtectionDomainEntry* next() { return _next; }
|
ProtectionDomainEntry* next() { return _next; }
|
||||||
oop protection_domain() { return _protection_domain; }
|
oop protection_domain() { return _pd_cache->protection_domain(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
// An entry in the system dictionary, this describes a class as
|
// An entry in the system dictionary, this describes a class as
|
||||||
|
@ -151,6 +249,24 @@ class DictionaryEntry : public HashtableEntry<Klass*, mtClass> {
|
||||||
private:
|
private:
|
||||||
// Contains the set of approved protection domains that can access
|
// Contains the set of approved protection domains that can access
|
||||||
// this system dictionary entry.
|
// this system dictionary entry.
|
||||||
|
//
|
||||||
|
// This protection domain set is a set of tuples:
|
||||||
|
//
|
||||||
|
// (InstanceKlass C, initiating class loader ICL, Protection Domain PD)
|
||||||
|
//
|
||||||
|
// [Note that C.protection_domain(), which is stored in the java.lang.Class
|
||||||
|
// mirror of C, is NOT the same as PD]
|
||||||
|
//
|
||||||
|
// If such an entry (C, ICL, PD) exists in the table, it means that
|
||||||
|
// it is okay for a class Foo to reference C, where
|
||||||
|
//
|
||||||
|
// Foo.protection_domain() == PD, and
|
||||||
|
// Foo's defining class loader == ICL
|
||||||
|
//
|
||||||
|
// The usage of the PD set can be seen in SystemDictionary::validate_protection_domain()
|
||||||
|
// It is essentially a cache to avoid repeated Java up-calls to
|
||||||
|
// ClassLoader.checkPackageAccess().
|
||||||
|
//
|
||||||
ProtectionDomainEntry* _pd_set;
|
ProtectionDomainEntry* _pd_set;
|
||||||
ClassLoaderData* _loader_data;
|
ClassLoaderData* _loader_data;
|
||||||
|
|
||||||
|
@ -158,7 +274,7 @@ class DictionaryEntry : public HashtableEntry<Klass*, mtClass> {
|
||||||
// Tells whether a protection is in the approved set.
|
// Tells whether a protection is in the approved set.
|
||||||
bool contains_protection_domain(oop protection_domain) const;
|
bool contains_protection_domain(oop protection_domain) const;
|
||||||
// Adds a protection domain to the approved set.
|
// Adds a protection domain to the approved set.
|
||||||
void add_protection_domain(oop protection_domain);
|
void add_protection_domain(Dictionary* dict, oop protection_domain);
|
||||||
|
|
||||||
Klass* klass() const { return (Klass*)literal(); }
|
Klass* klass() const { return (Klass*)literal(); }
|
||||||
Klass** klass_addr() { return (Klass**)literal_addr(); }
|
Klass** klass_addr() { return (Klass**)literal_addr(); }
|
||||||
|
@ -189,12 +305,11 @@ class DictionaryEntry : public HashtableEntry<Klass*, mtClass> {
|
||||||
: contains_protection_domain(protection_domain());
|
: contains_protection_domain(protection_domain());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void set_strongly_reachable() {
|
||||||
void protection_domain_set_oops_do(OopClosure* f) {
|
|
||||||
for (ProtectionDomainEntry* current = _pd_set;
|
for (ProtectionDomainEntry* current = _pd_set;
|
||||||
current != NULL;
|
current != NULL;
|
||||||
current = current->_next) {
|
current = current->_next) {
|
||||||
f->do_oop(&(current->_protection_domain));
|
current->_pd_cache->set_strongly_reachable();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -202,7 +317,7 @@ class DictionaryEntry : public HashtableEntry<Klass*, mtClass> {
|
||||||
for (ProtectionDomainEntry* current = _pd_set;
|
for (ProtectionDomainEntry* current = _pd_set;
|
||||||
current != NULL;
|
current != NULL;
|
||||||
current = current->_next) {
|
current = current->_next) {
|
||||||
current->_protection_domain->verify();
|
current->_pd_cache->protection_domain()->verify();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1376,8 +1376,15 @@ char* java_lang_Throwable::print_stack_element_to_buffer(Handle mirror,
|
||||||
const char* klass_name = holder->external_name();
|
const char* klass_name = holder->external_name();
|
||||||
int buf_len = (int)strlen(klass_name);
|
int buf_len = (int)strlen(klass_name);
|
||||||
|
|
||||||
// pushing to the stack trace added one.
|
// The method id may point to an obsolete method, can't get more stack information
|
||||||
Method* method = holder->method_with_idnum(method_id);
|
Method* method = holder->method_with_idnum(method_id);
|
||||||
|
if (method == NULL) {
|
||||||
|
char* buf = NEW_RESOURCE_ARRAY(char, buf_len + 64);
|
||||||
|
// This is what the java code prints in this case - added Redefined
|
||||||
|
sprintf(buf, "\tat %s.null (Redefined)", klass_name);
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
char* method_name = method->name()->as_C_string();
|
char* method_name = method->name()->as_C_string();
|
||||||
buf_len += (int)strlen(method_name);
|
buf_len += (int)strlen(method_name);
|
||||||
|
|
||||||
|
@ -1773,7 +1780,8 @@ oop java_lang_Throwable::get_stack_trace_element(oop throwable, int index, TRAPS
|
||||||
return element;
|
return element;
|
||||||
}
|
}
|
||||||
|
|
||||||
oop java_lang_StackTraceElement::create(Handle mirror, int method_id, int version, int bci, TRAPS) {
|
oop java_lang_StackTraceElement::create(Handle mirror, int method_id,
|
||||||
|
int version, int bci, TRAPS) {
|
||||||
// Allocate java.lang.StackTraceElement instance
|
// Allocate java.lang.StackTraceElement instance
|
||||||
Klass* k = SystemDictionary::StackTraceElement_klass();
|
Klass* k = SystemDictionary::StackTraceElement_klass();
|
||||||
assert(k != NULL, "must be loaded in 1.4+");
|
assert(k != NULL, "must be loaded in 1.4+");
|
||||||
|
@ -1790,8 +1798,16 @@ oop java_lang_StackTraceElement::create(Handle mirror, int method_id, int versio
|
||||||
oop classname = StringTable::intern((char*) str, CHECK_0);
|
oop classname = StringTable::intern((char*) str, CHECK_0);
|
||||||
java_lang_StackTraceElement::set_declaringClass(element(), classname);
|
java_lang_StackTraceElement::set_declaringClass(element(), classname);
|
||||||
|
|
||||||
// Fill in method name
|
|
||||||
Method* method = holder->method_with_idnum(method_id);
|
Method* method = holder->method_with_idnum(method_id);
|
||||||
|
// Method on stack may be obsolete because it was redefined so cannot be
|
||||||
|
// found by idnum.
|
||||||
|
if (method == NULL) {
|
||||||
|
// leave name and fileName null
|
||||||
|
java_lang_StackTraceElement::set_lineNumber(element(), -1);
|
||||||
|
return element();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fill in method name
|
||||||
oop methodname = StringTable::intern(method->name(), CHECK_0);
|
oop methodname = StringTable::intern(method->name(), CHECK_0);
|
||||||
java_lang_StackTraceElement::set_methodName(element(), methodname);
|
java_lang_StackTraceElement::set_methodName(element(), methodname);
|
||||||
|
|
||||||
|
|
|
@ -107,18 +107,13 @@ private:
|
||||||
add(loader_data, cp, names_count, name, lengths, cp_indices, hashValues, THREAD);
|
add(loader_data, cp, names_count, name, lengths, cp_indices, hashValues, THREAD);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Table size
|
|
||||||
enum {
|
|
||||||
symbol_table_size = 20011
|
|
||||||
};
|
|
||||||
|
|
||||||
Symbol* lookup(int index, const char* name, int len, unsigned int hash);
|
Symbol* lookup(int index, const char* name, int len, unsigned int hash);
|
||||||
|
|
||||||
SymbolTable()
|
SymbolTable()
|
||||||
: Hashtable<Symbol*, mtSymbol>(symbol_table_size, sizeof (HashtableEntry<Symbol*, mtSymbol>)) {}
|
: Hashtable<Symbol*, mtSymbol>(SymbolTableSize, sizeof (HashtableEntry<Symbol*, mtSymbol>)) {}
|
||||||
|
|
||||||
SymbolTable(HashtableBucket<mtSymbol>* t, int number_of_entries)
|
SymbolTable(HashtableBucket<mtSymbol>* t, int number_of_entries)
|
||||||
: Hashtable<Symbol*, mtSymbol>(symbol_table_size, sizeof (HashtableEntry<Symbol*, mtSymbol>), t,
|
: Hashtable<Symbol*, mtSymbol>(SymbolTableSize, sizeof (HashtableEntry<Symbol*, mtSymbol>), t,
|
||||||
number_of_entries) {}
|
number_of_entries) {}
|
||||||
|
|
||||||
// Arena for permanent symbols (null class loader) that are never unloaded
|
// Arena for permanent symbols (null class loader) that are never unloaded
|
||||||
|
@ -136,6 +131,9 @@ public:
|
||||||
// The symbol table
|
// The symbol table
|
||||||
static SymbolTable* the_table() { return _the_table; }
|
static SymbolTable* the_table() { return _the_table; }
|
||||||
|
|
||||||
|
// Size of one bucket in the string table. Used when checking for rollover.
|
||||||
|
static uint bucket_size() { return sizeof(HashtableBucket<mtSymbol>); }
|
||||||
|
|
||||||
static void create_table() {
|
static void create_table() {
|
||||||
assert(_the_table == NULL, "One symbol table allowed.");
|
assert(_the_table == NULL, "One symbol table allowed.");
|
||||||
_the_table = new SymbolTable();
|
_the_table = new SymbolTable();
|
||||||
|
@ -145,8 +143,11 @@ public:
|
||||||
static void create_table(HashtableBucket<mtSymbol>* t, int length,
|
static void create_table(HashtableBucket<mtSymbol>* t, int length,
|
||||||
int number_of_entries) {
|
int number_of_entries) {
|
||||||
assert(_the_table == NULL, "One symbol table allowed.");
|
assert(_the_table == NULL, "One symbol table allowed.");
|
||||||
assert(length == symbol_table_size * sizeof(HashtableBucket<mtSymbol>),
|
|
||||||
"bad shared symbol size.");
|
// If CDS archive used a different symbol table size, use that size instead
|
||||||
|
// which is better than giving an error.
|
||||||
|
SymbolTableSize = length/bucket_size();
|
||||||
|
|
||||||
_the_table = new SymbolTable(t, number_of_entries);
|
_the_table = new SymbolTable(t, number_of_entries);
|
||||||
// if CDS give symbol table a default arena size since most symbols
|
// if CDS give symbol table a default arena size since most symbols
|
||||||
// are already allocated in the shared misc section.
|
// are already allocated in the shared misc section.
|
||||||
|
|
|
@ -1697,6 +1697,24 @@ int SystemDictionary::calculate_systemdictionary_size(int classcount) {
|
||||||
return newsize;
|
return newsize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef ASSERT
|
||||||
|
class VerifySDReachableAndLiveClosure : public OopClosure {
|
||||||
|
private:
|
||||||
|
BoolObjectClosure* _is_alive;
|
||||||
|
|
||||||
|
template <class T> void do_oop_work(T* p) {
|
||||||
|
oop obj = oopDesc::load_decode_heap_oop(p);
|
||||||
|
guarantee(_is_alive->do_object_b(obj), "Oop in system dictionary must be live");
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
VerifySDReachableAndLiveClosure(BoolObjectClosure* is_alive) : OopClosure(), _is_alive(is_alive) { }
|
||||||
|
|
||||||
|
virtual void do_oop(oop* p) { do_oop_work(p); }
|
||||||
|
virtual void do_oop(narrowOop* p) { do_oop_work(p); }
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
// Assumes classes in the SystemDictionary are only unloaded at a safepoint
|
// Assumes classes in the SystemDictionary are only unloaded at a safepoint
|
||||||
// Note: anonymous classes are not in the SD.
|
// Note: anonymous classes are not in the SD.
|
||||||
bool SystemDictionary::do_unloading(BoolObjectClosure* is_alive) {
|
bool SystemDictionary::do_unloading(BoolObjectClosure* is_alive) {
|
||||||
|
@ -1708,6 +1726,14 @@ bool SystemDictionary::do_unloading(BoolObjectClosure* is_alive) {
|
||||||
constraints()->purge_loader_constraints();
|
constraints()->purge_loader_constraints();
|
||||||
resolution_errors()->purge_resolution_errors();
|
resolution_errors()->purge_resolution_errors();
|
||||||
}
|
}
|
||||||
|
// Oops referenced by the system dictionary may get unreachable independently
|
||||||
|
// of the class loader (eg. cached protection domain oops). So we need to
|
||||||
|
// explicitly unlink them here instead of in Dictionary::do_unloading.
|
||||||
|
dictionary()->unlink(is_alive);
|
||||||
|
#ifdef ASSERT
|
||||||
|
VerifySDReachableAndLiveClosure cl(is_alive);
|
||||||
|
dictionary()->oops_do(&cl);
|
||||||
|
#endif
|
||||||
return unloading_occurred;
|
return unloading_occurred;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2441,6 +2441,11 @@ void ClassVerifier::verify_invoke_instructions(
|
||||||
current_class()->super()->name()))) {
|
current_class()->super()->name()))) {
|
||||||
bool subtype = ref_class_type.is_assignable_from(
|
bool subtype = ref_class_type.is_assignable_from(
|
||||||
current_type(), this, CHECK_VERIFY(this));
|
current_type(), this, CHECK_VERIFY(this));
|
||||||
|
if (!subtype) {
|
||||||
|
if (current_class()->is_anonymous()) {
|
||||||
|
subtype = ref_class_type.is_assignable_from(VerificationType::reference_type(
|
||||||
|
current_class()->host_klass()->name()), this, CHECK_VERIFY(this));
|
||||||
|
}
|
||||||
if (!subtype) {
|
if (!subtype) {
|
||||||
verify_error(ErrorContext::bad_code(bci),
|
verify_error(ErrorContext::bad_code(bci),
|
||||||
"Bad invokespecial instruction: "
|
"Bad invokespecial instruction: "
|
||||||
|
@ -2448,6 +2453,7 @@ void ClassVerifier::verify_invoke_instructions(
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
// Match method descriptor with operand stack
|
// Match method descriptor with operand stack
|
||||||
for (int i = nargs - 1; i >= 0; i--) { // Run backwards
|
for (int i = nargs - 1; i >= 0; i--) { // Run backwards
|
||||||
current_frame->pop_stack(sig_types[i], CHECK_VERIFY(this));
|
current_frame->pop_stack(sig_types[i], CHECK_VERIFY(this));
|
||||||
|
@ -2461,7 +2467,28 @@ void ClassVerifier::verify_invoke_instructions(
|
||||||
} else { // other methods
|
} else { // other methods
|
||||||
// Ensures that target class is assignable to method class.
|
// Ensures that target class is assignable to method class.
|
||||||
if (opcode == Bytecodes::_invokespecial) {
|
if (opcode == Bytecodes::_invokespecial) {
|
||||||
|
if (!current_class()->is_anonymous()) {
|
||||||
current_frame->pop_stack(current_type(), CHECK_VERIFY(this));
|
current_frame->pop_stack(current_type(), CHECK_VERIFY(this));
|
||||||
|
} else {
|
||||||
|
// anonymous class invokespecial calls: either the
|
||||||
|
// operand stack/objectref is a subtype of the current class OR
|
||||||
|
// the objectref is a subtype of the host_klass of the current class
|
||||||
|
// to allow an anonymous class to reference methods in the host_klass
|
||||||
|
VerificationType top = current_frame->pop_stack(CHECK_VERIFY(this));
|
||||||
|
bool subtype = current_type().is_assignable_from(top, this, CHECK_VERIFY(this));
|
||||||
|
if (!subtype) {
|
||||||
|
VerificationType hosttype =
|
||||||
|
VerificationType::reference_type(current_class()->host_klass()->name());
|
||||||
|
subtype = hosttype.is_assignable_from(top, this, CHECK_VERIFY(this));
|
||||||
|
}
|
||||||
|
if (!subtype) {
|
||||||
|
verify_error( ErrorContext::bad_type(current_frame->offset(),
|
||||||
|
current_frame->stack_top_ctx(),
|
||||||
|
TypeOrigin::implicit(top)),
|
||||||
|
"Bad type on operand stack");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
} else if (opcode == Bytecodes::_invokevirtual) {
|
} else if (opcode == Bytecodes::_invokevirtual) {
|
||||||
VerificationType stack_object_type =
|
VerificationType stack_object_type =
|
||||||
current_frame->pop_stack(ref_class_type, CHECK_VERIFY(this));
|
current_frame->pop_stack(ref_class_type, CHECK_VERIFY(this));
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -812,8 +812,8 @@ class ClassHierarchyWalker {
|
||||||
Klass* k = ctxk;
|
Klass* k = ctxk;
|
||||||
Method* lm = k->lookup_method(m->name(), m->signature());
|
Method* lm = k->lookup_method(m->name(), m->signature());
|
||||||
if (lm == NULL && k->oop_is_instance()) {
|
if (lm == NULL && k->oop_is_instance()) {
|
||||||
// It might be an abstract interface method, devoid of mirandas.
|
// It might be an interface method
|
||||||
lm = ((InstanceKlass*)k)->lookup_method_in_all_interfaces(m->name(),
|
lm = ((InstanceKlass*)k)->lookup_method_in_ordered_interfaces(m->name(),
|
||||||
m->signature());
|
m->signature());
|
||||||
}
|
}
|
||||||
if (lm == m)
|
if (lm == m)
|
||||||
|
|
|
@ -6035,8 +6035,12 @@ void G1CollectedHeap::verify_dirty_region(HeapRegion* hr) {
|
||||||
// is dirty.
|
// is dirty.
|
||||||
G1SATBCardTableModRefBS* ct_bs = g1_barrier_set();
|
G1SATBCardTableModRefBS* ct_bs = g1_barrier_set();
|
||||||
MemRegion mr(hr->bottom(), hr->pre_dummy_top());
|
MemRegion mr(hr->bottom(), hr->pre_dummy_top());
|
||||||
|
if (hr->is_young()) {
|
||||||
|
ct_bs->verify_g1_young_region(mr);
|
||||||
|
} else {
|
||||||
ct_bs->verify_dirty_region(mr);
|
ct_bs->verify_dirty_region(mr);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void G1CollectedHeap::verify_dirty_young_list(HeapRegion* head) {
|
void G1CollectedHeap::verify_dirty_young_list(HeapRegion* head) {
|
||||||
G1SATBCardTableModRefBS* ct_bs = g1_barrier_set();
|
G1SATBCardTableModRefBS* ct_bs = g1_barrier_set();
|
||||||
|
|
|
@ -29,6 +29,7 @@
|
||||||
#include "gc_implementation/g1/g1CollectedHeap.hpp"
|
#include "gc_implementation/g1/g1CollectedHeap.hpp"
|
||||||
#include "gc_implementation/g1/g1AllocRegion.inline.hpp"
|
#include "gc_implementation/g1/g1AllocRegion.inline.hpp"
|
||||||
#include "gc_implementation/g1/g1CollectorPolicy.hpp"
|
#include "gc_implementation/g1/g1CollectorPolicy.hpp"
|
||||||
|
#include "gc_implementation/g1/g1SATBCardTableModRefBS.hpp"
|
||||||
#include "gc_implementation/g1/heapRegionSeq.inline.hpp"
|
#include "gc_implementation/g1/heapRegionSeq.inline.hpp"
|
||||||
#include "utilities/taskqueue.hpp"
|
#include "utilities/taskqueue.hpp"
|
||||||
|
|
||||||
|
@ -134,7 +135,7 @@ G1CollectedHeap::dirty_young_block(HeapWord* start, size_t word_size) {
|
||||||
assert(containing_hr->is_in(end - 1), "it should also contain end - 1");
|
assert(containing_hr->is_in(end - 1), "it should also contain end - 1");
|
||||||
|
|
||||||
MemRegion mr(start, end);
|
MemRegion mr(start, end);
|
||||||
g1_barrier_set()->dirty(mr);
|
g1_barrier_set()->g1_mark_as_young(mr);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline RefToScanQueue* G1CollectedHeap::task_queue(int i) const {
|
inline RefToScanQueue* G1CollectedHeap::task_queue(int i) const {
|
||||||
|
|
|
@ -319,10 +319,10 @@ G1CollectorPolicy::G1CollectorPolicy() :
|
||||||
}
|
}
|
||||||
|
|
||||||
void G1CollectorPolicy::initialize_flags() {
|
void G1CollectorPolicy::initialize_flags() {
|
||||||
set_min_alignment(HeapRegion::GrainBytes);
|
_min_alignment = HeapRegion::GrainBytes;
|
||||||
size_t card_table_alignment = GenRemSet::max_alignment_constraint(rem_set_name());
|
size_t card_table_alignment = GenRemSet::max_alignment_constraint(rem_set_name());
|
||||||
size_t page_size = UseLargePages ? os::large_page_size() : os::vm_page_size();
|
size_t page_size = UseLargePages ? os::large_page_size() : os::vm_page_size();
|
||||||
set_max_alignment(MAX3(card_table_alignment, min_alignment(), page_size));
|
_max_alignment = MAX3(card_table_alignment, _min_alignment, page_size);
|
||||||
if (SurvivorRatio < 1) {
|
if (SurvivorRatio < 1) {
|
||||||
vm_exit_during_initialization("Invalid survivor ratio specified");
|
vm_exit_during_initialization("Invalid survivor ratio specified");
|
||||||
}
|
}
|
||||||
|
|
|
@ -70,6 +70,12 @@ bool G1SATBCardTableModRefBS::mark_card_deferred(size_t card_index) {
|
||||||
if ((val & (clean_card_mask_val() | deferred_card_val())) == deferred_card_val()) {
|
if ((val & (clean_card_mask_val() | deferred_card_val())) == deferred_card_val()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (val == g1_young_gen) {
|
||||||
|
// the card is for a young gen region. We don't need to keep track of all pointers into young
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// Cached bit can be installed either on a clean card or on a claimed card.
|
// Cached bit can be installed either on a clean card or on a claimed card.
|
||||||
jbyte new_val = val;
|
jbyte new_val = val;
|
||||||
if (val == clean_card_val()) {
|
if (val == clean_card_val()) {
|
||||||
|
@ -85,6 +91,19 @@ bool G1SATBCardTableModRefBS::mark_card_deferred(size_t card_index) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void G1SATBCardTableModRefBS::g1_mark_as_young(const MemRegion& mr) {
|
||||||
|
jbyte *const first = byte_for(mr.start());
|
||||||
|
jbyte *const last = byte_after(mr.last());
|
||||||
|
|
||||||
|
memset(first, g1_young_gen, last - first);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef PRODUCT
|
||||||
|
void G1SATBCardTableModRefBS::verify_g1_young_region(MemRegion mr) {
|
||||||
|
verify_region(mr, g1_young_gen, true);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
G1SATBCardTableLoggingModRefBS::
|
G1SATBCardTableLoggingModRefBS::
|
||||||
G1SATBCardTableLoggingModRefBS(MemRegion whole_heap,
|
G1SATBCardTableLoggingModRefBS(MemRegion whole_heap,
|
||||||
int max_covered_regions) :
|
int max_covered_regions) :
|
||||||
|
@ -97,7 +116,11 @@ G1SATBCardTableLoggingModRefBS(MemRegion whole_heap,
|
||||||
void
|
void
|
||||||
G1SATBCardTableLoggingModRefBS::write_ref_field_work(void* field,
|
G1SATBCardTableLoggingModRefBS::write_ref_field_work(void* field,
|
||||||
oop new_val) {
|
oop new_val) {
|
||||||
jbyte* byte = byte_for(field);
|
volatile jbyte* byte = byte_for(field);
|
||||||
|
if (*byte == g1_young_gen) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
OrderAccess::storeload();
|
||||||
if (*byte != dirty_card) {
|
if (*byte != dirty_card) {
|
||||||
*byte = dirty_card;
|
*byte = dirty_card;
|
||||||
Thread* thr = Thread::current();
|
Thread* thr = Thread::current();
|
||||||
|
@ -129,7 +152,7 @@ G1SATBCardTableLoggingModRefBS::write_ref_field_static(void* field,
|
||||||
|
|
||||||
void
|
void
|
||||||
G1SATBCardTableLoggingModRefBS::invalidate(MemRegion mr, bool whole_heap) {
|
G1SATBCardTableLoggingModRefBS::invalidate(MemRegion mr, bool whole_heap) {
|
||||||
jbyte* byte = byte_for(mr.start());
|
volatile jbyte* byte = byte_for(mr.start());
|
||||||
jbyte* last_byte = byte_for(mr.last());
|
jbyte* last_byte = byte_for(mr.last());
|
||||||
Thread* thr = Thread::current();
|
Thread* thr = Thread::current();
|
||||||
if (whole_heap) {
|
if (whole_heap) {
|
||||||
|
@ -138,25 +161,35 @@ G1SATBCardTableLoggingModRefBS::invalidate(MemRegion mr, bool whole_heap) {
|
||||||
byte++;
|
byte++;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
// skip all consecutive young cards
|
||||||
|
for (; byte <= last_byte && *byte == g1_young_gen; byte++);
|
||||||
|
|
||||||
|
if (byte <= last_byte) {
|
||||||
|
OrderAccess::storeload();
|
||||||
// Enqueue if necessary.
|
// Enqueue if necessary.
|
||||||
if (thr->is_Java_thread()) {
|
if (thr->is_Java_thread()) {
|
||||||
JavaThread* jt = (JavaThread*)thr;
|
JavaThread* jt = (JavaThread*)thr;
|
||||||
while (byte <= last_byte) {
|
for (; byte <= last_byte; byte++) {
|
||||||
|
if (*byte == g1_young_gen) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (*byte != dirty_card) {
|
if (*byte != dirty_card) {
|
||||||
*byte = dirty_card;
|
*byte = dirty_card;
|
||||||
jt->dirty_card_queue().enqueue(byte);
|
jt->dirty_card_queue().enqueue(byte);
|
||||||
}
|
}
|
||||||
byte++;
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
MutexLockerEx x(Shared_DirtyCardQ_lock,
|
MutexLockerEx x(Shared_DirtyCardQ_lock,
|
||||||
Mutex::_no_safepoint_check_flag);
|
Mutex::_no_safepoint_check_flag);
|
||||||
while (byte <= last_byte) {
|
for (; byte <= last_byte; byte++) {
|
||||||
|
if (*byte == g1_young_gen) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (*byte != dirty_card) {
|
if (*byte != dirty_card) {
|
||||||
*byte = dirty_card;
|
*byte = dirty_card;
|
||||||
_dcqs.shared_dirty_card_queue()->enqueue(byte);
|
_dcqs.shared_dirty_card_queue()->enqueue(byte);
|
||||||
}
|
}
|
||||||
byte++;
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,7 +38,14 @@ class DirtyCardQueueSet;
|
||||||
// snapshot-at-the-beginning marking.
|
// snapshot-at-the-beginning marking.
|
||||||
|
|
||||||
class G1SATBCardTableModRefBS: public CardTableModRefBSForCTRS {
|
class G1SATBCardTableModRefBS: public CardTableModRefBSForCTRS {
|
||||||
|
protected:
|
||||||
|
enum G1CardValues {
|
||||||
|
g1_young_gen = CT_MR_BS_last_reserved << 1
|
||||||
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
static int g1_young_card_val() { return g1_young_gen; }
|
||||||
|
|
||||||
// Add "pre_val" to a set of objects that may have been disconnected from the
|
// Add "pre_val" to a set of objects that may have been disconnected from the
|
||||||
// pre-marking object graph.
|
// pre-marking object graph.
|
||||||
static void enqueue(oop pre_val);
|
static void enqueue(oop pre_val);
|
||||||
|
@ -118,6 +125,9 @@ public:
|
||||||
_byte_map[card_index] = val;
|
_byte_map[card_index] = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void verify_g1_young_region(MemRegion mr) PRODUCT_RETURN;
|
||||||
|
void g1_mark_as_young(const MemRegion& mr);
|
||||||
|
|
||||||
bool mark_card_deferred(size_t card_index);
|
bool mark_card_deferred(size_t card_index);
|
||||||
|
|
||||||
bool is_card_deferred(size_t card_index) {
|
bool is_card_deferred(size_t card_index) {
|
||||||
|
|
|
@ -80,6 +80,10 @@ public:
|
||||||
|
|
||||||
void reset() { if (_buf != NULL) _index = _sz; }
|
void reset() { if (_buf != NULL) _index = _sz; }
|
||||||
|
|
||||||
|
void enqueue(volatile void* ptr) {
|
||||||
|
enqueue((void*)(ptr));
|
||||||
|
}
|
||||||
|
|
||||||
// Enqueues the given "obj".
|
// Enqueues the given "obj".
|
||||||
void enqueue(void* ptr) {
|
void enqueue(void* ptr) {
|
||||||
if (!_active) return;
|
if (!_active) return;
|
||||||
|
|
|
@ -214,9 +214,6 @@ class VM_CollectForMetadataAllocation: public VM_GC_Operation {
|
||||||
: VM_GC_Operation(gc_count_before, gc_cause, full_gc_count_before, true),
|
: VM_GC_Operation(gc_count_before, gc_cause, full_gc_count_before, true),
|
||||||
_loader_data(loader_data), _size(size), _mdtype(mdtype), _result(NULL) {
|
_loader_data(loader_data), _size(size), _mdtype(mdtype), _result(NULL) {
|
||||||
}
|
}
|
||||||
~VM_CollectForMetadataAllocation() {
|
|
||||||
MetaspaceGC::set_expand_after_GC(false);
|
|
||||||
}
|
|
||||||
virtual VMOp_Type type() const { return VMOp_CollectForMetadataAllocation; }
|
virtual VMOp_Type type() const { return VMOp_CollectForMetadataAllocation; }
|
||||||
virtual void doit();
|
virtual void doit();
|
||||||
MetaWord* result() const { return _result; }
|
MetaWord* result() const { return _result; }
|
||||||
|
|
|
@ -202,12 +202,6 @@ void CollectedHeap::collect_as_vm_thread(GCCause::Cause cause) {
|
||||||
ShouldNotReachHere(); // Unexpected use of this function
|
ShouldNotReachHere(); // Unexpected use of this function
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
MetaWord* CollectedHeap::satisfy_failed_metadata_allocation(
|
|
||||||
ClassLoaderData* loader_data,
|
|
||||||
size_t size, Metaspace::MetadataType mdtype) {
|
|
||||||
return collector_policy()->satisfy_failed_metadata_allocation(loader_data, size, mdtype);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void CollectedHeap::pre_initialize() {
|
void CollectedHeap::pre_initialize() {
|
||||||
// Used for ReduceInitialCardMarks (when COMPILER2 is used);
|
// Used for ReduceInitialCardMarks (when COMPILER2 is used);
|
||||||
|
|
|
@ -475,11 +475,6 @@ class CollectedHeap : public CHeapObj<mtInternal> {
|
||||||
// the context of the vm thread.
|
// the context of the vm thread.
|
||||||
virtual void collect_as_vm_thread(GCCause::Cause cause);
|
virtual void collect_as_vm_thread(GCCause::Cause cause);
|
||||||
|
|
||||||
// Callback from VM_CollectForMetadataAllocation operation.
|
|
||||||
MetaWord* satisfy_failed_metadata_allocation(ClassLoaderData* loader_data,
|
|
||||||
size_t size,
|
|
||||||
Metaspace::MetadataType mdtype);
|
|
||||||
|
|
||||||
// Returns the barrier set for this heap
|
// Returns the barrier set for this heap
|
||||||
BarrierSet* barrier_set() { return _barrier_set; }
|
BarrierSet* barrier_set() { return _barrier_set; }
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
/*
|
/*
|
||||||
|
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -221,8 +222,17 @@ void LinkResolver::resolve_klass(KlassHandle& result, constantPoolHandle pool, i
|
||||||
//
|
//
|
||||||
// According to JVM spec. $5.4.3c & $5.4.3d
|
// According to JVM spec. $5.4.3c & $5.4.3d
|
||||||
|
|
||||||
|
// Look up method in klasses, including static methods
|
||||||
|
// Then look up local default methods
|
||||||
void LinkResolver::lookup_method_in_klasses(methodHandle& result, KlassHandle klass, Symbol* name, Symbol* signature, TRAPS) {
|
void LinkResolver::lookup_method_in_klasses(methodHandle& result, KlassHandle klass, Symbol* name, Symbol* signature, TRAPS) {
|
||||||
Method* result_oop = klass->uncached_lookup_method(name, signature);
|
Method* result_oop = klass->uncached_lookup_method(name, signature);
|
||||||
|
if (result_oop == NULL) {
|
||||||
|
Array<Method*>* default_methods = InstanceKlass::cast(klass())->default_methods();
|
||||||
|
if (default_methods != NULL) {
|
||||||
|
result_oop = InstanceKlass::find_method(default_methods, name, signature);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (EnableInvokeDynamic && result_oop != NULL) {
|
if (EnableInvokeDynamic && result_oop != NULL) {
|
||||||
vmIntrinsics::ID iid = result_oop->intrinsic_id();
|
vmIntrinsics::ID iid = result_oop->intrinsic_id();
|
||||||
if (MethodHandles::is_signature_polymorphic(iid)) {
|
if (MethodHandles::is_signature_polymorphic(iid)) {
|
||||||
|
@ -234,6 +244,7 @@ void LinkResolver::lookup_method_in_klasses(methodHandle& result, KlassHandle kl
|
||||||
}
|
}
|
||||||
|
|
||||||
// returns first instance method
|
// returns first instance method
|
||||||
|
// Looks up method in classes, then looks up local default methods
|
||||||
void LinkResolver::lookup_instance_method_in_klasses(methodHandle& result, KlassHandle klass, Symbol* name, Symbol* signature, TRAPS) {
|
void LinkResolver::lookup_instance_method_in_klasses(methodHandle& result, KlassHandle klass, Symbol* name, Symbol* signature, TRAPS) {
|
||||||
Method* result_oop = klass->uncached_lookup_method(name, signature);
|
Method* result_oop = klass->uncached_lookup_method(name, signature);
|
||||||
result = methodHandle(THREAD, result_oop);
|
result = methodHandle(THREAD, result_oop);
|
||||||
|
@ -241,13 +252,38 @@ void LinkResolver::lookup_instance_method_in_klasses(methodHandle& result, Klass
|
||||||
klass = KlassHandle(THREAD, result->method_holder()->super());
|
klass = KlassHandle(THREAD, result->method_holder()->super());
|
||||||
result = methodHandle(THREAD, klass->uncached_lookup_method(name, signature));
|
result = methodHandle(THREAD, klass->uncached_lookup_method(name, signature));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (result.is_null()) {
|
||||||
|
Array<Method*>* default_methods = InstanceKlass::cast(klass())->default_methods();
|
||||||
|
if (default_methods != NULL) {
|
||||||
|
result = methodHandle(InstanceKlass::find_method(default_methods, name, signature));
|
||||||
|
assert(result.is_null() || !result->is_static(), "static defaults not allowed");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int LinkResolver::vtable_index_of_interface_method(KlassHandle klass,
|
||||||
|
methodHandle resolved_method, TRAPS) {
|
||||||
|
|
||||||
int LinkResolver::vtable_index_of_miranda_method(KlassHandle klass, Symbol* name, Symbol* signature, TRAPS) {
|
int vtable_index = Method::invalid_vtable_index;
|
||||||
|
Symbol* name = resolved_method->name();
|
||||||
|
Symbol* signature = resolved_method->signature();
|
||||||
|
|
||||||
|
// First check in default method array
|
||||||
|
if (!resolved_method->is_abstract() &&
|
||||||
|
(InstanceKlass::cast(klass())->default_methods() != NULL)) {
|
||||||
|
int index = InstanceKlass::find_method_index(InstanceKlass::cast(klass())->default_methods(), name, signature);
|
||||||
|
if (index >= 0 ) {
|
||||||
|
vtable_index = InstanceKlass::cast(klass())->default_vtable_indices()->at(index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (vtable_index == Method::invalid_vtable_index) {
|
||||||
|
// get vtable_index for miranda methods
|
||||||
ResourceMark rm(THREAD);
|
ResourceMark rm(THREAD);
|
||||||
klassVtable *vt = InstanceKlass::cast(klass())->vtable();
|
klassVtable *vt = InstanceKlass::cast(klass())->vtable();
|
||||||
return vt->index_of_miranda(name, signature);
|
vtable_index = vt->index_of_miranda(name, signature);
|
||||||
|
}
|
||||||
|
return vtable_index;
|
||||||
}
|
}
|
||||||
|
|
||||||
void LinkResolver::lookup_method_in_interfaces(methodHandle& result, KlassHandle klass, Symbol* name, Symbol* signature, TRAPS) {
|
void LinkResolver::lookup_method_in_interfaces(methodHandle& result, KlassHandle klass, Symbol* name, Symbol* signature, TRAPS) {
|
||||||
|
@ -625,6 +661,12 @@ void LinkResolver::resolve_interface_method(methodHandle& resolved_method,
|
||||||
resolved_method->method_holder()->internal_name()
|
resolved_method->method_holder()->internal_name()
|
||||||
);
|
);
|
||||||
resolved_method->access_flags().print_on(tty);
|
resolved_method->access_flags().print_on(tty);
|
||||||
|
if (resolved_method->is_default_method()) {
|
||||||
|
tty->print("default");
|
||||||
|
}
|
||||||
|
if (resolved_method->is_overpass()) {
|
||||||
|
tty->print("overpass");
|
||||||
|
}
|
||||||
tty->cr();
|
tty->cr();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -853,6 +895,7 @@ void LinkResolver::linktime_resolve_special_method(methodHandle& resolved_method
|
||||||
resolved_method->signature()));
|
resolved_method->signature()));
|
||||||
THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(), buf);
|
THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(), buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (TraceItables && Verbose) {
|
if (TraceItables && Verbose) {
|
||||||
ResourceMark rm(THREAD);
|
ResourceMark rm(THREAD);
|
||||||
tty->print("invokespecial resolved method: caller-class:%s, compile-time-class:%s, method:%s, method_holder:%s, access_flags: ",
|
tty->print("invokespecial resolved method: caller-class:%s, compile-time-class:%s, method:%s, method_holder:%s, access_flags: ",
|
||||||
|
@ -864,8 +907,7 @@ void LinkResolver::linktime_resolve_special_method(methodHandle& resolved_method
|
||||||
resolved_method->method_holder()->internal_name()
|
resolved_method->method_holder()->internal_name()
|
||||||
);
|
);
|
||||||
resolved_method->access_flags().print_on(tty);
|
resolved_method->access_flags().print_on(tty);
|
||||||
if (resolved_method->method_holder()->is_interface() &&
|
if (resolved_method->is_default_method()) {
|
||||||
!resolved_method->is_abstract()) {
|
|
||||||
tty->print("default");
|
tty->print("default");
|
||||||
}
|
}
|
||||||
if (resolved_method->is_overpass()) {
|
if (resolved_method->is_overpass()) {
|
||||||
|
@ -945,10 +987,12 @@ void LinkResolver::runtime_resolve_special_method(CallInfo& result, methodHandle
|
||||||
sel_method->method_holder()->internal_name()
|
sel_method->method_holder()->internal_name()
|
||||||
);
|
);
|
||||||
sel_method->access_flags().print_on(tty);
|
sel_method->access_flags().print_on(tty);
|
||||||
if (sel_method->method_holder()->is_interface() &&
|
if (sel_method->is_default_method()) {
|
||||||
!sel_method->is_abstract()) {
|
|
||||||
tty->print("default");
|
tty->print("default");
|
||||||
}
|
}
|
||||||
|
if (sel_method->is_overpass()) {
|
||||||
|
tty->print("overpass");
|
||||||
|
}
|
||||||
tty->cr();
|
tty->cr();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1007,8 +1051,7 @@ void LinkResolver::linktime_resolve_virtual_method(methodHandle &resolved_method
|
||||||
resolved_method->method_holder()->internal_name()
|
resolved_method->method_holder()->internal_name()
|
||||||
);
|
);
|
||||||
resolved_method->access_flags().print_on(tty);
|
resolved_method->access_flags().print_on(tty);
|
||||||
if (resolved_method->method_holder()->is_interface() &&
|
if (resolved_method->is_default_method()) {
|
||||||
!resolved_method->is_abstract()) {
|
|
||||||
tty->print("default");
|
tty->print("default");
|
||||||
}
|
}
|
||||||
if (resolved_method->is_overpass()) {
|
if (resolved_method->is_overpass()) {
|
||||||
|
@ -1045,10 +1088,8 @@ void LinkResolver::runtime_resolve_virtual_method(CallInfo& result,
|
||||||
|
|
||||||
// do lookup based on receiver klass using the vtable index
|
// do lookup based on receiver klass using the vtable index
|
||||||
if (resolved_method->method_holder()->is_interface()) { // miranda method
|
if (resolved_method->method_holder()->is_interface()) { // miranda method
|
||||||
vtable_index = vtable_index_of_miranda_method(resolved_klass,
|
vtable_index = vtable_index_of_interface_method(resolved_klass,
|
||||||
resolved_method->name(),
|
resolved_method, CHECK);
|
||||||
resolved_method->signature(), CHECK);
|
|
||||||
|
|
||||||
assert(vtable_index >= 0 , "we should have valid vtable index at this point");
|
assert(vtable_index >= 0 , "we should have valid vtable index at this point");
|
||||||
|
|
||||||
InstanceKlass* inst = InstanceKlass::cast(recv_klass());
|
InstanceKlass* inst = InstanceKlass::cast(recv_klass());
|
||||||
|
@ -1104,11 +1145,10 @@ void LinkResolver::runtime_resolve_virtual_method(CallInfo& result,
|
||||||
vtable_index
|
vtable_index
|
||||||
);
|
);
|
||||||
selected_method->access_flags().print_on(tty);
|
selected_method->access_flags().print_on(tty);
|
||||||
if (selected_method->method_holder()->is_interface() &&
|
if (selected_method->is_default_method()) {
|
||||||
!selected_method->is_abstract()) {
|
|
||||||
tty->print("default");
|
tty->print("default");
|
||||||
}
|
}
|
||||||
if (resolved_method->is_overpass()) {
|
if (selected_method->is_overpass()) {
|
||||||
tty->print("overpass");
|
tty->print("overpass");
|
||||||
}
|
}
|
||||||
tty->cr();
|
tty->cr();
|
||||||
|
@ -1191,7 +1231,6 @@ void LinkResolver::runtime_resolve_interface_method(CallInfo& result, methodHand
|
||||||
sel_method->name(),
|
sel_method->name(),
|
||||||
sel_method->signature()));
|
sel_method->signature()));
|
||||||
}
|
}
|
||||||
|
|
||||||
// check if abstract
|
// check if abstract
|
||||||
if (check_null_and_abstract && sel_method->is_abstract()) {
|
if (check_null_and_abstract && sel_method->is_abstract()) {
|
||||||
ResourceMark rm(THREAD);
|
ResourceMark rm(THREAD);
|
||||||
|
@ -1220,11 +1259,10 @@ void LinkResolver::runtime_resolve_interface_method(CallInfo& result, methodHand
|
||||||
sel_method->method_holder()->internal_name()
|
sel_method->method_holder()->internal_name()
|
||||||
);
|
);
|
||||||
sel_method->access_flags().print_on(tty);
|
sel_method->access_flags().print_on(tty);
|
||||||
if (sel_method->method_holder()->is_interface() &&
|
if (sel_method->is_default_method()) {
|
||||||
!sel_method->is_abstract()) {
|
|
||||||
tty->print("default");
|
tty->print("default");
|
||||||
}
|
}
|
||||||
if (resolved_method->is_overpass()) {
|
if (sel_method->is_overpass()) {
|
||||||
tty->print("overpass");
|
tty->print("overpass");
|
||||||
}
|
}
|
||||||
tty->cr();
|
tty->cr();
|
||||||
|
|
|
@ -130,8 +130,7 @@ class LinkResolver: AllStatic {
|
||||||
static void lookup_polymorphic_method (methodHandle& result, KlassHandle klass, Symbol* name, Symbol* signature,
|
static void lookup_polymorphic_method (methodHandle& result, KlassHandle klass, Symbol* name, Symbol* signature,
|
||||||
KlassHandle current_klass, Handle *appendix_result_or_null, Handle *method_type_result, TRAPS);
|
KlassHandle current_klass, Handle *appendix_result_or_null, Handle *method_type_result, TRAPS);
|
||||||
|
|
||||||
static int vtable_index_of_miranda_method(KlassHandle klass, Symbol* name, Symbol* signature, TRAPS);
|
static int vtable_index_of_interface_method(KlassHandle klass, methodHandle resolved_method, TRAPS);
|
||||||
|
|
||||||
static void resolve_klass (KlassHandle& result, constantPoolHandle pool, int index, TRAPS);
|
static void resolve_klass (KlassHandle& result, constantPoolHandle pool, int index, TRAPS);
|
||||||
|
|
||||||
static void resolve_pool (KlassHandle& resolved_klass, Symbol*& method_name, Symbol*& method_signature, KlassHandle& current_klass, constantPoolHandle pool, int index, TRAPS);
|
static void resolve_pool (KlassHandle& resolved_klass, Symbol*& method_name, Symbol*& method_signature, KlassHandle& current_klass, constantPoolHandle pool, int index, TRAPS);
|
||||||
|
|
|
@ -47,85 +47,53 @@
|
||||||
|
|
||||||
// CollectorPolicy methods.
|
// CollectorPolicy methods.
|
||||||
|
|
||||||
// Align down. If the aligning result in 0, return 'alignment'.
|
|
||||||
static size_t restricted_align_down(size_t size, size_t alignment) {
|
|
||||||
return MAX2(alignment, align_size_down_(size, alignment));
|
|
||||||
}
|
|
||||||
|
|
||||||
void CollectorPolicy::initialize_flags() {
|
void CollectorPolicy::initialize_flags() {
|
||||||
assert(max_alignment() >= min_alignment(),
|
assert(_max_alignment >= _min_alignment,
|
||||||
err_msg("max_alignment: " SIZE_FORMAT " less than min_alignment: " SIZE_FORMAT,
|
err_msg("max_alignment: " SIZE_FORMAT " less than min_alignment: " SIZE_FORMAT,
|
||||||
max_alignment(), min_alignment()));
|
_max_alignment, _min_alignment));
|
||||||
assert(max_alignment() % min_alignment() == 0,
|
assert(_max_alignment % _min_alignment == 0,
|
||||||
err_msg("max_alignment: " SIZE_FORMAT " not aligned by min_alignment: " SIZE_FORMAT,
|
err_msg("max_alignment: " SIZE_FORMAT " not aligned by min_alignment: " SIZE_FORMAT,
|
||||||
max_alignment(), min_alignment()));
|
_max_alignment, _min_alignment));
|
||||||
|
|
||||||
if (MaxHeapSize < InitialHeapSize) {
|
if (MaxHeapSize < InitialHeapSize) {
|
||||||
vm_exit_during_initialization("Incompatible initial and maximum heap sizes specified");
|
vm_exit_during_initialization("Incompatible initial and maximum heap sizes specified");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Do not use FLAG_SET_ERGO to update MaxMetaspaceSize, since this will
|
MinHeapDeltaBytes = align_size_up(MinHeapDeltaBytes, _min_alignment);
|
||||||
// override if MaxMetaspaceSize was set on the command line or not.
|
|
||||||
// This information is needed later to conform to the specification of the
|
|
||||||
// java.lang.management.MemoryUsage API.
|
|
||||||
//
|
|
||||||
// Ideally, we would be able to set the default value of MaxMetaspaceSize in
|
|
||||||
// globals.hpp to the aligned value, but this is not possible, since the
|
|
||||||
// alignment depends on other flags being parsed.
|
|
||||||
MaxMetaspaceSize = restricted_align_down(MaxMetaspaceSize, max_alignment());
|
|
||||||
|
|
||||||
if (MetaspaceSize > MaxMetaspaceSize) {
|
|
||||||
MetaspaceSize = MaxMetaspaceSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
MetaspaceSize = restricted_align_down(MetaspaceSize, min_alignment());
|
|
||||||
|
|
||||||
assert(MetaspaceSize <= MaxMetaspaceSize, "Must be");
|
|
||||||
|
|
||||||
MinMetaspaceExpansion = restricted_align_down(MinMetaspaceExpansion, min_alignment());
|
|
||||||
MaxMetaspaceExpansion = restricted_align_down(MaxMetaspaceExpansion, min_alignment());
|
|
||||||
|
|
||||||
MinHeapDeltaBytes = align_size_up(MinHeapDeltaBytes, min_alignment());
|
|
||||||
|
|
||||||
assert(MetaspaceSize % min_alignment() == 0, "metapace alignment");
|
|
||||||
assert(MaxMetaspaceSize % max_alignment() == 0, "maximum metaspace alignment");
|
|
||||||
if (MetaspaceSize < 256*K) {
|
|
||||||
vm_exit_during_initialization("Too small initial Metaspace size");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CollectorPolicy::initialize_size_info() {
|
void CollectorPolicy::initialize_size_info() {
|
||||||
// User inputs from -mx and ms must be aligned
|
// User inputs from -mx and ms must be aligned
|
||||||
set_min_heap_byte_size(align_size_up(Arguments::min_heap_size(), min_alignment()));
|
_min_heap_byte_size = align_size_up(Arguments::min_heap_size(), _min_alignment);
|
||||||
set_initial_heap_byte_size(align_size_up(InitialHeapSize, min_alignment()));
|
_initial_heap_byte_size = align_size_up(InitialHeapSize, _min_alignment);
|
||||||
set_max_heap_byte_size(align_size_up(MaxHeapSize, max_alignment()));
|
_max_heap_byte_size = align_size_up(MaxHeapSize, _max_alignment);
|
||||||
|
|
||||||
// Check heap parameter properties
|
// Check heap parameter properties
|
||||||
if (initial_heap_byte_size() < M) {
|
if (_initial_heap_byte_size < M) {
|
||||||
vm_exit_during_initialization("Too small initial heap");
|
vm_exit_during_initialization("Too small initial heap");
|
||||||
}
|
}
|
||||||
// Check heap parameter properties
|
// Check heap parameter properties
|
||||||
if (min_heap_byte_size() < M) {
|
if (_min_heap_byte_size < M) {
|
||||||
vm_exit_during_initialization("Too small minimum heap");
|
vm_exit_during_initialization("Too small minimum heap");
|
||||||
}
|
}
|
||||||
if (initial_heap_byte_size() <= NewSize) {
|
if (_initial_heap_byte_size <= NewSize) {
|
||||||
// make sure there is at least some room in old space
|
// make sure there is at least some room in old space
|
||||||
vm_exit_during_initialization("Too small initial heap for new size specified");
|
vm_exit_during_initialization("Too small initial heap for new size specified");
|
||||||
}
|
}
|
||||||
if (max_heap_byte_size() < min_heap_byte_size()) {
|
if (_max_heap_byte_size < _min_heap_byte_size) {
|
||||||
vm_exit_during_initialization("Incompatible minimum and maximum heap sizes specified");
|
vm_exit_during_initialization("Incompatible minimum and maximum heap sizes specified");
|
||||||
}
|
}
|
||||||
if (initial_heap_byte_size() < min_heap_byte_size()) {
|
if (_initial_heap_byte_size < _min_heap_byte_size) {
|
||||||
vm_exit_during_initialization("Incompatible minimum and initial heap sizes specified");
|
vm_exit_during_initialization("Incompatible minimum and initial heap sizes specified");
|
||||||
}
|
}
|
||||||
if (max_heap_byte_size() < initial_heap_byte_size()) {
|
if (_max_heap_byte_size < _initial_heap_byte_size) {
|
||||||
vm_exit_during_initialization("Incompatible initial and maximum heap sizes specified");
|
vm_exit_during_initialization("Incompatible initial and maximum heap sizes specified");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (PrintGCDetails && Verbose) {
|
if (PrintGCDetails && Verbose) {
|
||||||
gclog_or_tty->print_cr("Minimum heap " SIZE_FORMAT " Initial heap "
|
gclog_or_tty->print_cr("Minimum heap " SIZE_FORMAT " Initial heap "
|
||||||
SIZE_FORMAT " Maximum heap " SIZE_FORMAT,
|
SIZE_FORMAT " Maximum heap " SIZE_FORMAT,
|
||||||
min_heap_byte_size(), initial_heap_byte_size(), max_heap_byte_size());
|
_min_heap_byte_size, _initial_heap_byte_size, _max_heap_byte_size);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -180,15 +148,15 @@ size_t CollectorPolicy::compute_max_alignment() {
|
||||||
|
|
||||||
size_t GenCollectorPolicy::scale_by_NewRatio_aligned(size_t base_size) {
|
size_t GenCollectorPolicy::scale_by_NewRatio_aligned(size_t base_size) {
|
||||||
size_t x = base_size / (NewRatio+1);
|
size_t x = base_size / (NewRatio+1);
|
||||||
size_t new_gen_size = x > min_alignment() ?
|
size_t new_gen_size = x > _min_alignment ?
|
||||||
align_size_down(x, min_alignment()) :
|
align_size_down(x, _min_alignment) :
|
||||||
min_alignment();
|
_min_alignment;
|
||||||
return new_gen_size;
|
return new_gen_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t GenCollectorPolicy::bound_minus_alignment(size_t desired_size,
|
size_t GenCollectorPolicy::bound_minus_alignment(size_t desired_size,
|
||||||
size_t maximum_size) {
|
size_t maximum_size) {
|
||||||
size_t alignment = min_alignment();
|
size_t alignment = _min_alignment;
|
||||||
size_t max_minus = maximum_size - alignment;
|
size_t max_minus = maximum_size - alignment;
|
||||||
return desired_size < max_minus ? desired_size : max_minus;
|
return desired_size < max_minus ? desired_size : max_minus;
|
||||||
}
|
}
|
||||||
|
@ -207,8 +175,8 @@ void GenCollectorPolicy::initialize_size_policy(size_t init_eden_size,
|
||||||
|
|
||||||
void GenCollectorPolicy::initialize_flags() {
|
void GenCollectorPolicy::initialize_flags() {
|
||||||
// All sizes must be multiples of the generation granularity.
|
// All sizes must be multiples of the generation granularity.
|
||||||
set_min_alignment((uintx) Generation::GenGrain);
|
_min_alignment = (uintx) Generation::GenGrain;
|
||||||
set_max_alignment(compute_max_alignment());
|
_max_alignment = compute_max_alignment();
|
||||||
|
|
||||||
CollectorPolicy::initialize_flags();
|
CollectorPolicy::initialize_flags();
|
||||||
|
|
||||||
|
@ -218,26 +186,26 @@ void GenCollectorPolicy::initialize_flags() {
|
||||||
if (NewSize > MaxNewSize) {
|
if (NewSize > MaxNewSize) {
|
||||||
MaxNewSize = NewSize;
|
MaxNewSize = NewSize;
|
||||||
}
|
}
|
||||||
NewSize = align_size_down(NewSize, min_alignment());
|
NewSize = align_size_down(NewSize, _min_alignment);
|
||||||
MaxNewSize = align_size_down(MaxNewSize, min_alignment());
|
MaxNewSize = align_size_down(MaxNewSize, _min_alignment);
|
||||||
|
|
||||||
// Check validity of heap flags
|
// Check validity of heap flags
|
||||||
assert(NewSize % min_alignment() == 0, "eden space alignment");
|
assert(NewSize % _min_alignment == 0, "eden space alignment");
|
||||||
assert(MaxNewSize % min_alignment() == 0, "survivor space alignment");
|
assert(MaxNewSize % _min_alignment == 0, "survivor space alignment");
|
||||||
|
|
||||||
if (NewSize < 3*min_alignment()) {
|
if (NewSize < 3 * _min_alignment) {
|
||||||
// make sure there room for eden and two survivor spaces
|
// make sure there room for eden and two survivor spaces
|
||||||
vm_exit_during_initialization("Too small new size specified");
|
vm_exit_during_initialization("Too small new size specified");
|
||||||
}
|
}
|
||||||
if (SurvivorRatio < 1 || NewRatio < 1) {
|
if (SurvivorRatio < 1 || NewRatio < 1) {
|
||||||
vm_exit_during_initialization("Invalid heap ratio specified");
|
vm_exit_during_initialization("Invalid young gen ratio specified");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TwoGenerationCollectorPolicy::initialize_flags() {
|
void TwoGenerationCollectorPolicy::initialize_flags() {
|
||||||
GenCollectorPolicy::initialize_flags();
|
GenCollectorPolicy::initialize_flags();
|
||||||
|
|
||||||
OldSize = align_size_down(OldSize, min_alignment());
|
OldSize = align_size_down(OldSize, _min_alignment);
|
||||||
|
|
||||||
if (FLAG_IS_CMDLINE(OldSize) && FLAG_IS_DEFAULT(NewSize)) {
|
if (FLAG_IS_CMDLINE(OldSize) && FLAG_IS_DEFAULT(NewSize)) {
|
||||||
// NewRatio will be used later to set the young generation size so we use
|
// NewRatio will be used later to set the young generation size so we use
|
||||||
|
@ -246,11 +214,11 @@ void TwoGenerationCollectorPolicy::initialize_flags() {
|
||||||
assert(NewRatio > 0, "NewRatio should have been set up earlier");
|
assert(NewRatio > 0, "NewRatio should have been set up earlier");
|
||||||
size_t calculated_heapsize = (OldSize / NewRatio) * (NewRatio + 1);
|
size_t calculated_heapsize = (OldSize / NewRatio) * (NewRatio + 1);
|
||||||
|
|
||||||
calculated_heapsize = align_size_up(calculated_heapsize, max_alignment());
|
calculated_heapsize = align_size_up(calculated_heapsize, _max_alignment);
|
||||||
MaxHeapSize = calculated_heapsize;
|
MaxHeapSize = calculated_heapsize;
|
||||||
InitialHeapSize = calculated_heapsize;
|
InitialHeapSize = calculated_heapsize;
|
||||||
}
|
}
|
||||||
MaxHeapSize = align_size_up(MaxHeapSize, max_alignment());
|
MaxHeapSize = align_size_up(MaxHeapSize, _max_alignment);
|
||||||
|
|
||||||
// adjust max heap size if necessary
|
// adjust max heap size if necessary
|
||||||
if (NewSize + OldSize > MaxHeapSize) {
|
if (NewSize + OldSize > MaxHeapSize) {
|
||||||
|
@ -260,18 +228,18 @@ void TwoGenerationCollectorPolicy::initialize_flags() {
|
||||||
uintx calculated_size = NewSize + OldSize;
|
uintx calculated_size = NewSize + OldSize;
|
||||||
double shrink_factor = (double) MaxHeapSize / calculated_size;
|
double shrink_factor = (double) MaxHeapSize / calculated_size;
|
||||||
// align
|
// align
|
||||||
NewSize = align_size_down((uintx) (NewSize * shrink_factor), min_alignment());
|
NewSize = align_size_down((uintx) (NewSize * shrink_factor), _min_alignment);
|
||||||
// OldSize is already aligned because above we aligned MaxHeapSize to
|
// OldSize is already aligned because above we aligned MaxHeapSize to
|
||||||
// max_alignment(), and we just made sure that NewSize is aligned to
|
// _max_alignment, and we just made sure that NewSize is aligned to
|
||||||
// min_alignment(). In initialize_flags() we verified that max_alignment()
|
// _min_alignment. In initialize_flags() we verified that _max_alignment
|
||||||
// is a multiple of min_alignment().
|
// is a multiple of _min_alignment.
|
||||||
OldSize = MaxHeapSize - NewSize;
|
OldSize = MaxHeapSize - NewSize;
|
||||||
} else {
|
} else {
|
||||||
MaxHeapSize = NewSize + OldSize;
|
MaxHeapSize = NewSize + OldSize;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// need to do this again
|
// need to do this again
|
||||||
MaxHeapSize = align_size_up(MaxHeapSize, max_alignment());
|
MaxHeapSize = align_size_up(MaxHeapSize, _max_alignment);
|
||||||
|
|
||||||
// adjust max heap size if necessary
|
// adjust max heap size if necessary
|
||||||
if (NewSize + OldSize > MaxHeapSize) {
|
if (NewSize + OldSize > MaxHeapSize) {
|
||||||
|
@ -281,24 +249,24 @@ void TwoGenerationCollectorPolicy::initialize_flags() {
|
||||||
uintx calculated_size = NewSize + OldSize;
|
uintx calculated_size = NewSize + OldSize;
|
||||||
double shrink_factor = (double) MaxHeapSize / calculated_size;
|
double shrink_factor = (double) MaxHeapSize / calculated_size;
|
||||||
// align
|
// align
|
||||||
NewSize = align_size_down((uintx) (NewSize * shrink_factor), min_alignment());
|
NewSize = align_size_down((uintx) (NewSize * shrink_factor), _min_alignment);
|
||||||
// OldSize is already aligned because above we aligned MaxHeapSize to
|
// OldSize is already aligned because above we aligned MaxHeapSize to
|
||||||
// max_alignment(), and we just made sure that NewSize is aligned to
|
// _max_alignment, and we just made sure that NewSize is aligned to
|
||||||
// min_alignment(). In initialize_flags() we verified that max_alignment()
|
// _min_alignment. In initialize_flags() we verified that _max_alignment
|
||||||
// is a multiple of min_alignment().
|
// is a multiple of _min_alignment.
|
||||||
OldSize = MaxHeapSize - NewSize;
|
OldSize = MaxHeapSize - NewSize;
|
||||||
} else {
|
} else {
|
||||||
MaxHeapSize = NewSize + OldSize;
|
MaxHeapSize = NewSize + OldSize;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// need to do this again
|
// need to do this again
|
||||||
MaxHeapSize = align_size_up(MaxHeapSize, max_alignment());
|
MaxHeapSize = align_size_up(MaxHeapSize, _max_alignment);
|
||||||
|
|
||||||
always_do_update_barrier = UseConcMarkSweepGC;
|
always_do_update_barrier = UseConcMarkSweepGC;
|
||||||
|
|
||||||
// Check validity of heap flags
|
// Check validity of heap flags
|
||||||
assert(OldSize % min_alignment() == 0, "old space alignment");
|
assert(OldSize % _min_alignment == 0, "old space alignment");
|
||||||
assert(MaxHeapSize % max_alignment() == 0, "maximum heap alignment");
|
assert(MaxHeapSize % _max_alignment == 0, "maximum heap alignment");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Values set on the command line win over any ergonomically
|
// Values set on the command line win over any ergonomically
|
||||||
|
@ -313,7 +281,7 @@ void TwoGenerationCollectorPolicy::initialize_flags() {
|
||||||
void GenCollectorPolicy::initialize_size_info() {
|
void GenCollectorPolicy::initialize_size_info() {
|
||||||
CollectorPolicy::initialize_size_info();
|
CollectorPolicy::initialize_size_info();
|
||||||
|
|
||||||
// min_alignment() is used for alignment within a generation.
|
// _min_alignment is used for alignment within a generation.
|
||||||
// There is additional alignment done down stream for some
|
// There is additional alignment done down stream for some
|
||||||
// collectors that sometimes causes unwanted rounding up of
|
// collectors that sometimes causes unwanted rounding up of
|
||||||
// generations sizes.
|
// generations sizes.
|
||||||
|
@ -322,18 +290,18 @@ void GenCollectorPolicy::initialize_size_info() {
|
||||||
|
|
||||||
size_t max_new_size = 0;
|
size_t max_new_size = 0;
|
||||||
if (FLAG_IS_CMDLINE(MaxNewSize) || FLAG_IS_ERGO(MaxNewSize)) {
|
if (FLAG_IS_CMDLINE(MaxNewSize) || FLAG_IS_ERGO(MaxNewSize)) {
|
||||||
if (MaxNewSize < min_alignment()) {
|
if (MaxNewSize < _min_alignment) {
|
||||||
max_new_size = min_alignment();
|
max_new_size = _min_alignment;
|
||||||
}
|
}
|
||||||
if (MaxNewSize >= max_heap_byte_size()) {
|
if (MaxNewSize >= _max_heap_byte_size) {
|
||||||
max_new_size = align_size_down(max_heap_byte_size() - min_alignment(),
|
max_new_size = align_size_down(_max_heap_byte_size - _min_alignment,
|
||||||
min_alignment());
|
_min_alignment);
|
||||||
warning("MaxNewSize (" SIZE_FORMAT "k) is equal to or "
|
warning("MaxNewSize (" SIZE_FORMAT "k) is equal to or "
|
||||||
"greater than the entire heap (" SIZE_FORMAT "k). A "
|
"greater than the entire heap (" SIZE_FORMAT "k). A "
|
||||||
"new generation size of " SIZE_FORMAT "k will be used.",
|
"new generation size of " SIZE_FORMAT "k will be used.",
|
||||||
MaxNewSize/K, max_heap_byte_size()/K, max_new_size/K);
|
MaxNewSize/K, _max_heap_byte_size/K, max_new_size/K);
|
||||||
} else {
|
} else {
|
||||||
max_new_size = align_size_down(MaxNewSize, min_alignment());
|
max_new_size = align_size_down(MaxNewSize, _min_alignment);
|
||||||
}
|
}
|
||||||
|
|
||||||
// The case for FLAG_IS_ERGO(MaxNewSize) could be treated
|
// The case for FLAG_IS_ERGO(MaxNewSize) could be treated
|
||||||
|
@ -351,7 +319,7 @@ void GenCollectorPolicy::initialize_size_info() {
|
||||||
// just accept those choices. The choices currently made are
|
// just accept those choices. The choices currently made are
|
||||||
// not always "wise".
|
// not always "wise".
|
||||||
} else {
|
} else {
|
||||||
max_new_size = scale_by_NewRatio_aligned(max_heap_byte_size());
|
max_new_size = scale_by_NewRatio_aligned(_max_heap_byte_size);
|
||||||
// Bound the maximum size by NewSize below (since it historically
|
// Bound the maximum size by NewSize below (since it historically
|
||||||
// would have been NewSize and because the NewRatio calculation could
|
// would have been NewSize and because the NewRatio calculation could
|
||||||
// yield a size that is too small) and bound it by MaxNewSize above.
|
// yield a size that is too small) and bound it by MaxNewSize above.
|
||||||
|
@ -364,13 +332,13 @@ void GenCollectorPolicy::initialize_size_info() {
|
||||||
// Given the maximum gen0 size, determine the initial and
|
// Given the maximum gen0 size, determine the initial and
|
||||||
// minimum gen0 sizes.
|
// minimum gen0 sizes.
|
||||||
|
|
||||||
if (max_heap_byte_size() == min_heap_byte_size()) {
|
if (_max_heap_byte_size == _min_heap_byte_size) {
|
||||||
// The maximum and minimum heap sizes are the same so
|
// The maximum and minimum heap sizes are the same so
|
||||||
// the generations minimum and initial must be the
|
// the generations minimum and initial must be the
|
||||||
// same as its maximum.
|
// same as its maximum.
|
||||||
set_min_gen0_size(max_new_size);
|
_min_gen0_size = max_new_size;
|
||||||
set_initial_gen0_size(max_new_size);
|
_initial_gen0_size = max_new_size;
|
||||||
set_max_gen0_size(max_new_size);
|
_max_gen0_size = max_new_size;
|
||||||
} else {
|
} else {
|
||||||
size_t desired_new_size = 0;
|
size_t desired_new_size = 0;
|
||||||
if (!FLAG_IS_DEFAULT(NewSize)) {
|
if (!FLAG_IS_DEFAULT(NewSize)) {
|
||||||
|
@ -391,43 +359,37 @@ void GenCollectorPolicy::initialize_size_info() {
|
||||||
// Use the default NewSize as the floor for these values. If
|
// Use the default NewSize as the floor for these values. If
|
||||||
// NewRatio is overly large, the resulting sizes can be too
|
// NewRatio is overly large, the resulting sizes can be too
|
||||||
// small.
|
// small.
|
||||||
_min_gen0_size = MAX2(scale_by_NewRatio_aligned(min_heap_byte_size()),
|
_min_gen0_size = MAX2(scale_by_NewRatio_aligned(_min_heap_byte_size), NewSize);
|
||||||
NewSize);
|
|
||||||
desired_new_size =
|
desired_new_size =
|
||||||
MAX2(scale_by_NewRatio_aligned(initial_heap_byte_size()),
|
MAX2(scale_by_NewRatio_aligned(_initial_heap_byte_size), NewSize);
|
||||||
NewSize);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(_min_gen0_size > 0, "Sanity check");
|
assert(_min_gen0_size > 0, "Sanity check");
|
||||||
set_initial_gen0_size(desired_new_size);
|
_initial_gen0_size = desired_new_size;
|
||||||
set_max_gen0_size(max_new_size);
|
_max_gen0_size = max_new_size;
|
||||||
|
|
||||||
// At this point the desirable initial and minimum sizes have been
|
// At this point the desirable initial and minimum sizes have been
|
||||||
// determined without regard to the maximum sizes.
|
// determined without regard to the maximum sizes.
|
||||||
|
|
||||||
// Bound the sizes by the corresponding overall heap sizes.
|
// Bound the sizes by the corresponding overall heap sizes.
|
||||||
set_min_gen0_size(
|
_min_gen0_size = bound_minus_alignment(_min_gen0_size, _min_heap_byte_size);
|
||||||
bound_minus_alignment(_min_gen0_size, min_heap_byte_size()));
|
_initial_gen0_size = bound_minus_alignment(_initial_gen0_size, _initial_heap_byte_size);
|
||||||
set_initial_gen0_size(
|
_max_gen0_size = bound_minus_alignment(_max_gen0_size, _max_heap_byte_size);
|
||||||
bound_minus_alignment(_initial_gen0_size, initial_heap_byte_size()));
|
|
||||||
set_max_gen0_size(
|
|
||||||
bound_minus_alignment(_max_gen0_size, max_heap_byte_size()));
|
|
||||||
|
|
||||||
// At this point all three sizes have been checked against the
|
// At this point all three sizes have been checked against the
|
||||||
// maximum sizes but have not been checked for consistency
|
// maximum sizes but have not been checked for consistency
|
||||||
// among the three.
|
// among the three.
|
||||||
|
|
||||||
// Final check min <= initial <= max
|
// Final check min <= initial <= max
|
||||||
set_min_gen0_size(MIN2(_min_gen0_size, _max_gen0_size));
|
_min_gen0_size = MIN2(_min_gen0_size, _max_gen0_size);
|
||||||
set_initial_gen0_size(
|
_initial_gen0_size = MAX2(MIN2(_initial_gen0_size, _max_gen0_size), _min_gen0_size);
|
||||||
MAX2(MIN2(_initial_gen0_size, _max_gen0_size), _min_gen0_size));
|
_min_gen0_size = MIN2(_min_gen0_size, _initial_gen0_size);
|
||||||
set_min_gen0_size(MIN2(_min_gen0_size, _initial_gen0_size));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (PrintGCDetails && Verbose) {
|
if (PrintGCDetails && Verbose) {
|
||||||
gclog_or_tty->print_cr("1: Minimum gen0 " SIZE_FORMAT " Initial gen0 "
|
gclog_or_tty->print_cr("1: Minimum gen0 " SIZE_FORMAT " Initial gen0 "
|
||||||
SIZE_FORMAT " Maximum gen0 " SIZE_FORMAT,
|
SIZE_FORMAT " Maximum gen0 " SIZE_FORMAT,
|
||||||
min_gen0_size(), initial_gen0_size(), max_gen0_size());
|
_min_gen0_size, _initial_gen0_size, _max_gen0_size);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -447,19 +409,17 @@ bool TwoGenerationCollectorPolicy::adjust_gen0_sizes(size_t* gen0_size_ptr,
|
||||||
|
|
||||||
if ((*gen1_size_ptr + *gen0_size_ptr) > heap_size) {
|
if ((*gen1_size_ptr + *gen0_size_ptr) > heap_size) {
|
||||||
if ((heap_size < (*gen0_size_ptr + min_gen1_size)) &&
|
if ((heap_size < (*gen0_size_ptr + min_gen1_size)) &&
|
||||||
(heap_size >= min_gen1_size + min_alignment())) {
|
(heap_size >= min_gen1_size + _min_alignment)) {
|
||||||
// Adjust gen0 down to accommodate min_gen1_size
|
// Adjust gen0 down to accommodate min_gen1_size
|
||||||
*gen0_size_ptr = heap_size - min_gen1_size;
|
*gen0_size_ptr = heap_size - min_gen1_size;
|
||||||
*gen0_size_ptr =
|
*gen0_size_ptr =
|
||||||
MAX2((uintx)align_size_down(*gen0_size_ptr, min_alignment()),
|
MAX2((uintx)align_size_down(*gen0_size_ptr, _min_alignment), _min_alignment);
|
||||||
min_alignment());
|
|
||||||
assert(*gen0_size_ptr > 0, "Min gen0 is too large");
|
assert(*gen0_size_ptr > 0, "Min gen0 is too large");
|
||||||
result = true;
|
result = true;
|
||||||
} else {
|
} else {
|
||||||
*gen1_size_ptr = heap_size - *gen0_size_ptr;
|
*gen1_size_ptr = heap_size - *gen0_size_ptr;
|
||||||
*gen1_size_ptr =
|
*gen1_size_ptr =
|
||||||
MAX2((uintx)align_size_down(*gen1_size_ptr, min_alignment()),
|
MAX2((uintx)align_size_down(*gen1_size_ptr, _min_alignment), _min_alignment);
|
||||||
min_alignment());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
|
@ -480,10 +440,9 @@ void TwoGenerationCollectorPolicy::initialize_size_info() {
|
||||||
// The maximum gen1 size can be determined from the maximum gen0
|
// The maximum gen1 size can be determined from the maximum gen0
|
||||||
// and maximum heap size since no explicit flags exits
|
// and maximum heap size since no explicit flags exits
|
||||||
// for setting the gen1 maximum.
|
// for setting the gen1 maximum.
|
||||||
_max_gen1_size = max_heap_byte_size() - _max_gen0_size;
|
_max_gen1_size = _max_heap_byte_size - _max_gen0_size;
|
||||||
_max_gen1_size =
|
_max_gen1_size =
|
||||||
MAX2((uintx)align_size_down(_max_gen1_size, min_alignment()),
|
MAX2((uintx)align_size_down(_max_gen1_size, _min_alignment), _min_alignment);
|
||||||
min_alignment());
|
|
||||||
// If no explicit command line flag has been set for the
|
// If no explicit command line flag has been set for the
|
||||||
// gen1 size, use what is left for gen1.
|
// gen1 size, use what is left for gen1.
|
||||||
if (FLAG_IS_DEFAULT(OldSize) || FLAG_IS_ERGO(OldSize)) {
|
if (FLAG_IS_DEFAULT(OldSize) || FLAG_IS_ERGO(OldSize)) {
|
||||||
|
@ -492,70 +451,66 @@ void TwoGenerationCollectorPolicy::initialize_size_info() {
|
||||||
// with the overall heap size). In either case make
|
// with the overall heap size). In either case make
|
||||||
// the minimum, maximum and initial sizes consistent
|
// the minimum, maximum and initial sizes consistent
|
||||||
// with the gen0 sizes and the overall heap sizes.
|
// with the gen0 sizes and the overall heap sizes.
|
||||||
assert(min_heap_byte_size() > _min_gen0_size,
|
assert(_min_heap_byte_size > _min_gen0_size,
|
||||||
"gen0 has an unexpected minimum size");
|
"gen0 has an unexpected minimum size");
|
||||||
set_min_gen1_size(min_heap_byte_size() - min_gen0_size());
|
_min_gen1_size = _min_heap_byte_size - _min_gen0_size;
|
||||||
set_min_gen1_size(
|
_min_gen1_size =
|
||||||
MAX2((uintx)align_size_down(_min_gen1_size, min_alignment()),
|
MAX2((uintx)align_size_down(_min_gen1_size, _min_alignment), _min_alignment);
|
||||||
min_alignment()));
|
_initial_gen1_size = _initial_heap_byte_size - _initial_gen0_size;
|
||||||
set_initial_gen1_size(initial_heap_byte_size() - initial_gen0_size());
|
_initial_gen1_size =
|
||||||
set_initial_gen1_size(
|
MAX2((uintx)align_size_down(_initial_gen1_size, _min_alignment), _min_alignment);
|
||||||
MAX2((uintx)align_size_down(_initial_gen1_size, min_alignment()),
|
|
||||||
min_alignment()));
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// It's been explicitly set on the command line. Use the
|
// It's been explicitly set on the command line. Use the
|
||||||
// OldSize and then determine the consequences.
|
// OldSize and then determine the consequences.
|
||||||
set_min_gen1_size(OldSize);
|
_min_gen1_size = OldSize;
|
||||||
set_initial_gen1_size(OldSize);
|
_initial_gen1_size = OldSize;
|
||||||
|
|
||||||
// If the user has explicitly set an OldSize that is inconsistent
|
// If the user has explicitly set an OldSize that is inconsistent
|
||||||
// with other command line flags, issue a warning.
|
// with other command line flags, issue a warning.
|
||||||
// The generation minimums and the overall heap mimimum should
|
// The generation minimums and the overall heap mimimum should
|
||||||
// be within one heap alignment.
|
// be within one heap alignment.
|
||||||
if ((_min_gen1_size + _min_gen0_size + min_alignment()) <
|
if ((_min_gen1_size + _min_gen0_size + _min_alignment) < _min_heap_byte_size) {
|
||||||
min_heap_byte_size()) {
|
|
||||||
warning("Inconsistency between minimum heap size and minimum "
|
warning("Inconsistency between minimum heap size and minimum "
|
||||||
"generation sizes: using minimum heap = " SIZE_FORMAT,
|
"generation sizes: using minimum heap = " SIZE_FORMAT,
|
||||||
min_heap_byte_size());
|
_min_heap_byte_size);
|
||||||
}
|
}
|
||||||
if ((OldSize > _max_gen1_size)) {
|
if ((OldSize > _max_gen1_size)) {
|
||||||
warning("Inconsistency between maximum heap size and maximum "
|
warning("Inconsistency between maximum heap size and maximum "
|
||||||
"generation sizes: using maximum heap = " SIZE_FORMAT
|
"generation sizes: using maximum heap = " SIZE_FORMAT
|
||||||
" -XX:OldSize flag is being ignored",
|
" -XX:OldSize flag is being ignored",
|
||||||
max_heap_byte_size());
|
_max_heap_byte_size);
|
||||||
}
|
}
|
||||||
// If there is an inconsistency between the OldSize and the minimum and/or
|
// If there is an inconsistency between the OldSize and the minimum and/or
|
||||||
// initial size of gen0, since OldSize was explicitly set, OldSize wins.
|
// initial size of gen0, since OldSize was explicitly set, OldSize wins.
|
||||||
if (adjust_gen0_sizes(&_min_gen0_size, &_min_gen1_size,
|
if (adjust_gen0_sizes(&_min_gen0_size, &_min_gen1_size,
|
||||||
min_heap_byte_size(), OldSize)) {
|
_min_heap_byte_size, OldSize)) {
|
||||||
if (PrintGCDetails && Verbose) {
|
if (PrintGCDetails && Verbose) {
|
||||||
gclog_or_tty->print_cr("2: Minimum gen0 " SIZE_FORMAT " Initial gen0 "
|
gclog_or_tty->print_cr("2: Minimum gen0 " SIZE_FORMAT " Initial gen0 "
|
||||||
SIZE_FORMAT " Maximum gen0 " SIZE_FORMAT,
|
SIZE_FORMAT " Maximum gen0 " SIZE_FORMAT,
|
||||||
min_gen0_size(), initial_gen0_size(), max_gen0_size());
|
_min_gen0_size, _initial_gen0_size, _max_gen0_size);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Initial size
|
// Initial size
|
||||||
if (adjust_gen0_sizes(&_initial_gen0_size, &_initial_gen1_size,
|
if (adjust_gen0_sizes(&_initial_gen0_size, &_initial_gen1_size,
|
||||||
initial_heap_byte_size(), OldSize)) {
|
_initial_heap_byte_size, OldSize)) {
|
||||||
if (PrintGCDetails && Verbose) {
|
if (PrintGCDetails && Verbose) {
|
||||||
gclog_or_tty->print_cr("3: Minimum gen0 " SIZE_FORMAT " Initial gen0 "
|
gclog_or_tty->print_cr("3: Minimum gen0 " SIZE_FORMAT " Initial gen0 "
|
||||||
SIZE_FORMAT " Maximum gen0 " SIZE_FORMAT,
|
SIZE_FORMAT " Maximum gen0 " SIZE_FORMAT,
|
||||||
min_gen0_size(), initial_gen0_size(), max_gen0_size());
|
_min_gen0_size, _initial_gen0_size, _max_gen0_size);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Enforce the maximum gen1 size.
|
// Enforce the maximum gen1 size.
|
||||||
set_min_gen1_size(MIN2(_min_gen1_size, _max_gen1_size));
|
_min_gen1_size = MIN2(_min_gen1_size, _max_gen1_size);
|
||||||
|
|
||||||
// Check that min gen1 <= initial gen1 <= max gen1
|
// Check that min gen1 <= initial gen1 <= max gen1
|
||||||
set_initial_gen1_size(MAX2(_initial_gen1_size, _min_gen1_size));
|
_initial_gen1_size = MAX2(_initial_gen1_size, _min_gen1_size);
|
||||||
set_initial_gen1_size(MIN2(_initial_gen1_size, _max_gen1_size));
|
_initial_gen1_size = MIN2(_initial_gen1_size, _max_gen1_size);
|
||||||
|
|
||||||
if (PrintGCDetails && Verbose) {
|
if (PrintGCDetails && Verbose) {
|
||||||
gclog_or_tty->print_cr("Minimum gen1 " SIZE_FORMAT " Initial gen1 "
|
gclog_or_tty->print_cr("Minimum gen1 " SIZE_FORMAT " Initial gen1 "
|
||||||
SIZE_FORMAT " Maximum gen1 " SIZE_FORMAT,
|
SIZE_FORMAT " Maximum gen1 " SIZE_FORMAT,
|
||||||
min_gen1_size(), initial_gen1_size(), max_gen1_size());
|
_min_gen1_size, _initial_gen1_size, _max_gen1_size);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -101,17 +101,12 @@ class CollectorPolicy : public CHeapObj<mtGC> {
|
||||||
// Return maximum heap alignment that may be imposed by the policy
|
// Return maximum heap alignment that may be imposed by the policy
|
||||||
static size_t compute_max_alignment();
|
static size_t compute_max_alignment();
|
||||||
|
|
||||||
void set_min_alignment(size_t align) { _min_alignment = align; }
|
|
||||||
size_t min_alignment() { return _min_alignment; }
|
size_t min_alignment() { return _min_alignment; }
|
||||||
void set_max_alignment(size_t align) { _max_alignment = align; }
|
|
||||||
size_t max_alignment() { return _max_alignment; }
|
size_t max_alignment() { return _max_alignment; }
|
||||||
|
|
||||||
size_t initial_heap_byte_size() { return _initial_heap_byte_size; }
|
size_t initial_heap_byte_size() { return _initial_heap_byte_size; }
|
||||||
void set_initial_heap_byte_size(size_t v) { _initial_heap_byte_size = v; }
|
|
||||||
size_t max_heap_byte_size() { return _max_heap_byte_size; }
|
size_t max_heap_byte_size() { return _max_heap_byte_size; }
|
||||||
void set_max_heap_byte_size(size_t v) { _max_heap_byte_size = v; }
|
|
||||||
size_t min_heap_byte_size() { return _min_heap_byte_size; }
|
size_t min_heap_byte_size() { return _min_heap_byte_size; }
|
||||||
void set_min_heap_byte_size(size_t v) { _min_heap_byte_size = v; }
|
|
||||||
|
|
||||||
enum Name {
|
enum Name {
|
||||||
CollectorPolicyKind,
|
CollectorPolicyKind,
|
||||||
|
@ -249,11 +244,8 @@ class GenCollectorPolicy : public CollectorPolicy {
|
||||||
public:
|
public:
|
||||||
// Accessors
|
// Accessors
|
||||||
size_t min_gen0_size() { return _min_gen0_size; }
|
size_t min_gen0_size() { return _min_gen0_size; }
|
||||||
void set_min_gen0_size(size_t v) { _min_gen0_size = v; }
|
|
||||||
size_t initial_gen0_size() { return _initial_gen0_size; }
|
size_t initial_gen0_size() { return _initial_gen0_size; }
|
||||||
void set_initial_gen0_size(size_t v) { _initial_gen0_size = v; }
|
|
||||||
size_t max_gen0_size() { return _max_gen0_size; }
|
size_t max_gen0_size() { return _max_gen0_size; }
|
||||||
void set_max_gen0_size(size_t v) { _max_gen0_size = v; }
|
|
||||||
|
|
||||||
virtual int number_of_generations() = 0;
|
virtual int number_of_generations() = 0;
|
||||||
|
|
||||||
|
@ -303,11 +295,8 @@ class TwoGenerationCollectorPolicy : public GenCollectorPolicy {
|
||||||
public:
|
public:
|
||||||
// Accessors
|
// Accessors
|
||||||
size_t min_gen1_size() { return _min_gen1_size; }
|
size_t min_gen1_size() { return _min_gen1_size; }
|
||||||
void set_min_gen1_size(size_t v) { _min_gen1_size = v; }
|
|
||||||
size_t initial_gen1_size() { return _initial_gen1_size; }
|
size_t initial_gen1_size() { return _initial_gen1_size; }
|
||||||
void set_initial_gen1_size(size_t v) { _initial_gen1_size = v; }
|
|
||||||
size_t max_gen1_size() { return _max_gen1_size; }
|
size_t max_gen1_size() { return _max_gen1_size; }
|
||||||
void set_max_gen1_size(size_t v) { _max_gen1_size = v; }
|
|
||||||
|
|
||||||
// Inherited methods
|
// Inherited methods
|
||||||
TwoGenerationCollectorPolicy* as_two_generation_policy() { return this; }
|
TwoGenerationCollectorPolicy* as_two_generation_policy() { return this; }
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
#define SHARE_VM_MEMORY_FILEMAP_HPP
|
#define SHARE_VM_MEMORY_FILEMAP_HPP
|
||||||
|
|
||||||
#include "memory/metaspaceShared.hpp"
|
#include "memory/metaspaceShared.hpp"
|
||||||
|
#include "memory/metaspace.hpp"
|
||||||
|
|
||||||
// Layout of the file:
|
// Layout of the file:
|
||||||
// header: dump of archive instance plus versioning info, datestamp, etc.
|
// header: dump of archive instance plus versioning info, datestamp, etc.
|
||||||
|
|
|
@ -73,6 +73,10 @@
|
||||||
"Number of bytes used by the InstanceKlass::methods() array") \
|
"Number of bytes used by the InstanceKlass::methods() array") \
|
||||||
f(method_ordering_bytes, IK_method_ordering, \
|
f(method_ordering_bytes, IK_method_ordering, \
|
||||||
"Number of bytes used by the InstanceKlass::method_ordering() array") \
|
"Number of bytes used by the InstanceKlass::method_ordering() array") \
|
||||||
|
f(default_methods_array_bytes, IK_default_methods, \
|
||||||
|
"Number of bytes used by the InstanceKlass::default_methods() array") \
|
||||||
|
f(default_vtable_indices_bytes, IK_default_vtable_indices, \
|
||||||
|
"Number of bytes used by the InstanceKlass::default_vtable_indices() array") \
|
||||||
f(local_interfaces_bytes, IK_local_interfaces, \
|
f(local_interfaces_bytes, IK_local_interfaces, \
|
||||||
"Number of bytes used by the InstanceKlass::local_interfaces() array") \
|
"Number of bytes used by the InstanceKlass::local_interfaces() array") \
|
||||||
f(transitive_interfaces_bytes, IK_transitive_interfaces, \
|
f(transitive_interfaces_bytes, IK_transitive_interfaces, \
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -87,9 +87,10 @@ class Metaspace : public CHeapObj<mtClass> {
|
||||||
friend class MetaspaceAux;
|
friend class MetaspaceAux;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
enum MetadataType {ClassType = 0,
|
enum MetadataType {
|
||||||
NonClassType = ClassType + 1,
|
ClassType,
|
||||||
MetadataTypeCount = ClassType + 2
|
NonClassType,
|
||||||
|
MetadataTypeCount
|
||||||
};
|
};
|
||||||
enum MetaspaceType {
|
enum MetaspaceType {
|
||||||
StandardMetaspaceType,
|
StandardMetaspaceType,
|
||||||
|
@ -103,6 +104,9 @@ class Metaspace : public CHeapObj<mtClass> {
|
||||||
private:
|
private:
|
||||||
void initialize(Mutex* lock, MetaspaceType type);
|
void initialize(Mutex* lock, MetaspaceType type);
|
||||||
|
|
||||||
|
// Get the first chunk for a Metaspace. Used for
|
||||||
|
// special cases such as the boot class loader, reflection
|
||||||
|
// class loader and anonymous class loader.
|
||||||
Metachunk* get_initialization_chunk(MetadataType mdtype,
|
Metachunk* get_initialization_chunk(MetadataType mdtype,
|
||||||
size_t chunk_word_size,
|
size_t chunk_word_size,
|
||||||
size_t chunk_bunch);
|
size_t chunk_bunch);
|
||||||
|
@ -123,6 +127,9 @@ class Metaspace : public CHeapObj<mtClass> {
|
||||||
static size_t _first_chunk_word_size;
|
static size_t _first_chunk_word_size;
|
||||||
static size_t _first_class_chunk_word_size;
|
static size_t _first_class_chunk_word_size;
|
||||||
|
|
||||||
|
static size_t _commit_alignment;
|
||||||
|
static size_t _reserve_alignment;
|
||||||
|
|
||||||
SpaceManager* _vsm;
|
SpaceManager* _vsm;
|
||||||
SpaceManager* vsm() const { return _vsm; }
|
SpaceManager* vsm() const { return _vsm; }
|
||||||
|
|
||||||
|
@ -191,12 +198,17 @@ class Metaspace : public CHeapObj<mtClass> {
|
||||||
Metaspace(Mutex* lock, MetaspaceType type);
|
Metaspace(Mutex* lock, MetaspaceType type);
|
||||||
~Metaspace();
|
~Metaspace();
|
||||||
|
|
||||||
// Initialize globals for Metaspace
|
static void ergo_initialize();
|
||||||
static void global_initialize();
|
static void global_initialize();
|
||||||
|
|
||||||
static size_t first_chunk_word_size() { return _first_chunk_word_size; }
|
static size_t first_chunk_word_size() { return _first_chunk_word_size; }
|
||||||
static size_t first_class_chunk_word_size() { return _first_class_chunk_word_size; }
|
static size_t first_class_chunk_word_size() { return _first_class_chunk_word_size; }
|
||||||
|
|
||||||
|
static size_t reserve_alignment() { return _reserve_alignment; }
|
||||||
|
static size_t reserve_alignment_words() { return _reserve_alignment / BytesPerWord; }
|
||||||
|
static size_t commit_alignment() { return _commit_alignment; }
|
||||||
|
static size_t commit_alignment_words() { return _commit_alignment / BytesPerWord; }
|
||||||
|
|
||||||
char* bottom() const;
|
char* bottom() const;
|
||||||
size_t used_words_slow(MetadataType mdtype) const;
|
size_t used_words_slow(MetadataType mdtype) const;
|
||||||
size_t free_words_slow(MetadataType mdtype) const;
|
size_t free_words_slow(MetadataType mdtype) const;
|
||||||
|
@ -219,6 +231,9 @@ class Metaspace : public CHeapObj<mtClass> {
|
||||||
static void purge(MetadataType mdtype);
|
static void purge(MetadataType mdtype);
|
||||||
static void purge();
|
static void purge();
|
||||||
|
|
||||||
|
static void report_metadata_oome(ClassLoaderData* loader_data, size_t word_size,
|
||||||
|
MetadataType mdtype, TRAPS);
|
||||||
|
|
||||||
void print_on(outputStream* st) const;
|
void print_on(outputStream* st) const;
|
||||||
// Debugging support
|
// Debugging support
|
||||||
void verify();
|
void verify();
|
||||||
|
@ -352,17 +367,10 @@ class MetaspaceAux : AllStatic {
|
||||||
|
|
||||||
class MetaspaceGC : AllStatic {
|
class MetaspaceGC : AllStatic {
|
||||||
|
|
||||||
// The current high-water-mark for inducing a GC. When
|
// The current high-water-mark for inducing a GC.
|
||||||
// the capacity of all space in the virtual lists reaches this value,
|
// When committed memory of all metaspaces reaches this value,
|
||||||
// a GC is induced and the value is increased. This should be changed
|
// a GC is induced and the value is increased. Size is in bytes.
|
||||||
// to the space actually used for allocations to avoid affects of
|
static volatile intptr_t _capacity_until_GC;
|
||||||
// fragmentation losses to partially used chunks. Size is in words.
|
|
||||||
static size_t _capacity_until_GC;
|
|
||||||
|
|
||||||
// After a GC is done any allocation that fails should try to expand
|
|
||||||
// the capacity of the Metaspaces. This flag is set during attempts
|
|
||||||
// to allocate in the VMGCOperation that does the GC.
|
|
||||||
static bool _expand_after_GC;
|
|
||||||
|
|
||||||
// For a CMS collection, signal that a concurrent collection should
|
// For a CMS collection, signal that a concurrent collection should
|
||||||
// be started.
|
// be started.
|
||||||
|
@ -370,20 +378,16 @@ class MetaspaceGC : AllStatic {
|
||||||
|
|
||||||
static uint _shrink_factor;
|
static uint _shrink_factor;
|
||||||
|
|
||||||
static void set_capacity_until_GC(size_t v) { _capacity_until_GC = v; }
|
|
||||||
|
|
||||||
static size_t shrink_factor() { return _shrink_factor; }
|
static size_t shrink_factor() { return _shrink_factor; }
|
||||||
void set_shrink_factor(uint v) { _shrink_factor = v; }
|
void set_shrink_factor(uint v) { _shrink_factor = v; }
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
static size_t capacity_until_GC() { return _capacity_until_GC; }
|
static void initialize() { _capacity_until_GC = MetaspaceSize; }
|
||||||
static void inc_capacity_until_GC(size_t v) { _capacity_until_GC += v; }
|
|
||||||
static void dec_capacity_until_GC(size_t v) {
|
static size_t capacity_until_GC();
|
||||||
_capacity_until_GC = _capacity_until_GC > v ? _capacity_until_GC - v : 0;
|
static size_t inc_capacity_until_GC(size_t v);
|
||||||
}
|
static size_t dec_capacity_until_GC(size_t v);
|
||||||
static bool expand_after_GC() { return _expand_after_GC; }
|
|
||||||
static void set_expand_after_GC(bool v) { _expand_after_GC = v; }
|
|
||||||
|
|
||||||
static bool should_concurrent_collect() { return _should_concurrent_collect; }
|
static bool should_concurrent_collect() { return _should_concurrent_collect; }
|
||||||
static void set_should_concurrent_collect(bool v) {
|
static void set_should_concurrent_collect(bool v) {
|
||||||
|
@ -391,11 +395,14 @@ class MetaspaceGC : AllStatic {
|
||||||
}
|
}
|
||||||
|
|
||||||
// The amount to increase the high-water-mark (_capacity_until_GC)
|
// The amount to increase the high-water-mark (_capacity_until_GC)
|
||||||
static size_t delta_capacity_until_GC(size_t word_size);
|
static size_t delta_capacity_until_GC(size_t bytes);
|
||||||
|
|
||||||
// It is expected that this will be called when the current capacity
|
// Tells if we have can expand metaspace without hitting set limits.
|
||||||
// has been used and a GC should be considered.
|
static bool can_expand(size_t words, bool is_class);
|
||||||
static bool should_expand(VirtualSpaceList* vsl, size_t word_size);
|
|
||||||
|
// Returns amount that we can expand without hitting a GC,
|
||||||
|
// measured in words.
|
||||||
|
static size_t allowed_expansion();
|
||||||
|
|
||||||
// Calculate the new high-water mark at which to induce
|
// Calculate the new high-water mark at which to induce
|
||||||
// a GC.
|
// a GC.
|
||||||
|
|
|
@ -238,6 +238,13 @@ void InstanceKlass::copy_method_ordering(intArray* m, TRAPS) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// create a new array of vtable_indices for default methods
|
||||||
|
Array<int>* InstanceKlass::create_new_default_vtable_indices(int len, TRAPS) {
|
||||||
|
Array<int>* vtable_indices = MetadataFactory::new_array<int>(class_loader_data(), len, CHECK_NULL);
|
||||||
|
assert(default_vtable_indices() == NULL, "only create once");
|
||||||
|
set_default_vtable_indices(vtable_indices);
|
||||||
|
return vtable_indices;
|
||||||
|
}
|
||||||
|
|
||||||
InstanceKlass::InstanceKlass(int vtable_len,
|
InstanceKlass::InstanceKlass(int vtable_len,
|
||||||
int itable_len,
|
int itable_len,
|
||||||
|
@ -263,6 +270,8 @@ InstanceKlass::InstanceKlass(int vtable_len,
|
||||||
set_array_klasses(NULL);
|
set_array_klasses(NULL);
|
||||||
set_methods(NULL);
|
set_methods(NULL);
|
||||||
set_method_ordering(NULL);
|
set_method_ordering(NULL);
|
||||||
|
set_default_methods(NULL);
|
||||||
|
set_default_vtable_indices(NULL);
|
||||||
set_local_interfaces(NULL);
|
set_local_interfaces(NULL);
|
||||||
set_transitive_interfaces(NULL);
|
set_transitive_interfaces(NULL);
|
||||||
init_implementor();
|
init_implementor();
|
||||||
|
@ -376,6 +385,21 @@ void InstanceKlass::deallocate_contents(ClassLoaderData* loader_data) {
|
||||||
}
|
}
|
||||||
set_method_ordering(NULL);
|
set_method_ordering(NULL);
|
||||||
|
|
||||||
|
// default methods can be empty
|
||||||
|
if (default_methods() != NULL &&
|
||||||
|
default_methods() != Universe::the_empty_method_array()) {
|
||||||
|
MetadataFactory::free_array<Method*>(loader_data, default_methods());
|
||||||
|
}
|
||||||
|
// Do NOT deallocate the default methods, they are owned by superinterfaces.
|
||||||
|
set_default_methods(NULL);
|
||||||
|
|
||||||
|
// default methods vtable indices can be empty
|
||||||
|
if (default_vtable_indices() != NULL) {
|
||||||
|
MetadataFactory::free_array<int>(loader_data, default_vtable_indices());
|
||||||
|
}
|
||||||
|
set_default_vtable_indices(NULL);
|
||||||
|
|
||||||
|
|
||||||
// This array is in Klass, but remove it with the InstanceKlass since
|
// This array is in Klass, but remove it with the InstanceKlass since
|
||||||
// this place would be the only caller and it can share memory with transitive
|
// this place would be the only caller and it can share memory with transitive
|
||||||
// interfaces.
|
// interfaces.
|
||||||
|
@ -456,14 +480,14 @@ objArrayOop InstanceKlass::signers() const {
|
||||||
return java_lang_Class::signers(java_mirror());
|
return java_lang_Class::signers(java_mirror());
|
||||||
}
|
}
|
||||||
|
|
||||||
volatile oop InstanceKlass::init_lock() const {
|
oop InstanceKlass::init_lock() const {
|
||||||
// return the init lock from the mirror
|
// return the init lock from the mirror
|
||||||
return java_lang_Class::init_lock(java_mirror());
|
return java_lang_Class::init_lock(java_mirror());
|
||||||
}
|
}
|
||||||
|
|
||||||
void InstanceKlass::eager_initialize_impl(instanceKlassHandle this_oop) {
|
void InstanceKlass::eager_initialize_impl(instanceKlassHandle this_oop) {
|
||||||
EXCEPTION_MARK;
|
EXCEPTION_MARK;
|
||||||
volatile oop init_lock = this_oop->init_lock();
|
oop init_lock = this_oop->init_lock();
|
||||||
ObjectLocker ol(init_lock, THREAD);
|
ObjectLocker ol(init_lock, THREAD);
|
||||||
|
|
||||||
// abort if someone beat us to the initialization
|
// abort if someone beat us to the initialization
|
||||||
|
@ -608,7 +632,7 @@ bool InstanceKlass::link_class_impl(
|
||||||
|
|
||||||
// verification & rewriting
|
// verification & rewriting
|
||||||
{
|
{
|
||||||
volatile oop init_lock = this_oop->init_lock();
|
oop init_lock = this_oop->init_lock();
|
||||||
ObjectLocker ol(init_lock, THREAD);
|
ObjectLocker ol(init_lock, THREAD);
|
||||||
// rewritten will have been set if loader constraint error found
|
// rewritten will have been set if loader constraint error found
|
||||||
// on an earlier link attempt
|
// on an earlier link attempt
|
||||||
|
@ -731,7 +755,7 @@ void InstanceKlass::initialize_impl(instanceKlassHandle this_oop, TRAPS) {
|
||||||
// refer to the JVM book page 47 for description of steps
|
// refer to the JVM book page 47 for description of steps
|
||||||
// Step 1
|
// Step 1
|
||||||
{
|
{
|
||||||
volatile oop init_lock = this_oop->init_lock();
|
oop init_lock = this_oop->init_lock();
|
||||||
ObjectLocker ol(init_lock, THREAD);
|
ObjectLocker ol(init_lock, THREAD);
|
||||||
|
|
||||||
Thread *self = THREAD; // it's passed the current thread
|
Thread *self = THREAD; // it's passed the current thread
|
||||||
|
@ -879,7 +903,7 @@ void InstanceKlass::set_initialization_state_and_notify(ClassState state, TRAPS)
|
||||||
}
|
}
|
||||||
|
|
||||||
void InstanceKlass::set_initialization_state_and_notify_impl(instanceKlassHandle this_oop, ClassState state, TRAPS) {
|
void InstanceKlass::set_initialization_state_and_notify_impl(instanceKlassHandle this_oop, ClassState state, TRAPS) {
|
||||||
volatile oop init_lock = this_oop->init_lock();
|
oop init_lock = this_oop->init_lock();
|
||||||
ObjectLocker ol(init_lock, THREAD);
|
ObjectLocker ol(init_lock, THREAD);
|
||||||
this_oop->set_init_state(state);
|
this_oop->set_init_state(state);
|
||||||
ol.notify_all(CHECK);
|
ol.notify_all(CHECK);
|
||||||
|
@ -1354,32 +1378,44 @@ static int binary_search(Array<Method*>* methods, Symbol* name) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// find_method looks up the name/signature in the local methods array
|
||||||
Method* InstanceKlass::find_method(Symbol* name, Symbol* signature) const {
|
Method* InstanceKlass::find_method(Symbol* name, Symbol* signature) const {
|
||||||
return InstanceKlass::find_method(methods(), name, signature);
|
return InstanceKlass::find_method(methods(), name, signature);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// find_method looks up the name/signature in the local methods array
|
||||||
Method* InstanceKlass::find_method(
|
Method* InstanceKlass::find_method(
|
||||||
Array<Method*>* methods, Symbol* name, Symbol* signature) {
|
Array<Method*>* methods, Symbol* name, Symbol* signature) {
|
||||||
|
int hit = find_method_index(methods, name, signature);
|
||||||
|
return hit >= 0 ? methods->at(hit): NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Used directly for default_methods to find the index into the
|
||||||
|
// default_vtable_indices, and indirectly by find_method
|
||||||
|
// find_method_index looks in the local methods array to return the index
|
||||||
|
// of the matching name/signature
|
||||||
|
int InstanceKlass::find_method_index(
|
||||||
|
Array<Method*>* methods, Symbol* name, Symbol* signature) {
|
||||||
int hit = binary_search(methods, name);
|
int hit = binary_search(methods, name);
|
||||||
if (hit != -1) {
|
if (hit != -1) {
|
||||||
Method* m = methods->at(hit);
|
Method* m = methods->at(hit);
|
||||||
// Do linear search to find matching signature. First, quick check
|
// Do linear search to find matching signature. First, quick check
|
||||||
// for common case
|
// for common case
|
||||||
if (m->signature() == signature) return m;
|
if (m->signature() == signature) return hit;
|
||||||
// search downwards through overloaded methods
|
// search downwards through overloaded methods
|
||||||
int i;
|
int i;
|
||||||
for (i = hit - 1; i >= 0; --i) {
|
for (i = hit - 1; i >= 0; --i) {
|
||||||
Method* m = methods->at(i);
|
Method* m = methods->at(i);
|
||||||
assert(m->is_method(), "must be method");
|
assert(m->is_method(), "must be method");
|
||||||
if (m->name() != name) break;
|
if (m->name() != name) break;
|
||||||
if (m->signature() == signature) return m;
|
if (m->signature() == signature) return i;
|
||||||
}
|
}
|
||||||
// search upwards
|
// search upwards
|
||||||
for (i = hit + 1; i < methods->length(); ++i) {
|
for (i = hit + 1; i < methods->length(); ++i) {
|
||||||
Method* m = methods->at(i);
|
Method* m = methods->at(i);
|
||||||
assert(m->is_method(), "must be method");
|
assert(m->is_method(), "must be method");
|
||||||
if (m->name() != name) break;
|
if (m->name() != name) break;
|
||||||
if (m->signature() == signature) return m;
|
if (m->signature() == signature) return i;
|
||||||
}
|
}
|
||||||
// not found
|
// not found
|
||||||
#ifdef ASSERT
|
#ifdef ASSERT
|
||||||
|
@ -1387,9 +1423,8 @@ Method* InstanceKlass::find_method(
|
||||||
assert(index == -1, err_msg("binary search should have found entry %d", index));
|
assert(index == -1, err_msg("binary search should have found entry %d", index));
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
return NULL;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int InstanceKlass::find_method_by_name(Symbol* name, int* end) {
|
int InstanceKlass::find_method_by_name(Symbol* name, int* end) {
|
||||||
return find_method_by_name(methods(), name, end);
|
return find_method_by_name(methods(), name, end);
|
||||||
}
|
}
|
||||||
|
@ -1408,6 +1443,7 @@ int InstanceKlass::find_method_by_name(
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// lookup_method searches both the local methods array and all superclasses methods arrays
|
||||||
Method* InstanceKlass::uncached_lookup_method(Symbol* name, Symbol* signature) const {
|
Method* InstanceKlass::uncached_lookup_method(Symbol* name, Symbol* signature) const {
|
||||||
Klass* klass = const_cast<InstanceKlass*>(this);
|
Klass* klass = const_cast<InstanceKlass*>(this);
|
||||||
while (klass != NULL) {
|
while (klass != NULL) {
|
||||||
|
@ -1418,6 +1454,21 @@ Method* InstanceKlass::uncached_lookup_method(Symbol* name, Symbol* signature) c
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// lookup a method in the default methods list then in all transitive interfaces
|
||||||
|
// Do NOT return private or static methods
|
||||||
|
Method* InstanceKlass::lookup_method_in_ordered_interfaces(Symbol* name,
|
||||||
|
Symbol* signature) const {
|
||||||
|
Method* m = NULL;
|
||||||
|
if (default_methods() != NULL) {
|
||||||
|
m = find_method(default_methods(), name, signature);
|
||||||
|
}
|
||||||
|
// Look up interfaces
|
||||||
|
if (m == NULL) {
|
||||||
|
m = lookup_method_in_all_interfaces(name, signature);
|
||||||
|
}
|
||||||
|
return m;
|
||||||
|
}
|
||||||
|
|
||||||
// lookup a method in all the interfaces that this class implements
|
// lookup a method in all the interfaces that this class implements
|
||||||
// Do NOT return private or static methods, new in JDK8 which are not externally visible
|
// Do NOT return private or static methods, new in JDK8 which are not externally visible
|
||||||
// They should only be found in the initial InterfaceMethodRef
|
// They should only be found in the initial InterfaceMethodRef
|
||||||
|
@ -2548,6 +2599,42 @@ Method* InstanceKlass::method_at_itable(Klass* holder, int index, TRAPS) {
|
||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#if INCLUDE_JVMTI
|
||||||
|
// update default_methods for redefineclasses for methods that are
|
||||||
|
// not yet in the vtable due to concurrent subclass define and superinterface
|
||||||
|
// redefinition
|
||||||
|
// Note: those in the vtable, should have been updated via adjust_method_entries
|
||||||
|
void InstanceKlass::adjust_default_methods(Method** old_methods, Method** new_methods,
|
||||||
|
int methods_length, bool* trace_name_printed) {
|
||||||
|
// search the default_methods for uses of either obsolete or EMCP methods
|
||||||
|
if (default_methods() != NULL) {
|
||||||
|
for (int j = 0; j < methods_length; j++) {
|
||||||
|
Method* old_method = old_methods[j];
|
||||||
|
Method* new_method = new_methods[j];
|
||||||
|
|
||||||
|
for (int index = 0; index < default_methods()->length(); index ++) {
|
||||||
|
if (default_methods()->at(index) == old_method) {
|
||||||
|
default_methods()->at_put(index, new_method);
|
||||||
|
if (RC_TRACE_IN_RANGE(0x00100000, 0x00400000)) {
|
||||||
|
if (!(*trace_name_printed)) {
|
||||||
|
// RC_TRACE_MESG macro has an embedded ResourceMark
|
||||||
|
RC_TRACE_MESG(("adjust: klassname=%s default methods from name=%s",
|
||||||
|
external_name(),
|
||||||
|
old_method->method_holder()->external_name()));
|
||||||
|
*trace_name_printed = true;
|
||||||
|
}
|
||||||
|
RC_TRACE(0x00100000, ("default method update: %s(%s) ",
|
||||||
|
new_method->name()->as_C_string(),
|
||||||
|
new_method->signature()->as_C_string()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif // INCLUDE_JVMTI
|
||||||
|
|
||||||
// On-stack replacement stuff
|
// On-stack replacement stuff
|
||||||
void InstanceKlass::add_osr_nmethod(nmethod* n) {
|
void InstanceKlass::add_osr_nmethod(nmethod* n) {
|
||||||
// only one compilation can be active
|
// only one compilation can be active
|
||||||
|
@ -2747,6 +2834,16 @@ void InstanceKlass::print_on(outputStream* st) const {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
st->print(BULLET"method ordering: "); method_ordering()->print_value_on(st); st->cr();
|
st->print(BULLET"method ordering: "); method_ordering()->print_value_on(st); st->cr();
|
||||||
|
st->print(BULLET"default_methods: "); default_methods()->print_value_on(st); st->cr();
|
||||||
|
if (Verbose && default_methods() != NULL) {
|
||||||
|
Array<Method*>* method_array = default_methods();
|
||||||
|
for (int i = 0; i < method_array->length(); i++) {
|
||||||
|
st->print("%d : ", i); method_array->at(i)->print_value(); st->cr();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (default_vtable_indices() != NULL) {
|
||||||
|
st->print(BULLET"default vtable indices: "); default_vtable_indices()->print_value_on(st); st->cr();
|
||||||
|
}
|
||||||
st->print(BULLET"local interfaces: "); local_interfaces()->print_value_on(st); st->cr();
|
st->print(BULLET"local interfaces: "); local_interfaces()->print_value_on(st); st->cr();
|
||||||
st->print(BULLET"trans. interfaces: "); transitive_interfaces()->print_value_on(st); st->cr();
|
st->print(BULLET"trans. interfaces: "); transitive_interfaces()->print_value_on(st); st->cr();
|
||||||
st->print(BULLET"constants: "); constants()->print_value_on(st); st->cr();
|
st->print(BULLET"constants: "); constants()->print_value_on(st); st->cr();
|
||||||
|
@ -3099,6 +3196,19 @@ void InstanceKlass::verify_on(outputStream* st, bool check_dictionary) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Verify default methods
|
||||||
|
if (default_methods() != NULL) {
|
||||||
|
Array<Method*>* methods = this->default_methods();
|
||||||
|
for (int j = 0; j < methods->length(); j++) {
|
||||||
|
guarantee(methods->at(j)->is_method(), "non-method in methods array");
|
||||||
|
}
|
||||||
|
for (int j = 0; j < methods->length() - 1; j++) {
|
||||||
|
Method* m1 = methods->at(j);
|
||||||
|
Method* m2 = methods->at(j + 1);
|
||||||
|
guarantee(m1->name()->fast_compare(m2->name()) <= 0, "methods not sorted correctly");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Verify JNI static field identifiers
|
// Verify JNI static field identifiers
|
||||||
if (jni_ids() != NULL) {
|
if (jni_ids() != NULL) {
|
||||||
jni_ids()->verify(this);
|
jni_ids()->verify(this);
|
||||||
|
|
|
@ -269,12 +269,18 @@ class InstanceKlass: public Klass {
|
||||||
|
|
||||||
// Method array.
|
// Method array.
|
||||||
Array<Method*>* _methods;
|
Array<Method*>* _methods;
|
||||||
|
// Default Method Array, concrete methods inherited from interfaces
|
||||||
|
Array<Method*>* _default_methods;
|
||||||
// Interface (Klass*s) this class declares locally to implement.
|
// Interface (Klass*s) this class declares locally to implement.
|
||||||
Array<Klass*>* _local_interfaces;
|
Array<Klass*>* _local_interfaces;
|
||||||
// Interface (Klass*s) this class implements transitively.
|
// Interface (Klass*s) this class implements transitively.
|
||||||
Array<Klass*>* _transitive_interfaces;
|
Array<Klass*>* _transitive_interfaces;
|
||||||
// Int array containing the original order of method in the class file (for JVMTI).
|
// Int array containing the original order of method in the class file (for JVMTI).
|
||||||
Array<int>* _method_ordering;
|
Array<int>* _method_ordering;
|
||||||
|
// Int array containing the vtable_indices for default_methods
|
||||||
|
// offset matches _default_methods offset
|
||||||
|
Array<int>* _default_vtable_indices;
|
||||||
|
|
||||||
// Instance and static variable information, starts with 6-tuples of shorts
|
// Instance and static variable information, starts with 6-tuples of shorts
|
||||||
// [access, name index, sig index, initval index, low_offset, high_offset]
|
// [access, name index, sig index, initval index, low_offset, high_offset]
|
||||||
// for all fields, followed by the generic signature data at the end of
|
// for all fields, followed by the generic signature data at the end of
|
||||||
|
@ -356,6 +362,15 @@ class InstanceKlass: public Klass {
|
||||||
void set_method_ordering(Array<int>* m) { _method_ordering = m; }
|
void set_method_ordering(Array<int>* m) { _method_ordering = m; }
|
||||||
void copy_method_ordering(intArray* m, TRAPS);
|
void copy_method_ordering(intArray* m, TRAPS);
|
||||||
|
|
||||||
|
// default_methods
|
||||||
|
Array<Method*>* default_methods() const { return _default_methods; }
|
||||||
|
void set_default_methods(Array<Method*>* a) { _default_methods = a; }
|
||||||
|
|
||||||
|
// default method vtable_indices
|
||||||
|
Array<int>* default_vtable_indices() const { return _default_vtable_indices; }
|
||||||
|
void set_default_vtable_indices(Array<int>* v) { _default_vtable_indices = v; }
|
||||||
|
Array<int>* create_new_default_vtable_indices(int len, TRAPS);
|
||||||
|
|
||||||
// interfaces
|
// interfaces
|
||||||
Array<Klass*>* local_interfaces() const { return _local_interfaces; }
|
Array<Klass*>* local_interfaces() const { return _local_interfaces; }
|
||||||
void set_local_interfaces(Array<Klass*>* a) {
|
void set_local_interfaces(Array<Klass*>* a) {
|
||||||
|
@ -501,12 +516,18 @@ class InstanceKlass: public Klass {
|
||||||
Method* find_method(Symbol* name, Symbol* signature) const;
|
Method* find_method(Symbol* name, Symbol* signature) const;
|
||||||
static Method* find_method(Array<Method*>* methods, Symbol* name, Symbol* signature);
|
static Method* find_method(Array<Method*>* methods, Symbol* name, Symbol* signature);
|
||||||
|
|
||||||
|
// find a local method index in default_methods (returns -1 if not found)
|
||||||
|
static int find_method_index(Array<Method*>* methods, Symbol* name, Symbol* signature);
|
||||||
|
|
||||||
// lookup operation (returns NULL if not found)
|
// lookup operation (returns NULL if not found)
|
||||||
Method* uncached_lookup_method(Symbol* name, Symbol* signature) const;
|
Method* uncached_lookup_method(Symbol* name, Symbol* signature) const;
|
||||||
|
|
||||||
// lookup a method in all the interfaces that this class implements
|
// lookup a method in all the interfaces that this class implements
|
||||||
// (returns NULL if not found)
|
// (returns NULL if not found)
|
||||||
Method* lookup_method_in_all_interfaces(Symbol* name, Symbol* signature) const;
|
Method* lookup_method_in_all_interfaces(Symbol* name, Symbol* signature) const;
|
||||||
|
// lookup a method in local defaults then in all interfaces
|
||||||
|
// (returns NULL if not found)
|
||||||
|
Method* lookup_method_in_ordered_interfaces(Symbol* name, Symbol* signature) const;
|
||||||
|
|
||||||
// Find method indices by name. If a method with the specified name is
|
// Find method indices by name. If a method with the specified name is
|
||||||
// found the index to the first method is returned, and 'end' is filled in
|
// found the index to the first method is returned, and 'end' is filled in
|
||||||
|
@ -910,6 +931,11 @@ class InstanceKlass: public Klass {
|
||||||
klassItable* itable() const; // return new klassItable wrapper
|
klassItable* itable() const; // return new klassItable wrapper
|
||||||
Method* method_at_itable(Klass* holder, int index, TRAPS);
|
Method* method_at_itable(Klass* holder, int index, TRAPS);
|
||||||
|
|
||||||
|
#if INCLUDE_JVMTI
|
||||||
|
void adjust_default_methods(Method** old_methods, Method** new_methods,
|
||||||
|
int methods_length, bool* trace_name_printed);
|
||||||
|
#endif // INCLUDE_JVMTI
|
||||||
|
|
||||||
// Garbage collection
|
// Garbage collection
|
||||||
void oop_follow_contents(oop obj);
|
void oop_follow_contents(oop obj);
|
||||||
int oop_adjust_pointers(oop obj);
|
int oop_adjust_pointers(oop obj);
|
||||||
|
@ -995,7 +1021,7 @@ public:
|
||||||
// Must be one per class and it has to be a VM internal object so java code
|
// Must be one per class and it has to be a VM internal object so java code
|
||||||
// cannot lock it (like the mirror).
|
// cannot lock it (like the mirror).
|
||||||
// It has to be an object not a Mutex because it's held through java calls.
|
// It has to be an object not a Mutex because it's held through java calls.
|
||||||
volatile oop init_lock() const;
|
oop init_lock() const;
|
||||||
private:
|
private:
|
||||||
|
|
||||||
// Static methods that are used to implement member methods where an exposed this pointer
|
// Static methods that are used to implement member methods where an exposed this pointer
|
||||||
|
|
|
@ -83,7 +83,7 @@ void klassVtable::compute_vtable_size_and_num_mirandas(
|
||||||
|
|
||||||
GrowableArray<Method*> new_mirandas(20);
|
GrowableArray<Method*> new_mirandas(20);
|
||||||
// compute the number of mirandas methods that must be added to the end
|
// compute the number of mirandas methods that must be added to the end
|
||||||
get_mirandas(&new_mirandas, all_mirandas, super, methods, local_interfaces);
|
get_mirandas(&new_mirandas, all_mirandas, super, methods, NULL, local_interfaces);
|
||||||
*num_new_mirandas = new_mirandas.length();
|
*num_new_mirandas = new_mirandas.length();
|
||||||
|
|
||||||
vtable_length += *num_new_mirandas * vtableEntry::size();
|
vtable_length += *num_new_mirandas * vtableEntry::size();
|
||||||
|
@ -186,7 +186,7 @@ void klassVtable::initialize_vtable(bool checkconstraints, TRAPS) {
|
||||||
assert(methods->at(i)->is_method(), "must be a Method*");
|
assert(methods->at(i)->is_method(), "must be a Method*");
|
||||||
methodHandle mh(THREAD, methods->at(i));
|
methodHandle mh(THREAD, methods->at(i));
|
||||||
|
|
||||||
bool needs_new_entry = update_inherited_vtable(ik(), mh, super_vtable_len, checkconstraints, CHECK);
|
bool needs_new_entry = update_inherited_vtable(ik(), mh, super_vtable_len, -1, checkconstraints, CHECK);
|
||||||
|
|
||||||
if (needs_new_entry) {
|
if (needs_new_entry) {
|
||||||
put_method_at(mh(), initialized);
|
put_method_at(mh(), initialized);
|
||||||
|
@ -195,7 +195,35 @@ void klassVtable::initialize_vtable(bool checkconstraints, TRAPS) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// add miranda methods to end of vtable.
|
// update vtable with default_methods
|
||||||
|
Array<Method*>* default_methods = ik()->default_methods();
|
||||||
|
if (default_methods != NULL) {
|
||||||
|
len = default_methods->length();
|
||||||
|
if (len > 0) {
|
||||||
|
Array<int>* def_vtable_indices = NULL;
|
||||||
|
if ((def_vtable_indices = ik()->default_vtable_indices()) == NULL) {
|
||||||
|
def_vtable_indices = ik()->create_new_default_vtable_indices(len, CHECK);
|
||||||
|
} else {
|
||||||
|
assert(def_vtable_indices->length() == len, "reinit vtable len?");
|
||||||
|
}
|
||||||
|
for (int i = 0; i < len; i++) {
|
||||||
|
HandleMark hm(THREAD);
|
||||||
|
assert(default_methods->at(i)->is_method(), "must be a Method*");
|
||||||
|
methodHandle mh(THREAD, default_methods->at(i));
|
||||||
|
|
||||||
|
bool needs_new_entry = update_inherited_vtable(ik(), mh, super_vtable_len, i, checkconstraints, CHECK);
|
||||||
|
|
||||||
|
// needs new entry
|
||||||
|
if (needs_new_entry) {
|
||||||
|
put_method_at(mh(), initialized);
|
||||||
|
def_vtable_indices->at_put(i, initialized); //set vtable index
|
||||||
|
initialized++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// add miranda methods; it will also return the updated initialized
|
||||||
initialized = fill_in_mirandas(initialized);
|
initialized = fill_in_mirandas(initialized);
|
||||||
|
|
||||||
// In class hierarchies where the accessibility is not increasing (i.e., going from private ->
|
// In class hierarchies where the accessibility is not increasing (i.e., going from private ->
|
||||||
|
@ -230,14 +258,19 @@ InstanceKlass* klassVtable::find_transitive_override(InstanceKlass* initialsuper
|
||||||
#ifndef PRODUCT
|
#ifndef PRODUCT
|
||||||
if (PrintVtables && Verbose) {
|
if (PrintVtables && Verbose) {
|
||||||
ResourceMark rm(THREAD);
|
ResourceMark rm(THREAD);
|
||||||
|
char* sig = target_method()->name_and_sig_as_C_string();
|
||||||
tty->print("transitive overriding superclass %s with %s::%s index %d, original flags: ",
|
tty->print("transitive overriding superclass %s with %s::%s index %d, original flags: ",
|
||||||
supersuperklass->internal_name(),
|
supersuperklass->internal_name(),
|
||||||
_klass->internal_name(), (target_method() != NULL) ?
|
_klass->internal_name(), sig, vtable_index);
|
||||||
target_method()->name()->as_C_string() : "<NULL>", vtable_index);
|
|
||||||
super_method->access_flags().print_on(tty);
|
super_method->access_flags().print_on(tty);
|
||||||
|
if (super_method->is_default_method()) {
|
||||||
|
tty->print("default");
|
||||||
|
}
|
||||||
tty->print("overriders flags: ");
|
tty->print("overriders flags: ");
|
||||||
target_method->access_flags().print_on(tty);
|
target_method->access_flags().print_on(tty);
|
||||||
tty->cr();
|
if (target_method->is_default_method()) {
|
||||||
|
tty->print("default");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif /*PRODUCT*/
|
#endif /*PRODUCT*/
|
||||||
break; // return found superk
|
break; // return found superk
|
||||||
|
@ -258,16 +291,31 @@ InstanceKlass* klassVtable::find_transitive_override(InstanceKlass* initialsuper
|
||||||
// OR return true if a new vtable entry is required.
|
// OR return true if a new vtable entry is required.
|
||||||
// Only called for InstanceKlass's, i.e. not for arrays
|
// Only called for InstanceKlass's, i.e. not for arrays
|
||||||
// If that changed, could not use _klass as handle for klass
|
// If that changed, could not use _klass as handle for klass
|
||||||
bool klassVtable::update_inherited_vtable(InstanceKlass* klass, methodHandle target_method, int super_vtable_len,
|
bool klassVtable::update_inherited_vtable(InstanceKlass* klass, methodHandle target_method,
|
||||||
|
int super_vtable_len, int default_index,
|
||||||
bool checkconstraints, TRAPS) {
|
bool checkconstraints, TRAPS) {
|
||||||
ResourceMark rm;
|
ResourceMark rm;
|
||||||
bool allocate_new = true;
|
bool allocate_new = true;
|
||||||
assert(klass->oop_is_instance(), "must be InstanceKlass");
|
assert(klass->oop_is_instance(), "must be InstanceKlass");
|
||||||
assert(klass == target_method()->method_holder(), "caller resp.");
|
|
||||||
|
|
||||||
|
Array<int>* def_vtable_indices = NULL;
|
||||||
|
bool is_default = false;
|
||||||
|
// default methods are concrete methods in superinterfaces which are added to the vtable
|
||||||
|
// with their real method_holder
|
||||||
|
// Since vtable and itable indices share the same storage, don't touch
|
||||||
|
// the default method's real vtable/itable index
|
||||||
|
// default_vtable_indices stores the vtable value relative to this inheritor
|
||||||
|
if (default_index >= 0 ) {
|
||||||
|
is_default = true;
|
||||||
|
def_vtable_indices = klass->default_vtable_indices();
|
||||||
|
assert(def_vtable_indices != NULL, "def vtable alloc?");
|
||||||
|
assert(default_index <= def_vtable_indices->length(), "def vtable len?");
|
||||||
|
} else {
|
||||||
|
assert(klass == target_method()->method_holder(), "caller resp.");
|
||||||
// Initialize the method's vtable index to "nonvirtual".
|
// Initialize the method's vtable index to "nonvirtual".
|
||||||
// If we allocate a vtable entry, we will update it to a non-negative number.
|
// If we allocate a vtable entry, we will update it to a non-negative number.
|
||||||
target_method()->set_vtable_index(Method::nonvirtual_vtable_index);
|
target_method()->set_vtable_index(Method::nonvirtual_vtable_index);
|
||||||
|
}
|
||||||
|
|
||||||
// Static and <init> methods are never in
|
// Static and <init> methods are never in
|
||||||
if (target_method()->is_static() || target_method()->name() == vmSymbols::object_initializer_name()) {
|
if (target_method()->is_static() || target_method()->name() == vmSymbols::object_initializer_name()) {
|
||||||
|
@ -284,6 +332,8 @@ bool klassVtable::update_inherited_vtable(InstanceKlass* klass, methodHandle tar
|
||||||
// An interface never allocates new vtable slots, only inherits old ones.
|
// An interface never allocates new vtable slots, only inherits old ones.
|
||||||
// This method will either be assigned its own itable index later,
|
// This method will either be assigned its own itable index later,
|
||||||
// or be assigned an inherited vtable index in the loop below.
|
// or be assigned an inherited vtable index in the loop below.
|
||||||
|
// default methods store their vtable indices in the inheritors default_vtable_indices
|
||||||
|
assert (default_index == -1, "interfaces don't store resolved default methods");
|
||||||
target_method()->set_vtable_index(Method::pending_itable_index);
|
target_method()->set_vtable_index(Method::pending_itable_index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -307,8 +357,15 @@ bool klassVtable::update_inherited_vtable(InstanceKlass* klass, methodHandle tar
|
||||||
|
|
||||||
Symbol* name = target_method()->name();
|
Symbol* name = target_method()->name();
|
||||||
Symbol* signature = target_method()->signature();
|
Symbol* signature = target_method()->signature();
|
||||||
Handle target_loader(THREAD, _klass()->class_loader());
|
|
||||||
Symbol* target_classname = _klass->name();
|
KlassHandle target_klass(THREAD, target_method()->method_holder());
|
||||||
|
if (target_klass == NULL) {
|
||||||
|
target_klass = _klass;
|
||||||
|
}
|
||||||
|
|
||||||
|
Handle target_loader(THREAD, target_klass->class_loader());
|
||||||
|
|
||||||
|
Symbol* target_classname = target_klass->name();
|
||||||
for(int i = 0; i < super_vtable_len; i++) {
|
for(int i = 0; i < super_vtable_len; i++) {
|
||||||
Method* super_method = method_at(i);
|
Method* super_method = method_at(i);
|
||||||
// Check if method name matches
|
// Check if method name matches
|
||||||
|
@ -317,10 +374,14 @@ bool klassVtable::update_inherited_vtable(InstanceKlass* klass, methodHandle tar
|
||||||
// get super_klass for method_holder for the found method
|
// get super_klass for method_holder for the found method
|
||||||
InstanceKlass* super_klass = super_method->method_holder();
|
InstanceKlass* super_klass = super_method->method_holder();
|
||||||
|
|
||||||
if ((super_klass->is_override(super_method, target_loader, target_classname, THREAD)) ||
|
if (is_default
|
||||||
((klass->major_version() >= VTABLE_TRANSITIVE_OVERRIDE_VERSION)
|
|| ((super_klass->is_override(super_method, target_loader, target_classname, THREAD))
|
||||||
&& ((super_klass = find_transitive_override(super_klass, target_method, i, target_loader,
|
|| ((klass->major_version() >= VTABLE_TRANSITIVE_OVERRIDE_VERSION)
|
||||||
target_classname, THREAD)) != (InstanceKlass*)NULL))) {
|
&& ((super_klass = find_transitive_override(super_klass,
|
||||||
|
target_method, i, target_loader,
|
||||||
|
target_classname, THREAD))
|
||||||
|
!= (InstanceKlass*)NULL))))
|
||||||
|
{
|
||||||
// overriding, so no new entry
|
// overriding, so no new entry
|
||||||
allocate_new = false;
|
allocate_new = false;
|
||||||
|
|
||||||
|
@ -347,7 +408,7 @@ bool klassVtable::update_inherited_vtable(InstanceKlass* klass, methodHandle tar
|
||||||
"%s used in the signature";
|
"%s used in the signature";
|
||||||
char* sig = target_method()->name_and_sig_as_C_string();
|
char* sig = target_method()->name_and_sig_as_C_string();
|
||||||
const char* loader1 = SystemDictionary::loader_name(target_loader());
|
const char* loader1 = SystemDictionary::loader_name(target_loader());
|
||||||
char* current = _klass->name()->as_C_string();
|
char* current = target_klass->name()->as_C_string();
|
||||||
const char* loader2 = SystemDictionary::loader_name(super_loader());
|
const char* loader2 = SystemDictionary::loader_name(super_loader());
|
||||||
char* failed_type_name = failed_type_symbol->as_C_string();
|
char* failed_type_name = failed_type_symbol->as_C_string();
|
||||||
size_t buflen = strlen(msg) + strlen(sig) + strlen(loader1) +
|
size_t buflen = strlen(msg) + strlen(sig) + strlen(loader1) +
|
||||||
|
@ -361,15 +422,38 @@ bool klassVtable::update_inherited_vtable(InstanceKlass* klass, methodHandle tar
|
||||||
}
|
}
|
||||||
|
|
||||||
put_method_at(target_method(), i);
|
put_method_at(target_method(), i);
|
||||||
|
if (!is_default) {
|
||||||
target_method()->set_vtable_index(i);
|
target_method()->set_vtable_index(i);
|
||||||
|
} else {
|
||||||
|
if (def_vtable_indices != NULL) {
|
||||||
|
def_vtable_indices->at_put(default_index, i);
|
||||||
|
}
|
||||||
|
assert(super_method->is_default_method() || super_method->is_overpass()
|
||||||
|
|| super_method->is_abstract(), "default override error");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifndef PRODUCT
|
#ifndef PRODUCT
|
||||||
if (PrintVtables && Verbose) {
|
if (PrintVtables && Verbose) {
|
||||||
|
ResourceMark rm(THREAD);
|
||||||
|
char* sig = target_method()->name_and_sig_as_C_string();
|
||||||
tty->print("overriding with %s::%s index %d, original flags: ",
|
tty->print("overriding with %s::%s index %d, original flags: ",
|
||||||
_klass->internal_name(), (target_method() != NULL) ?
|
target_klass->internal_name(), sig, i);
|
||||||
target_method()->name()->as_C_string() : "<NULL>", i);
|
|
||||||
super_method->access_flags().print_on(tty);
|
super_method->access_flags().print_on(tty);
|
||||||
|
if (super_method->is_default_method()) {
|
||||||
|
tty->print("default");
|
||||||
|
}
|
||||||
|
if (super_method->is_overpass()) {
|
||||||
|
tty->print("overpass");
|
||||||
|
}
|
||||||
tty->print("overriders flags: ");
|
tty->print("overriders flags: ");
|
||||||
target_method->access_flags().print_on(tty);
|
target_method->access_flags().print_on(tty);
|
||||||
|
if (target_method->is_default_method()) {
|
||||||
|
tty->print("default");
|
||||||
|
}
|
||||||
|
if (target_method->is_overpass()) {
|
||||||
|
tty->print("overpass");
|
||||||
|
}
|
||||||
tty->cr();
|
tty->cr();
|
||||||
}
|
}
|
||||||
#endif /*PRODUCT*/
|
#endif /*PRODUCT*/
|
||||||
|
@ -378,12 +462,25 @@ bool klassVtable::update_inherited_vtable(InstanceKlass* klass, methodHandle tar
|
||||||
// but not override another. Once we override one, not need new
|
// but not override another. Once we override one, not need new
|
||||||
#ifndef PRODUCT
|
#ifndef PRODUCT
|
||||||
if (PrintVtables && Verbose) {
|
if (PrintVtables && Verbose) {
|
||||||
|
ResourceMark rm(THREAD);
|
||||||
|
char* sig = target_method()->name_and_sig_as_C_string();
|
||||||
tty->print("NOT overriding with %s::%s index %d, original flags: ",
|
tty->print("NOT overriding with %s::%s index %d, original flags: ",
|
||||||
_klass->internal_name(), (target_method() != NULL) ?
|
target_klass->internal_name(), sig,i);
|
||||||
target_method()->name()->as_C_string() : "<NULL>", i);
|
|
||||||
super_method->access_flags().print_on(tty);
|
super_method->access_flags().print_on(tty);
|
||||||
|
if (super_method->is_default_method()) {
|
||||||
|
tty->print("default");
|
||||||
|
}
|
||||||
|
if (super_method->is_overpass()) {
|
||||||
|
tty->print("overpass");
|
||||||
|
}
|
||||||
tty->print("overriders flags: ");
|
tty->print("overriders flags: ");
|
||||||
target_method->access_flags().print_on(tty);
|
target_method->access_flags().print_on(tty);
|
||||||
|
if (target_method->is_default_method()) {
|
||||||
|
tty->print("default");
|
||||||
|
}
|
||||||
|
if (target_method->is_overpass()) {
|
||||||
|
tty->print("overpass");
|
||||||
|
}
|
||||||
tty->cr();
|
tty->cr();
|
||||||
}
|
}
|
||||||
#endif /*PRODUCT*/
|
#endif /*PRODUCT*/
|
||||||
|
@ -438,6 +535,14 @@ bool klassVtable::needs_new_vtable_entry(methodHandle target_method,
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Concrete interface methods do not need new entries, they override
|
||||||
|
// abstract method entries using default inheritance rules
|
||||||
|
if (target_method()->method_holder() != NULL &&
|
||||||
|
target_method()->method_holder()->is_interface() &&
|
||||||
|
!target_method()->is_abstract() ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// we need a new entry if there is no superclass
|
// we need a new entry if there is no superclass
|
||||||
if (super == NULL) {
|
if (super == NULL) {
|
||||||
return true;
|
return true;
|
||||||
|
@ -526,26 +631,30 @@ bool klassVtable::is_miranda_entry_at(int i) {
|
||||||
if (mhk->is_interface()) {
|
if (mhk->is_interface()) {
|
||||||
assert(m->is_public(), "should be public");
|
assert(m->is_public(), "should be public");
|
||||||
assert(ik()->implements_interface(method_holder) , "this class should implement the interface");
|
assert(ik()->implements_interface(method_holder) , "this class should implement the interface");
|
||||||
assert(is_miranda(m, ik()->methods(), ik()->super()), "should be a miranda_method");
|
assert(is_miranda(m, ik()->methods(), ik()->default_methods(), ik()->super()), "should be a miranda_method");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// check if a method is a miranda method, given a class's methods table and its super
|
// check if a method is a miranda method, given a class's methods table,
|
||||||
// "miranda" means not static, not defined by this class, and not defined
|
// its default_method table and its super
|
||||||
// in super unless it is private and therefore inaccessible to this class.
|
// "miranda" means not static, not defined by this class.
|
||||||
|
// private methods in interfaces do not belong in the miranda list.
|
||||||
// the caller must make sure that the method belongs to an interface implemented by the class
|
// the caller must make sure that the method belongs to an interface implemented by the class
|
||||||
// Miranda methods only include public interface instance methods
|
// Miranda methods only include public interface instance methods
|
||||||
// Not private methods, not static methods, not default = concrete abstract
|
// Not private methods, not static methods, not default == concrete abstract
|
||||||
bool klassVtable::is_miranda(Method* m, Array<Method*>* class_methods, Klass* super) {
|
bool klassVtable::is_miranda(Method* m, Array<Method*>* class_methods,
|
||||||
if (m->is_static()) {
|
Array<Method*>* default_methods, Klass* super) {
|
||||||
|
if (m->is_static() || m->is_private()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
Symbol* name = m->name();
|
Symbol* name = m->name();
|
||||||
Symbol* signature = m->signature();
|
Symbol* signature = m->signature();
|
||||||
if (InstanceKlass::find_method(class_methods, name, signature) == NULL) {
|
if (InstanceKlass::find_method(class_methods, name, signature) == NULL) {
|
||||||
// did not find it in the method table of the current class
|
// did not find it in the method table of the current class
|
||||||
|
if ((default_methods == NULL) ||
|
||||||
|
InstanceKlass::find_method(default_methods, name, signature) == NULL) {
|
||||||
if (super == NULL) {
|
if (super == NULL) {
|
||||||
// super doesn't exist
|
// super doesn't exist
|
||||||
return true;
|
return true;
|
||||||
|
@ -557,12 +666,13 @@ bool klassVtable::is_miranda(Method* m, Array<Method*>* class_methods, Klass* su
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Scans current_interface_methods for miranda methods that do not
|
// Scans current_interface_methods for miranda methods that do not
|
||||||
// already appear in new_mirandas and are also not defined-and-non-private
|
// already appear in new_mirandas, or default methods, and are also not defined-and-non-private
|
||||||
// in super (superclass). These mirandas are added to all_mirandas if it is
|
// in super (superclass). These mirandas are added to all_mirandas if it is
|
||||||
// not null; in addition, those that are not duplicates of miranda methods
|
// not null; in addition, those that are not duplicates of miranda methods
|
||||||
// inherited by super from its interfaces are added to new_mirandas.
|
// inherited by super from its interfaces are added to new_mirandas.
|
||||||
|
@ -572,7 +682,8 @@ bool klassVtable::is_miranda(Method* m, Array<Method*>* class_methods, Klass* su
|
||||||
void klassVtable::add_new_mirandas_to_lists(
|
void klassVtable::add_new_mirandas_to_lists(
|
||||||
GrowableArray<Method*>* new_mirandas, GrowableArray<Method*>* all_mirandas,
|
GrowableArray<Method*>* new_mirandas, GrowableArray<Method*>* all_mirandas,
|
||||||
Array<Method*>* current_interface_methods, Array<Method*>* class_methods,
|
Array<Method*>* current_interface_methods, Array<Method*>* class_methods,
|
||||||
Klass* super) {
|
Array<Method*>* default_methods, Klass* super) {
|
||||||
|
|
||||||
// iterate thru the current interface's method to see if it a miranda
|
// iterate thru the current interface's method to see if it a miranda
|
||||||
int num_methods = current_interface_methods->length();
|
int num_methods = current_interface_methods->length();
|
||||||
for (int i = 0; i < num_methods; i++) {
|
for (int i = 0; i < num_methods; i++) {
|
||||||
|
@ -590,7 +701,7 @@ void klassVtable::add_new_mirandas_to_lists(
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!is_duplicate) { // we don't want duplicate miranda entries in the vtable
|
if (!is_duplicate) { // we don't want duplicate miranda entries in the vtable
|
||||||
if (is_miranda(im, class_methods, super)) { // is it a miranda at all?
|
if (is_miranda(im, class_methods, default_methods, super)) { // is it a miranda at all?
|
||||||
InstanceKlass *sk = InstanceKlass::cast(super);
|
InstanceKlass *sk = InstanceKlass::cast(super);
|
||||||
// check if it is a duplicate of a super's miranda
|
// check if it is a duplicate of a super's miranda
|
||||||
if (sk->lookup_method_in_all_interfaces(im->name(), im->signature()) == NULL) {
|
if (sk->lookup_method_in_all_interfaces(im->name(), im->signature()) == NULL) {
|
||||||
|
@ -607,6 +718,7 @@ void klassVtable::add_new_mirandas_to_lists(
|
||||||
void klassVtable::get_mirandas(GrowableArray<Method*>* new_mirandas,
|
void klassVtable::get_mirandas(GrowableArray<Method*>* new_mirandas,
|
||||||
GrowableArray<Method*>* all_mirandas,
|
GrowableArray<Method*>* all_mirandas,
|
||||||
Klass* super, Array<Method*>* class_methods,
|
Klass* super, Array<Method*>* class_methods,
|
||||||
|
Array<Method*>* default_methods,
|
||||||
Array<Klass*>* local_interfaces) {
|
Array<Klass*>* local_interfaces) {
|
||||||
assert((new_mirandas->length() == 0) , "current mirandas must be 0");
|
assert((new_mirandas->length() == 0) , "current mirandas must be 0");
|
||||||
|
|
||||||
|
@ -615,14 +727,16 @@ void klassVtable::get_mirandas(GrowableArray<Method*>* new_mirandas,
|
||||||
for (int i = 0; i < num_local_ifs; i++) {
|
for (int i = 0; i < num_local_ifs; i++) {
|
||||||
InstanceKlass *ik = InstanceKlass::cast(local_interfaces->at(i));
|
InstanceKlass *ik = InstanceKlass::cast(local_interfaces->at(i));
|
||||||
add_new_mirandas_to_lists(new_mirandas, all_mirandas,
|
add_new_mirandas_to_lists(new_mirandas, all_mirandas,
|
||||||
ik->methods(), class_methods, super);
|
ik->methods(), class_methods,
|
||||||
|
default_methods, super);
|
||||||
// iterate thru each local's super interfaces
|
// iterate thru each local's super interfaces
|
||||||
Array<Klass*>* super_ifs = ik->transitive_interfaces();
|
Array<Klass*>* super_ifs = ik->transitive_interfaces();
|
||||||
int num_super_ifs = super_ifs->length();
|
int num_super_ifs = super_ifs->length();
|
||||||
for (int j = 0; j < num_super_ifs; j++) {
|
for (int j = 0; j < num_super_ifs; j++) {
|
||||||
InstanceKlass *sik = InstanceKlass::cast(super_ifs->at(j));
|
InstanceKlass *sik = InstanceKlass::cast(super_ifs->at(j));
|
||||||
add_new_mirandas_to_lists(new_mirandas, all_mirandas,
|
add_new_mirandas_to_lists(new_mirandas, all_mirandas,
|
||||||
sik->methods(), class_methods, super);
|
sik->methods(), class_methods,
|
||||||
|
default_methods, super);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -633,8 +747,22 @@ void klassVtable::get_mirandas(GrowableArray<Method*>* new_mirandas,
|
||||||
int klassVtable::fill_in_mirandas(int initialized) {
|
int klassVtable::fill_in_mirandas(int initialized) {
|
||||||
GrowableArray<Method*> mirandas(20);
|
GrowableArray<Method*> mirandas(20);
|
||||||
get_mirandas(&mirandas, NULL, ik()->super(), ik()->methods(),
|
get_mirandas(&mirandas, NULL, ik()->super(), ik()->methods(),
|
||||||
ik()->local_interfaces());
|
ik()->default_methods(), ik()->local_interfaces());
|
||||||
for (int i = 0; i < mirandas.length(); i++) {
|
for (int i = 0; i < mirandas.length(); i++) {
|
||||||
|
if (PrintVtables && Verbose) {
|
||||||
|
Method* meth = mirandas.at(i);
|
||||||
|
ResourceMark rm(Thread::current());
|
||||||
|
if (meth != NULL) {
|
||||||
|
char* sig = meth->name_and_sig_as_C_string();
|
||||||
|
tty->print("fill in mirandas with %s index %d, flags: ",
|
||||||
|
sig, initialized);
|
||||||
|
meth->access_flags().print_on(tty);
|
||||||
|
if (meth->is_default_method()) {
|
||||||
|
tty->print("default");
|
||||||
|
}
|
||||||
|
tty->cr();
|
||||||
|
}
|
||||||
|
}
|
||||||
put_method_at(mirandas.at(i), initialized);
|
put_method_at(mirandas.at(i), initialized);
|
||||||
++initialized;
|
++initialized;
|
||||||
}
|
}
|
||||||
|
@ -648,6 +776,26 @@ void klassVtable::copy_vtable_to(vtableEntry* start) {
|
||||||
}
|
}
|
||||||
|
|
||||||
#if INCLUDE_JVMTI
|
#if INCLUDE_JVMTI
|
||||||
|
bool klassVtable::adjust_default_method(int vtable_index, Method* old_method, Method* new_method) {
|
||||||
|
// If old_method is default, find this vtable index in default_vtable_indices
|
||||||
|
// and replace that method in the _default_methods list
|
||||||
|
bool updated = false;
|
||||||
|
|
||||||
|
Array<Method*>* default_methods = ik()->default_methods();
|
||||||
|
if (default_methods != NULL) {
|
||||||
|
int len = default_methods->length();
|
||||||
|
for (int idx = 0; idx < len; idx++) {
|
||||||
|
if (vtable_index == ik()->default_vtable_indices()->at(idx)) {
|
||||||
|
if (default_methods->at(idx) == old_method) {
|
||||||
|
default_methods->at_put(idx, new_method);
|
||||||
|
updated = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return updated;
|
||||||
|
}
|
||||||
void klassVtable::adjust_method_entries(Method** old_methods, Method** new_methods,
|
void klassVtable::adjust_method_entries(Method** old_methods, Method** new_methods,
|
||||||
int methods_length, bool * trace_name_printed) {
|
int methods_length, bool * trace_name_printed) {
|
||||||
// search the vtable for uses of either obsolete or EMCP methods
|
// search the vtable for uses of either obsolete or EMCP methods
|
||||||
|
@ -663,18 +811,26 @@ void klassVtable::adjust_method_entries(Method** old_methods, Method** new_metho
|
||||||
for (int index = 0; index < length(); index++) {
|
for (int index = 0; index < length(); index++) {
|
||||||
if (unchecked_method_at(index) == old_method) {
|
if (unchecked_method_at(index) == old_method) {
|
||||||
put_method_at(new_method, index);
|
put_method_at(new_method, index);
|
||||||
|
// For default methods, need to update the _default_methods array
|
||||||
|
// which can only have one method entry for a given signature
|
||||||
|
bool updated_default = false;
|
||||||
|
if (old_method->is_default_method()) {
|
||||||
|
updated_default = adjust_default_method(index, old_method, new_method);
|
||||||
|
}
|
||||||
|
|
||||||
if (RC_TRACE_IN_RANGE(0x00100000, 0x00400000)) {
|
if (RC_TRACE_IN_RANGE(0x00100000, 0x00400000)) {
|
||||||
if (!(*trace_name_printed)) {
|
if (!(*trace_name_printed)) {
|
||||||
// RC_TRACE_MESG macro has an embedded ResourceMark
|
// RC_TRACE_MESG macro has an embedded ResourceMark
|
||||||
RC_TRACE_MESG(("adjust: name=%s",
|
RC_TRACE_MESG(("adjust: klassname=%s for methods from name=%s",
|
||||||
|
klass()->external_name(),
|
||||||
old_method->method_holder()->external_name()));
|
old_method->method_holder()->external_name()));
|
||||||
*trace_name_printed = true;
|
*trace_name_printed = true;
|
||||||
}
|
}
|
||||||
// RC_TRACE macro has an embedded ResourceMark
|
// RC_TRACE macro has an embedded ResourceMark
|
||||||
RC_TRACE(0x00100000, ("vtable method update: %s(%s)",
|
RC_TRACE(0x00100000, ("vtable method update: %s(%s), updated default = %s",
|
||||||
new_method->name()->as_C_string(),
|
new_method->name()->as_C_string(),
|
||||||
new_method->signature()->as_C_string()));
|
new_method->signature()->as_C_string(),
|
||||||
|
updated_default ? "true" : "false"));
|
||||||
}
|
}
|
||||||
// cannot 'break' here; see for-loop comment above.
|
// cannot 'break' here; see for-loop comment above.
|
||||||
}
|
}
|
||||||
|
@ -701,6 +857,12 @@ void klassVtable::dump_vtable() {
|
||||||
if (m != NULL) {
|
if (m != NULL) {
|
||||||
tty->print(" (%5d) ", i);
|
tty->print(" (%5d) ", i);
|
||||||
m->access_flags().print_on(tty);
|
m->access_flags().print_on(tty);
|
||||||
|
if (m->is_default_method()) {
|
||||||
|
tty->print("default");
|
||||||
|
}
|
||||||
|
if (m->is_overpass()) {
|
||||||
|
tty->print("overpass");
|
||||||
|
}
|
||||||
tty->print(" -- ");
|
tty->print(" -- ");
|
||||||
m->print_name(tty);
|
m->print_name(tty);
|
||||||
tty->cr();
|
tty->cr();
|
||||||
|
@ -757,9 +919,9 @@ static int initialize_count = 0;
|
||||||
// Initialization
|
// Initialization
|
||||||
void klassItable::initialize_itable(bool checkconstraints, TRAPS) {
|
void klassItable::initialize_itable(bool checkconstraints, TRAPS) {
|
||||||
if (_klass->is_interface()) {
|
if (_klass->is_interface()) {
|
||||||
// This needs to go after vtable indexes are assigned but
|
// This needs to go after vtable indices are assigned but
|
||||||
// before implementors need to know the number of itable indexes.
|
// before implementors need to know the number of itable indices.
|
||||||
assign_itable_indexes_for_interface(_klass());
|
assign_itable_indices_for_interface(_klass());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cannot be setup doing bootstrapping, interfaces don't have
|
// Cannot be setup doing bootstrapping, interfaces don't have
|
||||||
|
@ -803,7 +965,7 @@ inline bool interface_method_needs_itable_index(Method* m) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
int klassItable::assign_itable_indexes_for_interface(Klass* klass) {
|
int klassItable::assign_itable_indices_for_interface(Klass* klass) {
|
||||||
// an interface does not have an itable, but its methods need to be numbered
|
// an interface does not have an itable, but its methods need to be numbered
|
||||||
if (TraceItables) tty->print_cr("%3d: Initializing itable for interface %s", ++initialize_count,
|
if (TraceItables) tty->print_cr("%3d: Initializing itable for interface %s", ++initialize_count,
|
||||||
klass->name()->as_C_string());
|
klass->name()->as_C_string());
|
||||||
|
@ -846,7 +1008,7 @@ int klassItable::method_count_for_interface(Klass* interf) {
|
||||||
}
|
}
|
||||||
nof_methods -= 1;
|
nof_methods -= 1;
|
||||||
}
|
}
|
||||||
// no methods have itable indexes
|
// no methods have itable indices
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -907,6 +1069,21 @@ void klassItable::initialize_itable_for_interface(int method_table_offset, Klass
|
||||||
int ime_num = m->itable_index();
|
int ime_num = m->itable_index();
|
||||||
assert(ime_num < ime_count, "oob");
|
assert(ime_num < ime_count, "oob");
|
||||||
itableOffsetEntry::method_entry(_klass(), method_table_offset)[ime_num].initialize(target());
|
itableOffsetEntry::method_entry(_klass(), method_table_offset)[ime_num].initialize(target());
|
||||||
|
if (TraceItables && Verbose) {
|
||||||
|
ResourceMark rm(THREAD);
|
||||||
|
if (target() != NULL) {
|
||||||
|
char* sig = target()->name_and_sig_as_C_string();
|
||||||
|
tty->print("interface: %s, ime_num: %d, target: %s, method_holder: %s ",
|
||||||
|
interf_h()->internal_name(), ime_num, sig,
|
||||||
|
target()->method_holder()->internal_name());
|
||||||
|
tty->print("target_method flags: ");
|
||||||
|
target()->access_flags().print_on(tty);
|
||||||
|
if (target()->is_default_method()) {
|
||||||
|
tty->print("default");
|
||||||
|
}
|
||||||
|
tty->cr();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -980,6 +1157,9 @@ void klassItable::dump_itable() {
|
||||||
if (m != NULL) {
|
if (m != NULL) {
|
||||||
tty->print(" (%5d) ", i);
|
tty->print(" (%5d) ", i);
|
||||||
m->access_flags().print_on(tty);
|
m->access_flags().print_on(tty);
|
||||||
|
if (m->is_default_method()) {
|
||||||
|
tty->print("default");
|
||||||
|
}
|
||||||
tty->print(" -- ");
|
tty->print(" -- ");
|
||||||
m->print_name(tty);
|
m->print_name(tty);
|
||||||
tty->cr();
|
tty->cr();
|
||||||
|
@ -1116,7 +1296,7 @@ Method* klassItable::method_for_itable_index(Klass* intf, int itable_index) {
|
||||||
Array<Method*>* methods = InstanceKlass::cast(intf)->methods();
|
Array<Method*>* methods = InstanceKlass::cast(intf)->methods();
|
||||||
|
|
||||||
if (itable_index < 0 || itable_index >= method_count_for_interface(intf))
|
if (itable_index < 0 || itable_index >= method_count_for_interface(intf))
|
||||||
return NULL; // help caller defend against bad indexes
|
return NULL; // help caller defend against bad indices
|
||||||
|
|
||||||
int index = itable_index;
|
int index = itable_index;
|
||||||
Method* m = methods->at(index);
|
Method* m = methods->at(index);
|
||||||
|
|
|
@ -97,6 +97,7 @@ class klassVtable : public ResourceObj {
|
||||||
// trace_name_printed is set to true if the current call has
|
// trace_name_printed is set to true if the current call has
|
||||||
// printed the klass name so that other routines in the adjust_*
|
// printed the klass name so that other routines in the adjust_*
|
||||||
// group don't print the klass name.
|
// group don't print the klass name.
|
||||||
|
bool adjust_default_method(int vtable_index, Method* old_method, Method* new_method);
|
||||||
void adjust_method_entries(Method** old_methods, Method** new_methods,
|
void adjust_method_entries(Method** old_methods, Method** new_methods,
|
||||||
int methods_length, bool * trace_name_printed);
|
int methods_length, bool * trace_name_printed);
|
||||||
bool check_no_old_or_obsolete_entries();
|
bool check_no_old_or_obsolete_entries();
|
||||||
|
@ -118,24 +119,28 @@ class klassVtable : public ResourceObj {
|
||||||
void put_method_at(Method* m, int index);
|
void put_method_at(Method* m, int index);
|
||||||
static bool needs_new_vtable_entry(methodHandle m, Klass* super, Handle classloader, Symbol* classname, AccessFlags access_flags, TRAPS);
|
static bool needs_new_vtable_entry(methodHandle m, Klass* super, Handle classloader, Symbol* classname, AccessFlags access_flags, TRAPS);
|
||||||
|
|
||||||
bool update_inherited_vtable(InstanceKlass* klass, methodHandle target_method, int super_vtable_len, bool checkconstraints, TRAPS);
|
bool update_inherited_vtable(InstanceKlass* klass, methodHandle target_method, int super_vtable_len, int default_index, bool checkconstraints, TRAPS);
|
||||||
InstanceKlass* find_transitive_override(InstanceKlass* initialsuper, methodHandle target_method, int vtable_index,
|
InstanceKlass* find_transitive_override(InstanceKlass* initialsuper, methodHandle target_method, int vtable_index,
|
||||||
Handle target_loader, Symbol* target_classname, Thread* THREAD);
|
Handle target_loader, Symbol* target_classname, Thread* THREAD);
|
||||||
|
|
||||||
// support for miranda methods
|
// support for miranda methods
|
||||||
bool is_miranda_entry_at(int i);
|
bool is_miranda_entry_at(int i);
|
||||||
int fill_in_mirandas(int initialized);
|
int fill_in_mirandas(int initialized);
|
||||||
static bool is_miranda(Method* m, Array<Method*>* class_methods, Klass* super);
|
static bool is_miranda(Method* m, Array<Method*>* class_methods,
|
||||||
|
Array<Method*>* default_methods, Klass* super);
|
||||||
static void add_new_mirandas_to_lists(
|
static void add_new_mirandas_to_lists(
|
||||||
GrowableArray<Method*>* new_mirandas,
|
GrowableArray<Method*>* new_mirandas,
|
||||||
GrowableArray<Method*>* all_mirandas,
|
GrowableArray<Method*>* all_mirandas,
|
||||||
Array<Method*>* current_interface_methods, Array<Method*>* class_methods,
|
Array<Method*>* current_interface_methods,
|
||||||
|
Array<Method*>* class_methods,
|
||||||
|
Array<Method*>* default_methods,
|
||||||
Klass* super);
|
Klass* super);
|
||||||
static void get_mirandas(
|
static void get_mirandas(
|
||||||
GrowableArray<Method*>* new_mirandas,
|
GrowableArray<Method*>* new_mirandas,
|
||||||
GrowableArray<Method*>* all_mirandas, Klass* super,
|
GrowableArray<Method*>* all_mirandas, Klass* super,
|
||||||
Array<Method*>* class_methods, Array<Klass*>* local_interfaces);
|
Array<Method*>* class_methods,
|
||||||
|
Array<Method*>* default_methods,
|
||||||
|
Array<Klass*>* local_interfaces);
|
||||||
void verify_against(outputStream* st, klassVtable* vt, int index);
|
void verify_against(outputStream* st, klassVtable* vt, int index);
|
||||||
inline InstanceKlass* ik() const;
|
inline InstanceKlass* ik() const;
|
||||||
};
|
};
|
||||||
|
@ -290,7 +295,7 @@ class klassItable : public ResourceObj {
|
||||||
#endif // INCLUDE_JVMTI
|
#endif // INCLUDE_JVMTI
|
||||||
|
|
||||||
// Setup of itable
|
// Setup of itable
|
||||||
static int assign_itable_indexes_for_interface(Klass* klass);
|
static int assign_itable_indices_for_interface(Klass* klass);
|
||||||
static int method_count_for_interface(Klass* klass);
|
static int method_count_for_interface(Klass* klass);
|
||||||
static int compute_itable_size(Array<Klass*>* transitive_interfaces);
|
static int compute_itable_size(Array<Klass*>* transitive_interfaces);
|
||||||
static void setup_itable_offset_table(instanceKlassHandle klass);
|
static void setup_itable_offset_table(instanceKlassHandle klass);
|
||||||
|
|
|
@ -511,9 +511,9 @@ bool Method::compute_has_loops_flag() {
|
||||||
|
|
||||||
bool Method::is_final_method(AccessFlags class_access_flags) const {
|
bool Method::is_final_method(AccessFlags class_access_flags) const {
|
||||||
// or "does_not_require_vtable_entry"
|
// or "does_not_require_vtable_entry"
|
||||||
// overpass can occur, is not final (reuses vtable entry)
|
// default method or overpass can occur, is not final (reuses vtable entry)
|
||||||
// private methods get vtable entries for backward class compatibility.
|
// private methods get vtable entries for backward class compatibility.
|
||||||
if (is_overpass()) return false;
|
if (is_overpass() || is_default_method()) return false;
|
||||||
return is_final() || class_access_flags.is_final();
|
return is_final() || class_access_flags.is_final();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -521,11 +521,24 @@ bool Method::is_final_method() const {
|
||||||
return is_final_method(method_holder()->access_flags());
|
return is_final_method(method_holder()->access_flags());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Method::is_default_method() const {
|
||||||
|
if (method_holder() != NULL &&
|
||||||
|
method_holder()->is_interface() &&
|
||||||
|
!is_abstract()) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool Method::can_be_statically_bound(AccessFlags class_access_flags) const {
|
bool Method::can_be_statically_bound(AccessFlags class_access_flags) const {
|
||||||
if (is_final_method(class_access_flags)) return true;
|
if (is_final_method(class_access_flags)) return true;
|
||||||
#ifdef ASSERT
|
#ifdef ASSERT
|
||||||
|
ResourceMark rm;
|
||||||
bool is_nonv = (vtable_index() == nonvirtual_vtable_index);
|
bool is_nonv = (vtable_index() == nonvirtual_vtable_index);
|
||||||
if (class_access_flags.is_interface()) assert(is_nonv == is_static(), err_msg("is_nonv=%s", is_nonv));
|
if (class_access_flags.is_interface()) {
|
||||||
|
assert(is_nonv == is_static(), err_msg("is_nonv=%s", name_and_sig_as_C_string()));
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
assert(valid_vtable_index() || valid_itable_index(), "method must be linked before we ask this question");
|
assert(valid_vtable_index() || valid_itable_index(), "method must be linked before we ask this question");
|
||||||
return vtable_index() == nonvirtual_vtable_index;
|
return vtable_index() == nonvirtual_vtable_index;
|
||||||
|
@ -1371,7 +1384,8 @@ static int method_comparator(Method* a, Method* b) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is only done during class loading, so it is OK to assume method_idnum matches the methods() array
|
// This is only done during class loading, so it is OK to assume method_idnum matches the methods() array
|
||||||
void Method::sort_methods(Array<Method*>* methods, bool idempotent) {
|
// default_methods also uses this without the ordering for fast find_method
|
||||||
|
void Method::sort_methods(Array<Method*>* methods, bool idempotent, bool set_idnums) {
|
||||||
int length = methods->length();
|
int length = methods->length();
|
||||||
if (length > 1) {
|
if (length > 1) {
|
||||||
{
|
{
|
||||||
|
@ -1379,13 +1393,14 @@ void Method::sort_methods(Array<Method*>* methods, bool idempotent) {
|
||||||
QuickSort::sort<Method*>(methods->data(), length, method_comparator, idempotent);
|
QuickSort::sort<Method*>(methods->data(), length, method_comparator, idempotent);
|
||||||
}
|
}
|
||||||
// Reset method ordering
|
// Reset method ordering
|
||||||
|
if (set_idnums) {
|
||||||
for (int i = 0; i < length; i++) {
|
for (int i = 0; i < length; i++) {
|
||||||
Method* m = methods->at(i);
|
Method* m = methods->at(i);
|
||||||
m->set_method_idnum(i);
|
m->set_method_idnum(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------------
|
||||||
// Non-product code unless JVM/TI needs it
|
// Non-product code unless JVM/TI needs it
|
||||||
|
|
|
@ -567,6 +567,7 @@ class Method : public Metadata {
|
||||||
// checks method and its method holder
|
// checks method and its method holder
|
||||||
bool is_final_method() const;
|
bool is_final_method() const;
|
||||||
bool is_final_method(AccessFlags class_access_flags) const;
|
bool is_final_method(AccessFlags class_access_flags) const;
|
||||||
|
bool is_default_method() const;
|
||||||
|
|
||||||
// true if method needs no dynamic dispatch (final and/or no vtable entry)
|
// true if method needs no dynamic dispatch (final and/or no vtable entry)
|
||||||
bool can_be_statically_bound() const;
|
bool can_be_statically_bound() const;
|
||||||
|
@ -846,7 +847,7 @@ class Method : public Metadata {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Helper routine used for method sorting
|
// Helper routine used for method sorting
|
||||||
static void sort_methods(Array<Method*>* methods, bool idempotent = false);
|
static void sort_methods(Array<Method*>* methods, bool idempotent = false, bool set_idnums = true);
|
||||||
|
|
||||||
// Deallocation function for redefine classes or if an error occurs
|
// Deallocation function for redefine classes or if an error occurs
|
||||||
void deallocate_contents(ClassLoaderData* loader_data);
|
void deallocate_contents(ClassLoaderData* loader_data);
|
||||||
|
|
|
@ -3713,7 +3713,8 @@ void GraphKit::g1_write_barrier_post(Node* oop_store,
|
||||||
Node* no_base = __ top();
|
Node* no_base = __ top();
|
||||||
float likely = PROB_LIKELY(0.999);
|
float likely = PROB_LIKELY(0.999);
|
||||||
float unlikely = PROB_UNLIKELY(0.999);
|
float unlikely = PROB_UNLIKELY(0.999);
|
||||||
Node* zero = __ ConI(0);
|
Node* young_card = __ ConI((jint)G1SATBCardTableModRefBS::g1_young_card_val());
|
||||||
|
Node* dirty_card = __ ConI((jint)CardTableModRefBS::dirty_card_val());
|
||||||
Node* zeroX = __ ConX(0);
|
Node* zeroX = __ ConX(0);
|
||||||
|
|
||||||
// Get the alias_index for raw card-mark memory
|
// Get the alias_index for raw card-mark memory
|
||||||
|
@ -3769,11 +3770,19 @@ void GraphKit::g1_write_barrier_post(Node* oop_store,
|
||||||
// load the original value of the card
|
// load the original value of the card
|
||||||
Node* card_val = __ load(__ ctrl(), card_adr, TypeInt::INT, T_BYTE, Compile::AliasIdxRaw);
|
Node* card_val = __ load(__ ctrl(), card_adr, TypeInt::INT, T_BYTE, Compile::AliasIdxRaw);
|
||||||
|
|
||||||
__ if_then(card_val, BoolTest::ne, zero); {
|
__ if_then(card_val, BoolTest::ne, young_card); {
|
||||||
|
sync_kit(ideal);
|
||||||
|
// Use Op_MemBarVolatile to achieve the effect of a StoreLoad barrier.
|
||||||
|
insert_mem_bar(Op_MemBarVolatile, oop_store);
|
||||||
|
__ sync_kit(this);
|
||||||
|
|
||||||
|
Node* card_val_reload = __ load(__ ctrl(), card_adr, TypeInt::INT, T_BYTE, Compile::AliasIdxRaw);
|
||||||
|
__ if_then(card_val_reload, BoolTest::ne, dirty_card); {
|
||||||
g1_mark_card(ideal, card_adr, oop_store, alias_idx, index, index_adr, buffer, tf);
|
g1_mark_card(ideal, card_adr, oop_store, alias_idx, index, index_adr, buffer, tf);
|
||||||
} __ end_if();
|
} __ end_if();
|
||||||
} __ end_if();
|
} __ end_if();
|
||||||
} __ end_if();
|
} __ end_if();
|
||||||
|
} __ end_if();
|
||||||
} else {
|
} else {
|
||||||
// Object.clone() instrinsic uses this path.
|
// Object.clone() instrinsic uses this path.
|
||||||
g1_mark_card(ideal, card_adr, oop_store, alias_idx, index, index_adr, buffer, tf);
|
g1_mark_card(ideal, card_adr, oop_store, alias_idx, index, index_adr, buffer, tf);
|
||||||
|
|
|
@ -1591,10 +1591,8 @@ static jmethodID get_method_id(JNIEnv *env, jclass clazz, const char *name_str,
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
m = klass->lookup_method(name, signature);
|
m = klass->lookup_method(name, signature);
|
||||||
// Look up interfaces
|
|
||||||
if (m == NULL && klass->oop_is_instance()) {
|
if (m == NULL && klass->oop_is_instance()) {
|
||||||
m = InstanceKlass::cast(klass())->lookup_method_in_all_interfaces(name,
|
m = InstanceKlass::cast(klass())->lookup_method_in_ordered_interfaces(name, signature);
|
||||||
signature);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (m == NULL || (m->is_static() != is_static)) {
|
if (m == NULL || (m->is_static() != is_static)) {
|
||||||
|
@ -3210,7 +3208,11 @@ JNI_QUICK_ENTRY(jsize, jni_GetStringLength(JNIEnv *env, jstring string))
|
||||||
HOTSPOT_JNI_GETSTRINGLENGTH_ENTRY(
|
HOTSPOT_JNI_GETSTRINGLENGTH_ENTRY(
|
||||||
env, string);
|
env, string);
|
||||||
#endif /* USDT2 */
|
#endif /* USDT2 */
|
||||||
jsize ret = java_lang_String::length(JNIHandles::resolve_non_null(string));
|
jsize ret = 0;
|
||||||
|
oop s = JNIHandles::resolve_non_null(string);
|
||||||
|
if (java_lang_String::value(s) != NULL) {
|
||||||
|
ret = java_lang_String::length(s);
|
||||||
|
}
|
||||||
#ifndef USDT2
|
#ifndef USDT2
|
||||||
DTRACE_PROBE1(hotspot_jni, GetStringLength__return, ret);
|
DTRACE_PROBE1(hotspot_jni, GetStringLength__return, ret);
|
||||||
#else /* USDT2 */
|
#else /* USDT2 */
|
||||||
|
@ -3230,11 +3232,13 @@ JNI_QUICK_ENTRY(const jchar*, jni_GetStringChars(
|
||||||
HOTSPOT_JNI_GETSTRINGCHARS_ENTRY(
|
HOTSPOT_JNI_GETSTRINGCHARS_ENTRY(
|
||||||
env, string, (uintptr_t *) isCopy);
|
env, string, (uintptr_t *) isCopy);
|
||||||
#endif /* USDT2 */
|
#endif /* USDT2 */
|
||||||
|
jchar* buf = NULL;
|
||||||
oop s = JNIHandles::resolve_non_null(string);
|
oop s = JNIHandles::resolve_non_null(string);
|
||||||
int s_len = java_lang_String::length(s);
|
|
||||||
typeArrayOop s_value = java_lang_String::value(s);
|
typeArrayOop s_value = java_lang_String::value(s);
|
||||||
|
if (s_value != NULL) {
|
||||||
|
int s_len = java_lang_String::length(s);
|
||||||
int s_offset = java_lang_String::offset(s);
|
int s_offset = java_lang_String::offset(s);
|
||||||
jchar* buf = NEW_C_HEAP_ARRAY_RETURN_NULL(jchar, s_len + 1, mtInternal); // add one for zero termination
|
buf = NEW_C_HEAP_ARRAY_RETURN_NULL(jchar, s_len + 1, mtInternal); // add one for zero termination
|
||||||
/* JNI Specification states return NULL on OOM */
|
/* JNI Specification states return NULL on OOM */
|
||||||
if (buf != NULL) {
|
if (buf != NULL) {
|
||||||
if (s_len > 0) {
|
if (s_len > 0) {
|
||||||
|
@ -3246,6 +3250,7 @@ JNI_QUICK_ENTRY(const jchar*, jni_GetStringChars(
|
||||||
*isCopy = JNI_TRUE;
|
*isCopy = JNI_TRUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
#ifndef USDT2
|
#ifndef USDT2
|
||||||
DTRACE_PROBE1(hotspot_jni, GetStringChars__return, buf);
|
DTRACE_PROBE1(hotspot_jni, GetStringChars__return, buf);
|
||||||
#else /* USDT2 */
|
#else /* USDT2 */
|
||||||
|
@ -3313,7 +3318,11 @@ JNI_ENTRY(jsize, jni_GetStringUTFLength(JNIEnv *env, jstring string))
|
||||||
HOTSPOT_JNI_GETSTRINGUTFLENGTH_ENTRY(
|
HOTSPOT_JNI_GETSTRINGUTFLENGTH_ENTRY(
|
||||||
env, string);
|
env, string);
|
||||||
#endif /* USDT2 */
|
#endif /* USDT2 */
|
||||||
jsize ret = java_lang_String::utf8_length(JNIHandles::resolve_non_null(string));
|
jsize ret = 0;
|
||||||
|
oop java_string = JNIHandles::resolve_non_null(string);
|
||||||
|
if (java_lang_String::value(java_string) != NULL) {
|
||||||
|
ret = java_lang_String::utf8_length(java_string);
|
||||||
|
}
|
||||||
#ifndef USDT2
|
#ifndef USDT2
|
||||||
DTRACE_PROBE1(hotspot_jni, GetStringUTFLength__return, ret);
|
DTRACE_PROBE1(hotspot_jni, GetStringUTFLength__return, ret);
|
||||||
#else /* USDT2 */
|
#else /* USDT2 */
|
||||||
|
@ -3332,16 +3341,19 @@ JNI_ENTRY(const char*, jni_GetStringUTFChars(JNIEnv *env, jstring string, jboole
|
||||||
HOTSPOT_JNI_GETSTRINGUTFCHARS_ENTRY(
|
HOTSPOT_JNI_GETSTRINGUTFCHARS_ENTRY(
|
||||||
env, string, (uintptr_t *) isCopy);
|
env, string, (uintptr_t *) isCopy);
|
||||||
#endif /* USDT2 */
|
#endif /* USDT2 */
|
||||||
|
char* result = NULL;
|
||||||
oop java_string = JNIHandles::resolve_non_null(string);
|
oop java_string = JNIHandles::resolve_non_null(string);
|
||||||
|
if (java_lang_String::value(java_string) != NULL) {
|
||||||
size_t length = java_lang_String::utf8_length(java_string);
|
size_t length = java_lang_String::utf8_length(java_string);
|
||||||
/* JNI Specification states return NULL on OOM */
|
/* JNI Specification states return NULL on OOM */
|
||||||
char* result = AllocateHeap(length + 1, mtInternal, 0, AllocFailStrategy::RETURN_NULL);
|
result = AllocateHeap(length + 1, mtInternal, 0, AllocFailStrategy::RETURN_NULL);
|
||||||
if (result != NULL) {
|
if (result != NULL) {
|
||||||
java_lang_String::as_utf8_string(java_string, result, (int) length + 1);
|
java_lang_String::as_utf8_string(java_string, result, (int) length + 1);
|
||||||
if (isCopy != NULL) {
|
if (isCopy != NULL) {
|
||||||
*isCopy = JNI_TRUE;
|
*isCopy = JNI_TRUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
#ifndef USDT2
|
#ifndef USDT2
|
||||||
DTRACE_PROBE1(hotspot_jni, GetStringUTFChars__return, result);
|
DTRACE_PROBE1(hotspot_jni, GetStringUTFChars__return, result);
|
||||||
#else /* USDT2 */
|
#else /* USDT2 */
|
||||||
|
|
|
@ -1324,18 +1324,19 @@ JNI_ENTRY_CHECKED(const jchar *,
|
||||||
IN_VM(
|
IN_VM(
|
||||||
checkString(thr, str);
|
checkString(thr, str);
|
||||||
)
|
)
|
||||||
|
jchar* newResult = NULL;
|
||||||
const jchar *result = UNCHECKED()->GetStringChars(env,str,isCopy);
|
const jchar *result = UNCHECKED()->GetStringChars(env,str,isCopy);
|
||||||
assert (isCopy == NULL || *isCopy == JNI_TRUE, "GetStringChars didn't return a copy as expected");
|
assert (isCopy == NULL || *isCopy == JNI_TRUE, "GetStringChars didn't return a copy as expected");
|
||||||
|
if (result != NULL) {
|
||||||
size_t len = UNCHECKED()->GetStringLength(env,str) + 1; // + 1 for NULL termination
|
size_t len = UNCHECKED()->GetStringLength(env,str) + 1; // + 1 for NULL termination
|
||||||
jint* tagLocation = (jint*) AllocateHeap(len * sizeof(jchar) + sizeof(jint), mtInternal);
|
jint* tagLocation = (jint*) AllocateHeap(len * sizeof(jchar) + sizeof(jint), mtInternal);
|
||||||
*tagLocation = STRING_TAG;
|
*tagLocation = STRING_TAG;
|
||||||
jchar* newResult = (jchar*) (tagLocation + 1);
|
newResult = (jchar*) (tagLocation + 1);
|
||||||
memcpy(newResult, result, len * sizeof(jchar));
|
memcpy(newResult, result, len * sizeof(jchar));
|
||||||
// Avoiding call to UNCHECKED()->ReleaseStringChars() since that will fire unexpected dtrace probes
|
// Avoiding call to UNCHECKED()->ReleaseStringChars() since that will fire unexpected dtrace probes
|
||||||
// Note that the dtrace arguments for the allocated memory will not match up with this solution.
|
// Note that the dtrace arguments for the allocated memory will not match up with this solution.
|
||||||
FreeHeap((char*)result);
|
FreeHeap((char*)result);
|
||||||
|
}
|
||||||
functionExit(env);
|
functionExit(env);
|
||||||
return newResult;
|
return newResult;
|
||||||
JNI_END
|
JNI_END
|
||||||
|
@ -1394,18 +1395,19 @@ JNI_ENTRY_CHECKED(const char *,
|
||||||
IN_VM(
|
IN_VM(
|
||||||
checkString(thr, str);
|
checkString(thr, str);
|
||||||
)
|
)
|
||||||
|
char* newResult = NULL;
|
||||||
const char *result = UNCHECKED()->GetStringUTFChars(env,str,isCopy);
|
const char *result = UNCHECKED()->GetStringUTFChars(env,str,isCopy);
|
||||||
assert (isCopy == NULL || *isCopy == JNI_TRUE, "GetStringUTFChars didn't return a copy as expected");
|
assert (isCopy == NULL || *isCopy == JNI_TRUE, "GetStringUTFChars didn't return a copy as expected");
|
||||||
|
if (result != NULL) {
|
||||||
size_t len = strlen(result) + 1; // + 1 for NULL termination
|
size_t len = strlen(result) + 1; // + 1 for NULL termination
|
||||||
jint* tagLocation = (jint*) AllocateHeap(len + sizeof(jint), mtInternal);
|
jint* tagLocation = (jint*) AllocateHeap(len + sizeof(jint), mtInternal);
|
||||||
*tagLocation = STRING_UTF_TAG;
|
*tagLocation = STRING_UTF_TAG;
|
||||||
char* newResult = (char*) (tagLocation + 1);
|
newResult = (char*) (tagLocation + 1);
|
||||||
strcpy(newResult, result);
|
strcpy(newResult, result);
|
||||||
// Avoiding call to UNCHECKED()->ReleaseStringUTFChars() since that will fire unexpected dtrace probes
|
// Avoiding call to UNCHECKED()->ReleaseStringUTFChars() since that will fire unexpected dtrace probes
|
||||||
// Note that the dtrace arguments for the allocated memory will not match up with this solution.
|
// Note that the dtrace arguments for the allocated memory will not match up with this solution.
|
||||||
FreeHeap((char*)result, mtInternal);
|
FreeHeap((char*)result, mtInternal);
|
||||||
|
}
|
||||||
functionExit(env);
|
functionExit(env);
|
||||||
return newResult;
|
return newResult;
|
||||||
JNI_END
|
JNI_END
|
||||||
|
|
|
@ -668,13 +668,12 @@ JVM_END
|
||||||
JVM_ENTRY(jclass, JVM_GetCallerClass(JNIEnv* env, int depth))
|
JVM_ENTRY(jclass, JVM_GetCallerClass(JNIEnv* env, int depth))
|
||||||
JVMWrapper("JVM_GetCallerClass");
|
JVMWrapper("JVM_GetCallerClass");
|
||||||
|
|
||||||
// Pre-JDK 8 and early builds of JDK 8 don't have a CallerSensitive annotation.
|
// Pre-JDK 8 and early builds of JDK 8 don't have a CallerSensitive annotation; or
|
||||||
if (SystemDictionary::reflect_CallerSensitive_klass() == NULL) {
|
// sun.reflect.Reflection.getCallerClass with a depth parameter is provided
|
||||||
|
// temporarily for existing code to use until a replacement API is defined.
|
||||||
|
if (SystemDictionary::reflect_CallerSensitive_klass() == NULL || depth != JVM_CALLER_DEPTH) {
|
||||||
Klass* k = thread->security_get_caller_class(depth);
|
Klass* k = thread->security_get_caller_class(depth);
|
||||||
return (k == NULL) ? NULL : (jclass) JNIHandles::make_local(env, k->java_mirror());
|
return (k == NULL) ? NULL : (jclass) JNIHandles::make_local(env, k->java_mirror());
|
||||||
} else {
|
|
||||||
// Basic handshaking with Java_sun_reflect_Reflection_getCallerClass
|
|
||||||
assert(depth == -1, "wrong handshake depth");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Getting the class of the caller frame.
|
// Getting the class of the caller frame.
|
||||||
|
@ -3954,248 +3953,6 @@ void initialize_converter_functions() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Serialization
|
|
||||||
JVM_ENTRY(void, JVM_SetPrimitiveFieldValues(JNIEnv *env, jclass cb, jobject obj,
|
|
||||||
jlongArray fieldIDs, jcharArray typecodes, jbyteArray data))
|
|
||||||
assert(!JDK_Version::is_gte_jdk14x_version(), "should only be used in 1.3.1 and earlier");
|
|
||||||
|
|
||||||
typeArrayOop tcodes = typeArrayOop(JNIHandles::resolve(typecodes));
|
|
||||||
typeArrayOop dbuf = typeArrayOop(JNIHandles::resolve(data));
|
|
||||||
typeArrayOop fids = typeArrayOop(JNIHandles::resolve(fieldIDs));
|
|
||||||
oop o = JNIHandles::resolve(obj);
|
|
||||||
|
|
||||||
if (o == NULL || fids == NULL || dbuf == NULL || tcodes == NULL) {
|
|
||||||
THROW(vmSymbols::java_lang_NullPointerException());
|
|
||||||
}
|
|
||||||
|
|
||||||
jsize nfids = fids->length();
|
|
||||||
if (nfids == 0) return;
|
|
||||||
|
|
||||||
if (tcodes->length() < nfids) {
|
|
||||||
THROW(vmSymbols::java_lang_ArrayIndexOutOfBoundsException());
|
|
||||||
}
|
|
||||||
|
|
||||||
jsize off = 0;
|
|
||||||
/* loop through fields, setting values */
|
|
||||||
for (jsize i = 0; i < nfids; i++) {
|
|
||||||
jfieldID fid = (jfieldID)(intptr_t) fids->long_at(i);
|
|
||||||
int field_offset;
|
|
||||||
if (fid != NULL) {
|
|
||||||
// NULL is a legal value for fid, but retrieving the field offset
|
|
||||||
// trigger assertion in that case
|
|
||||||
field_offset = jfieldIDWorkaround::from_instance_jfieldID(o->klass(), fid);
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (tcodes->char_at(i)) {
|
|
||||||
case 'Z':
|
|
||||||
if (fid != NULL) {
|
|
||||||
jboolean val = (dbuf->byte_at(off) != 0) ? JNI_TRUE : JNI_FALSE;
|
|
||||||
o->bool_field_put(field_offset, val);
|
|
||||||
}
|
|
||||||
off++;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'B':
|
|
||||||
if (fid != NULL) {
|
|
||||||
o->byte_field_put(field_offset, dbuf->byte_at(off));
|
|
||||||
}
|
|
||||||
off++;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'C':
|
|
||||||
if (fid != NULL) {
|
|
||||||
jchar val = ((dbuf->byte_at(off + 0) & 0xFF) << 8)
|
|
||||||
+ ((dbuf->byte_at(off + 1) & 0xFF) << 0);
|
|
||||||
o->char_field_put(field_offset, val);
|
|
||||||
}
|
|
||||||
off += 2;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'S':
|
|
||||||
if (fid != NULL) {
|
|
||||||
jshort val = ((dbuf->byte_at(off + 0) & 0xFF) << 8)
|
|
||||||
+ ((dbuf->byte_at(off + 1) & 0xFF) << 0);
|
|
||||||
o->short_field_put(field_offset, val);
|
|
||||||
}
|
|
||||||
off += 2;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'I':
|
|
||||||
if (fid != NULL) {
|
|
||||||
jint ival = ((dbuf->byte_at(off + 0) & 0xFF) << 24)
|
|
||||||
+ ((dbuf->byte_at(off + 1) & 0xFF) << 16)
|
|
||||||
+ ((dbuf->byte_at(off + 2) & 0xFF) << 8)
|
|
||||||
+ ((dbuf->byte_at(off + 3) & 0xFF) << 0);
|
|
||||||
o->int_field_put(field_offset, ival);
|
|
||||||
}
|
|
||||||
off += 4;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'F':
|
|
||||||
if (fid != NULL) {
|
|
||||||
jint ival = ((dbuf->byte_at(off + 0) & 0xFF) << 24)
|
|
||||||
+ ((dbuf->byte_at(off + 1) & 0xFF) << 16)
|
|
||||||
+ ((dbuf->byte_at(off + 2) & 0xFF) << 8)
|
|
||||||
+ ((dbuf->byte_at(off + 3) & 0xFF) << 0);
|
|
||||||
jfloat fval = (*int_bits_to_float_fn)(env, NULL, ival);
|
|
||||||
o->float_field_put(field_offset, fval);
|
|
||||||
}
|
|
||||||
off += 4;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'J':
|
|
||||||
if (fid != NULL) {
|
|
||||||
jlong lval = (((jlong) dbuf->byte_at(off + 0) & 0xFF) << 56)
|
|
||||||
+ (((jlong) dbuf->byte_at(off + 1) & 0xFF) << 48)
|
|
||||||
+ (((jlong) dbuf->byte_at(off + 2) & 0xFF) << 40)
|
|
||||||
+ (((jlong) dbuf->byte_at(off + 3) & 0xFF) << 32)
|
|
||||||
+ (((jlong) dbuf->byte_at(off + 4) & 0xFF) << 24)
|
|
||||||
+ (((jlong) dbuf->byte_at(off + 5) & 0xFF) << 16)
|
|
||||||
+ (((jlong) dbuf->byte_at(off + 6) & 0xFF) << 8)
|
|
||||||
+ (((jlong) dbuf->byte_at(off + 7) & 0xFF) << 0);
|
|
||||||
o->long_field_put(field_offset, lval);
|
|
||||||
}
|
|
||||||
off += 8;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'D':
|
|
||||||
if (fid != NULL) {
|
|
||||||
jlong lval = (((jlong) dbuf->byte_at(off + 0) & 0xFF) << 56)
|
|
||||||
+ (((jlong) dbuf->byte_at(off + 1) & 0xFF) << 48)
|
|
||||||
+ (((jlong) dbuf->byte_at(off + 2) & 0xFF) << 40)
|
|
||||||
+ (((jlong) dbuf->byte_at(off + 3) & 0xFF) << 32)
|
|
||||||
+ (((jlong) dbuf->byte_at(off + 4) & 0xFF) << 24)
|
|
||||||
+ (((jlong) dbuf->byte_at(off + 5) & 0xFF) << 16)
|
|
||||||
+ (((jlong) dbuf->byte_at(off + 6) & 0xFF) << 8)
|
|
||||||
+ (((jlong) dbuf->byte_at(off + 7) & 0xFF) << 0);
|
|
||||||
jdouble dval = (*long_bits_to_double_fn)(env, NULL, lval);
|
|
||||||
o->double_field_put(field_offset, dval);
|
|
||||||
}
|
|
||||||
off += 8;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
// Illegal typecode
|
|
||||||
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), "illegal typecode");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
JVM_END
|
|
||||||
|
|
||||||
|
|
||||||
JVM_ENTRY(void, JVM_GetPrimitiveFieldValues(JNIEnv *env, jclass cb, jobject obj,
|
|
||||||
jlongArray fieldIDs, jcharArray typecodes, jbyteArray data))
|
|
||||||
assert(!JDK_Version::is_gte_jdk14x_version(), "should only be used in 1.3.1 and earlier");
|
|
||||||
|
|
||||||
typeArrayOop tcodes = typeArrayOop(JNIHandles::resolve(typecodes));
|
|
||||||
typeArrayOop dbuf = typeArrayOop(JNIHandles::resolve(data));
|
|
||||||
typeArrayOop fids = typeArrayOop(JNIHandles::resolve(fieldIDs));
|
|
||||||
oop o = JNIHandles::resolve(obj);
|
|
||||||
|
|
||||||
if (o == NULL || fids == NULL || dbuf == NULL || tcodes == NULL) {
|
|
||||||
THROW(vmSymbols::java_lang_NullPointerException());
|
|
||||||
}
|
|
||||||
|
|
||||||
jsize nfids = fids->length();
|
|
||||||
if (nfids == 0) return;
|
|
||||||
|
|
||||||
if (tcodes->length() < nfids) {
|
|
||||||
THROW(vmSymbols::java_lang_ArrayIndexOutOfBoundsException());
|
|
||||||
}
|
|
||||||
|
|
||||||
/* loop through fields, fetching values */
|
|
||||||
jsize off = 0;
|
|
||||||
for (jsize i = 0; i < nfids; i++) {
|
|
||||||
jfieldID fid = (jfieldID)(intptr_t) fids->long_at(i);
|
|
||||||
if (fid == NULL) {
|
|
||||||
THROW(vmSymbols::java_lang_NullPointerException());
|
|
||||||
}
|
|
||||||
int field_offset = jfieldIDWorkaround::from_instance_jfieldID(o->klass(), fid);
|
|
||||||
|
|
||||||
switch (tcodes->char_at(i)) {
|
|
||||||
case 'Z':
|
|
||||||
{
|
|
||||||
jboolean val = o->bool_field(field_offset);
|
|
||||||
dbuf->byte_at_put(off++, (val != 0) ? 1 : 0);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'B':
|
|
||||||
dbuf->byte_at_put(off++, o->byte_field(field_offset));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'C':
|
|
||||||
{
|
|
||||||
jchar val = o->char_field(field_offset);
|
|
||||||
dbuf->byte_at_put(off++, (val >> 8) & 0xFF);
|
|
||||||
dbuf->byte_at_put(off++, (val >> 0) & 0xFF);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'S':
|
|
||||||
{
|
|
||||||
jshort val = o->short_field(field_offset);
|
|
||||||
dbuf->byte_at_put(off++, (val >> 8) & 0xFF);
|
|
||||||
dbuf->byte_at_put(off++, (val >> 0) & 0xFF);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'I':
|
|
||||||
{
|
|
||||||
jint val = o->int_field(field_offset);
|
|
||||||
dbuf->byte_at_put(off++, (val >> 24) & 0xFF);
|
|
||||||
dbuf->byte_at_put(off++, (val >> 16) & 0xFF);
|
|
||||||
dbuf->byte_at_put(off++, (val >> 8) & 0xFF);
|
|
||||||
dbuf->byte_at_put(off++, (val >> 0) & 0xFF);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'F':
|
|
||||||
{
|
|
||||||
jfloat fval = o->float_field(field_offset);
|
|
||||||
jint ival = (*float_to_int_bits_fn)(env, NULL, fval);
|
|
||||||
dbuf->byte_at_put(off++, (ival >> 24) & 0xFF);
|
|
||||||
dbuf->byte_at_put(off++, (ival >> 16) & 0xFF);
|
|
||||||
dbuf->byte_at_put(off++, (ival >> 8) & 0xFF);
|
|
||||||
dbuf->byte_at_put(off++, (ival >> 0) & 0xFF);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'J':
|
|
||||||
{
|
|
||||||
jlong val = o->long_field(field_offset);
|
|
||||||
dbuf->byte_at_put(off++, (val >> 56) & 0xFF);
|
|
||||||
dbuf->byte_at_put(off++, (val >> 48) & 0xFF);
|
|
||||||
dbuf->byte_at_put(off++, (val >> 40) & 0xFF);
|
|
||||||
dbuf->byte_at_put(off++, (val >> 32) & 0xFF);
|
|
||||||
dbuf->byte_at_put(off++, (val >> 24) & 0xFF);
|
|
||||||
dbuf->byte_at_put(off++, (val >> 16) & 0xFF);
|
|
||||||
dbuf->byte_at_put(off++, (val >> 8) & 0xFF);
|
|
||||||
dbuf->byte_at_put(off++, (val >> 0) & 0xFF);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'D':
|
|
||||||
{
|
|
||||||
jdouble dval = o->double_field(field_offset);
|
|
||||||
jlong lval = (*double_to_long_bits_fn)(env, NULL, dval);
|
|
||||||
dbuf->byte_at_put(off++, (lval >> 56) & 0xFF);
|
|
||||||
dbuf->byte_at_put(off++, (lval >> 48) & 0xFF);
|
|
||||||
dbuf->byte_at_put(off++, (lval >> 40) & 0xFF);
|
|
||||||
dbuf->byte_at_put(off++, (lval >> 32) & 0xFF);
|
|
||||||
dbuf->byte_at_put(off++, (lval >> 24) & 0xFF);
|
|
||||||
dbuf->byte_at_put(off++, (lval >> 16) & 0xFF);
|
|
||||||
dbuf->byte_at_put(off++, (lval >> 8) & 0xFF);
|
|
||||||
dbuf->byte_at_put(off++, (lval >> 0) & 0xFF);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
// Illegal typecode
|
|
||||||
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), "illegal typecode");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
JVM_END
|
|
||||||
|
|
||||||
|
|
||||||
// Shared JNI/JVM entry points //////////////////////////////////////////////////////////////
|
// Shared JNI/JVM entry points //////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
|
|
@ -374,6 +374,9 @@ JVM_NewMultiArray(JNIEnv *env, jclass eltClass, jintArray dim);
|
||||||
/*
|
/*
|
||||||
* java.lang.Class and java.lang.ClassLoader
|
* java.lang.Class and java.lang.ClassLoader
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#define JVM_CALLER_DEPTH -1
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Returns the class in which the code invoking the native method
|
* Returns the class in which the code invoking the native method
|
||||||
* belongs.
|
* belongs.
|
||||||
|
|
|
@ -35,22 +35,6 @@ jclass find_class_from_class_loader(JNIEnv* env, Symbol* name, jboolean init, Ha
|
||||||
|
|
||||||
void trace_class_resolution(Klass* to_class);
|
void trace_class_resolution(Klass* to_class);
|
||||||
|
|
||||||
/*
|
|
||||||
* Support for Serialization and RMI. Currently used by HotSpot only.
|
|
||||||
*/
|
|
||||||
|
|
||||||
extern "C" {
|
|
||||||
|
|
||||||
void JNICALL
|
|
||||||
JVM_SetPrimitiveFieldValues(JNIEnv *env, jclass cb, jobject obj,
|
|
||||||
jlongArray fieldIDs, jcharArray typecodes, jbyteArray data);
|
|
||||||
|
|
||||||
void JNICALL
|
|
||||||
JVM_GetPrimitiveFieldValues(JNIEnv *env, jclass cb, jobject obj,
|
|
||||||
jlongArray fieldIDs, jcharArray typecodes, jbyteArray data);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Support for -Xcheck:jni
|
* Support for -Xcheck:jni
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -2755,13 +2755,26 @@ void VM_RedefineClasses::AdjustCpoolCacheAndVtable::do_klass(Klass* k) {
|
||||||
// InstanceKlass around to hold obsolete methods so we don't have
|
// InstanceKlass around to hold obsolete methods so we don't have
|
||||||
// any other InstanceKlass embedded vtables to update. The vtable
|
// any other InstanceKlass embedded vtables to update. The vtable
|
||||||
// holds the Method*s for virtual (but not final) methods.
|
// holds the Method*s for virtual (but not final) methods.
|
||||||
if (ik->vtable_length() > 0 && ik->is_subtype_of(_the_class_oop)) {
|
// Default methods, or concrete methods in interfaces are stored
|
||||||
|
// in the vtable, so if an interface changes we need to check
|
||||||
|
// adjust_method_entries() for every InstanceKlass, which will also
|
||||||
|
// adjust the default method vtable indices.
|
||||||
|
// We also need to adjust any default method entries that are
|
||||||
|
// not yet in the vtable, because the vtable setup is in progress.
|
||||||
|
// This must be done after we adjust the default_methods and
|
||||||
|
// default_vtable_indices for methods already in the vtable.
|
||||||
|
if (ik->vtable_length() > 0 && (_the_class_oop->is_interface()
|
||||||
|
|| ik->is_subtype_of(_the_class_oop))) {
|
||||||
// ik->vtable() creates a wrapper object; rm cleans it up
|
// ik->vtable() creates a wrapper object; rm cleans it up
|
||||||
ResourceMark rm(_thread);
|
ResourceMark rm(_thread);
|
||||||
ik->vtable()->adjust_method_entries(_matching_old_methods,
|
ik->vtable()->adjust_method_entries(_matching_old_methods,
|
||||||
_matching_new_methods,
|
_matching_new_methods,
|
||||||
_matching_methods_length,
|
_matching_methods_length,
|
||||||
&trace_name_printed);
|
&trace_name_printed);
|
||||||
|
ik->adjust_default_methods(_matching_old_methods,
|
||||||
|
_matching_new_methods,
|
||||||
|
_matching_methods_length,
|
||||||
|
&trace_name_printed);
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the current class has an itable and we are either redefining an
|
// If the current class has an itable and we are either redefining an
|
||||||
|
@ -2931,7 +2944,8 @@ void VM_RedefineClasses::check_methods_and_mark_as_obsolete(
|
||||||
old_method->set_is_obsolete();
|
old_method->set_is_obsolete();
|
||||||
obsolete_count++;
|
obsolete_count++;
|
||||||
|
|
||||||
// obsolete methods need a unique idnum
|
// obsolete methods need a unique idnum so they become new entries in
|
||||||
|
// the jmethodID cache in InstanceKlass
|
||||||
u2 num = InstanceKlass::cast(_the_class_oop)->next_method_idnum();
|
u2 num = InstanceKlass::cast(_the_class_oop)->next_method_idnum();
|
||||||
if (num != ConstMethod::UNSET_IDNUM) {
|
if (num != ConstMethod::UNSET_IDNUM) {
|
||||||
old_method->set_method_idnum(num);
|
old_method->set_method_idnum(num);
|
||||||
|
|
|
@ -187,12 +187,34 @@ oop MethodHandles::init_method_MemberName(Handle mname, CallInfo& info) {
|
||||||
receiver_limit = m->method_holder();
|
receiver_limit = m->method_holder();
|
||||||
assert(receiver_limit->verify_itable_index(vmindex), "");
|
assert(receiver_limit->verify_itable_index(vmindex), "");
|
||||||
flags |= IS_METHOD | (JVM_REF_invokeInterface << REFERENCE_KIND_SHIFT);
|
flags |= IS_METHOD | (JVM_REF_invokeInterface << REFERENCE_KIND_SHIFT);
|
||||||
|
if (TraceInvokeDynamic) {
|
||||||
|
ResourceMark rm;
|
||||||
|
tty->print_cr("memberName: invokeinterface method_holder::method: %s, receiver: %s, itableindex: %d, access_flags:",
|
||||||
|
Method::name_and_sig_as_C_string(receiver_limit(), m->name(), m->signature()),
|
||||||
|
receiver_limit()->internal_name(), vmindex);
|
||||||
|
m->access_flags().print_on(tty);
|
||||||
|
if (!m->is_abstract()) {
|
||||||
|
tty->print("default");
|
||||||
|
}
|
||||||
|
tty->cr();
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CallInfo::vtable_call:
|
case CallInfo::vtable_call:
|
||||||
vmindex = info.vtable_index();
|
vmindex = info.vtable_index();
|
||||||
flags |= IS_METHOD | (JVM_REF_invokeVirtual << REFERENCE_KIND_SHIFT);
|
flags |= IS_METHOD | (JVM_REF_invokeVirtual << REFERENCE_KIND_SHIFT);
|
||||||
assert(receiver_limit->is_subtype_of(m->method_holder()), "virtual call must be type-safe");
|
assert(receiver_limit->is_subtype_of(m->method_holder()), "virtual call must be type-safe");
|
||||||
|
if (TraceInvokeDynamic) {
|
||||||
|
ResourceMark rm;
|
||||||
|
tty->print_cr("memberName: invokevirtual method_holder::method: %s, receiver: %s, vtableindex: %d, access_flags:",
|
||||||
|
Method::name_and_sig_as_C_string(receiver_limit(), m->name(), m->signature()),
|
||||||
|
receiver_limit()->internal_name(), vmindex);
|
||||||
|
m->access_flags().print_on(tty);
|
||||||
|
if (m->is_default_method()) {
|
||||||
|
tty->print("default");
|
||||||
|
}
|
||||||
|
tty->cr();
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CallInfo::direct_call:
|
case CallInfo::direct_call:
|
||||||
|
|
|
@ -129,10 +129,6 @@ extern "C" {
|
||||||
#define FN_PTR(f) CAST_FROM_FN_PTR(void*, &f)
|
#define FN_PTR(f) CAST_FROM_FN_PTR(void*, &f)
|
||||||
|
|
||||||
static JNINativeMethod lookup_special_native_methods[] = {
|
static JNINativeMethod lookup_special_native_methods[] = {
|
||||||
// Next two functions only exist for compatibility with 1.3.1 and earlier.
|
|
||||||
{ CC"Java_java_io_ObjectOutputStream_getPrimitiveFieldValues", NULL, FN_PTR(JVM_GetPrimitiveFieldValues) }, // intercept ObjectOutputStream getPrimitiveFieldValues for faster serialization
|
|
||||||
{ CC"Java_java_io_ObjectInputStream_setPrimitiveFieldValues", NULL, FN_PTR(JVM_SetPrimitiveFieldValues) }, // intercept ObjectInputStream setPrimitiveFieldValues for faster serialization
|
|
||||||
|
|
||||||
{ CC"Java_sun_misc_Unsafe_registerNatives", NULL, FN_PTR(JVM_RegisterUnsafeMethods) },
|
{ CC"Java_sun_misc_Unsafe_registerNatives", NULL, FN_PTR(JVM_RegisterUnsafeMethods) },
|
||||||
{ CC"Java_java_lang_invoke_MethodHandleNatives_registerNatives", NULL, FN_PTR(JVM_RegisterMethodHandleMethods) },
|
{ CC"Java_java_lang_invoke_MethodHandleNatives_registerNatives", NULL, FN_PTR(JVM_RegisterMethodHandleMethods) },
|
||||||
{ CC"Java_sun_misc_Perf_registerNatives", NULL, FN_PTR(JVM_RegisterPerfMethods) },
|
{ CC"Java_sun_misc_Perf_registerNatives", NULL, FN_PTR(JVM_RegisterPerfMethods) },
|
||||||
|
@ -140,9 +136,8 @@ static JNINativeMethod lookup_special_native_methods[] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
static address lookup_special_native(char* jni_name) {
|
static address lookup_special_native(char* jni_name) {
|
||||||
int i = !JDK_Version::is_gte_jdk14x_version() ? 0 : 2; // see comment in lookup_special_native_methods
|
|
||||||
int count = sizeof(lookup_special_native_methods) / sizeof(JNINativeMethod);
|
int count = sizeof(lookup_special_native_methods) / sizeof(JNINativeMethod);
|
||||||
for (; i < count; i++) {
|
for (int i = 0; i < count; i++) {
|
||||||
// NB: To ignore the jni prefix and jni postfix strstr is used matching.
|
// NB: To ignore the jni prefix and jni postfix strstr is used matching.
|
||||||
if (strstr(jni_name, lookup_special_native_methods[i].name) != NULL) {
|
if (strstr(jni_name, lookup_special_native_methods[i].name) != NULL) {
|
||||||
return CAST_FROM_FN_PTR(address, lookup_special_native_methods[i].fnPtr);
|
return CAST_FROM_FN_PTR(address, lookup_special_native_methods[i].fnPtr);
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -117,11 +117,12 @@ WB_ENTRY(jobjectArray, WB_ParseCommandLine(JNIEnv* env, jobject o, jstring j_cmd
|
||||||
|
|
||||||
const char* c_cmdline = java_lang_String::as_utf8_string(JNIHandles::resolve(j_cmdline));
|
const char* c_cmdline = java_lang_String::as_utf8_string(JNIHandles::resolve(j_cmdline));
|
||||||
objArrayOop argumentArray = objArrayOop(JNIHandles::resolve_non_null(arguments));
|
objArrayOop argumentArray = objArrayOop(JNIHandles::resolve_non_null(arguments));
|
||||||
|
objArrayHandle argumentArray_ah(THREAD, argumentArray);
|
||||||
|
|
||||||
int length = argumentArray->length();
|
int length = argumentArray_ah->length();
|
||||||
|
|
||||||
for (int i = 0; i < length; i++) {
|
for (int i = 0; i < length; i++) {
|
||||||
oop argument_oop = argumentArray->obj_at(i);
|
oop argument_oop = argumentArray_ah->obj_at(i);
|
||||||
fill_in_parser(&parser, argument_oop);
|
fill_in_parser(&parser, argument_oop);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -130,19 +131,20 @@ WB_ENTRY(jobjectArray, WB_ParseCommandLine(JNIEnv* env, jobject o, jstring j_cmd
|
||||||
|
|
||||||
Klass* k = SystemDictionary::Object_klass();
|
Klass* k = SystemDictionary::Object_klass();
|
||||||
objArrayOop returnvalue_array = oopFactory::new_objArray(k, parser.num_arguments() * 2, CHECK_NULL);
|
objArrayOop returnvalue_array = oopFactory::new_objArray(k, parser.num_arguments() * 2, CHECK_NULL);
|
||||||
|
objArrayHandle returnvalue_array_ah(THREAD, returnvalue_array);
|
||||||
|
|
||||||
GrowableArray<const char *>*parsedArgNames = parser.argument_name_array();
|
GrowableArray<const char *>*parsedArgNames = parser.argument_name_array();
|
||||||
|
|
||||||
for (int i = 0; i < parser.num_arguments(); i++) {
|
for (int i = 0; i < parser.num_arguments(); i++) {
|
||||||
oop parsedName = java_lang_String::create_oop_from_str(parsedArgNames->at(i), CHECK_NULL);
|
oop parsedName = java_lang_String::create_oop_from_str(parsedArgNames->at(i), CHECK_NULL);
|
||||||
returnvalue_array->obj_at_put(i*2, parsedName);
|
returnvalue_array_ah->obj_at_put(i*2, parsedName);
|
||||||
GenDCmdArgument* arg = parser.lookup_dcmd_option(parsedArgNames->at(i), strlen(parsedArgNames->at(i)));
|
GenDCmdArgument* arg = parser.lookup_dcmd_option(parsedArgNames->at(i), strlen(parsedArgNames->at(i)));
|
||||||
char buf[VALUE_MAXLEN];
|
char buf[VALUE_MAXLEN];
|
||||||
arg->value_as_str(buf, sizeof(buf));
|
arg->value_as_str(buf, sizeof(buf));
|
||||||
oop parsedValue = java_lang_String::create_oop_from_str(buf, CHECK_NULL);
|
oop parsedValue = java_lang_String::create_oop_from_str(buf, CHECK_NULL);
|
||||||
returnvalue_array->obj_at_put(i*2+1, parsedValue);
|
returnvalue_array_ah->obj_at_put(i*2+1, parsedValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (jobjectArray) JNIHandles::make_local(returnvalue_array);
|
return (jobjectArray) JNIHandles::make_local(returnvalue_array_ah());
|
||||||
|
|
||||||
WB_END
|
WB_END
|
||||||
|
|
|
@ -2045,6 +2045,9 @@ bool Arguments::check_vm_args_consistency() {
|
||||||
status = status && verify_interval(StringTableSize, minimumStringTableSize,
|
status = status && verify_interval(StringTableSize, minimumStringTableSize,
|
||||||
(max_uintx / StringTable::bucket_size()), "StringTable size");
|
(max_uintx / StringTable::bucket_size()), "StringTable size");
|
||||||
|
|
||||||
|
status = status && verify_interval(SymbolTableSize, minimumSymbolTableSize,
|
||||||
|
(max_uintx / SymbolTable::bucket_size()), "SymbolTable size");
|
||||||
|
|
||||||
if (MinHeapFreeRatio > MaxHeapFreeRatio) {
|
if (MinHeapFreeRatio > MaxHeapFreeRatio) {
|
||||||
jio_fprintf(defaultStream::error_stream(),
|
jio_fprintf(defaultStream::error_stream(),
|
||||||
"MinHeapFreeRatio (" UINTX_FORMAT ") must be less than or "
|
"MinHeapFreeRatio (" UINTX_FORMAT ") must be less than or "
|
||||||
|
@ -2654,16 +2657,16 @@ jint Arguments::parse_each_vm_init_arg(const JavaVMInitArgs* args,
|
||||||
FLAG_SET_CMDLINE(bool, BackgroundCompilation, false);
|
FLAG_SET_CMDLINE(bool, BackgroundCompilation, false);
|
||||||
// -Xmn for compatibility with other JVM vendors
|
// -Xmn for compatibility with other JVM vendors
|
||||||
} else if (match_option(option, "-Xmn", &tail)) {
|
} else if (match_option(option, "-Xmn", &tail)) {
|
||||||
julong long_initial_eden_size = 0;
|
julong long_initial_young_size = 0;
|
||||||
ArgsRange errcode = parse_memory_size(tail, &long_initial_eden_size, 1);
|
ArgsRange errcode = parse_memory_size(tail, &long_initial_young_size, 1);
|
||||||
if (errcode != arg_in_range) {
|
if (errcode != arg_in_range) {
|
||||||
jio_fprintf(defaultStream::error_stream(),
|
jio_fprintf(defaultStream::error_stream(),
|
||||||
"Invalid initial eden size: %s\n", option->optionString);
|
"Invalid initial young generation size: %s\n", option->optionString);
|
||||||
describe_range_error(errcode);
|
describe_range_error(errcode);
|
||||||
return JNI_EINVAL;
|
return JNI_EINVAL;
|
||||||
}
|
}
|
||||||
FLAG_SET_CMDLINE(uintx, MaxNewSize, (uintx)long_initial_eden_size);
|
FLAG_SET_CMDLINE(uintx, MaxNewSize, (uintx)long_initial_young_size);
|
||||||
FLAG_SET_CMDLINE(uintx, NewSize, (uintx)long_initial_eden_size);
|
FLAG_SET_CMDLINE(uintx, NewSize, (uintx)long_initial_young_size);
|
||||||
// -Xms
|
// -Xms
|
||||||
} else if (match_option(option, "-Xms", &tail)) {
|
} else if (match_option(option, "-Xms", &tail)) {
|
||||||
julong long_initial_heap_size = 0;
|
julong long_initial_heap_size = 0;
|
||||||
|
@ -3663,6 +3666,9 @@ jint Arguments::apply_ergo() {
|
||||||
assert(verify_serial_gc_flags(), "SerialGC unset");
|
assert(verify_serial_gc_flags(), "SerialGC unset");
|
||||||
#endif // INCLUDE_ALL_GCS
|
#endif // INCLUDE_ALL_GCS
|
||||||
|
|
||||||
|
// Initialize Metaspace flags and alignments.
|
||||||
|
Metaspace::ergo_initialize();
|
||||||
|
|
||||||
// Set bytecode rewriting flags
|
// Set bytecode rewriting flags
|
||||||
set_bytecode_flags();
|
set_bytecode_flags();
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -27,8 +27,11 @@
|
||||||
#include "memory/universe.inline.hpp"
|
#include "memory/universe.inline.hpp"
|
||||||
#include "runtime/reflectionUtils.hpp"
|
#include "runtime/reflectionUtils.hpp"
|
||||||
|
|
||||||
KlassStream::KlassStream(instanceKlassHandle klass, bool local_only, bool classes_only) {
|
KlassStream::KlassStream(instanceKlassHandle klass, bool local_only,
|
||||||
_klass = klass;
|
bool classes_only, bool walk_defaults) {
|
||||||
|
_klass = _base_klass = klass;
|
||||||
|
_base_class_search_defaults = false;
|
||||||
|
_defaults_checked = false;
|
||||||
if (classes_only) {
|
if (classes_only) {
|
||||||
_interfaces = Universe::the_empty_klass_array();
|
_interfaces = Universe::the_empty_klass_array();
|
||||||
} else {
|
} else {
|
||||||
|
@ -37,6 +40,7 @@ KlassStream::KlassStream(instanceKlassHandle klass, bool local_only, bool classe
|
||||||
_interface_index = _interfaces->length();
|
_interface_index = _interfaces->length();
|
||||||
_local_only = local_only;
|
_local_only = local_only;
|
||||||
_classes_only = classes_only;
|
_classes_only = classes_only;
|
||||||
|
_walk_defaults = walk_defaults;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool KlassStream::eos() {
|
bool KlassStream::eos() {
|
||||||
|
@ -45,7 +49,13 @@ bool KlassStream::eos() {
|
||||||
if (!_klass->is_interface() && _klass->super() != NULL) {
|
if (!_klass->is_interface() && _klass->super() != NULL) {
|
||||||
// go up superclass chain (not for interfaces)
|
// go up superclass chain (not for interfaces)
|
||||||
_klass = _klass->super();
|
_klass = _klass->super();
|
||||||
|
// Next for method walks, walk default methods
|
||||||
|
} else if (_walk_defaults && (_defaults_checked == false) && (_base_klass->default_methods() != NULL)) {
|
||||||
|
_base_class_search_defaults = true;
|
||||||
|
_klass = _base_klass;
|
||||||
|
_defaults_checked = true;
|
||||||
} else {
|
} else {
|
||||||
|
// Next walk transitive interfaces
|
||||||
if (_interface_index > 0) {
|
if (_interface_index > 0) {
|
||||||
_klass = _interfaces->at(--_interface_index);
|
_klass = _interfaces->at(--_interface_index);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -38,7 +38,7 @@
|
||||||
// and (super)interfaces. Streaming is done in reverse order (subclasses first,
|
// and (super)interfaces. Streaming is done in reverse order (subclasses first,
|
||||||
// interfaces last).
|
// interfaces last).
|
||||||
//
|
//
|
||||||
// for (KlassStream st(k, false, false); !st.eos(); st.next()) {
|
// for (KlassStream st(k, false, false, false); !st.eos(); st.next()) {
|
||||||
// Klass* k = st.klass();
|
// Klass* k = st.klass();
|
||||||
// ...
|
// ...
|
||||||
// }
|
// }
|
||||||
|
@ -46,17 +46,21 @@
|
||||||
class KlassStream VALUE_OBJ_CLASS_SPEC {
|
class KlassStream VALUE_OBJ_CLASS_SPEC {
|
||||||
protected:
|
protected:
|
||||||
instanceKlassHandle _klass; // current klass/interface iterated over
|
instanceKlassHandle _klass; // current klass/interface iterated over
|
||||||
|
instanceKlassHandle _base_klass; // initial klass/interface to iterate over
|
||||||
Array<Klass*>* _interfaces; // transitive interfaces for initial class
|
Array<Klass*>* _interfaces; // transitive interfaces for initial class
|
||||||
int _interface_index; // current interface being processed
|
int _interface_index; // current interface being processed
|
||||||
bool _local_only; // process initial class/interface only
|
bool _local_only; // process initial class/interface only
|
||||||
bool _classes_only; // process classes only (no interfaces)
|
bool _classes_only; // process classes only (no interfaces)
|
||||||
|
bool _walk_defaults; // process default methods
|
||||||
|
bool _base_class_search_defaults; // time to process default methods
|
||||||
|
bool _defaults_checked; // already checked for default methods
|
||||||
int _index;
|
int _index;
|
||||||
|
|
||||||
virtual int length() const = 0;
|
virtual int length() = 0;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// constructor
|
// constructor
|
||||||
KlassStream(instanceKlassHandle klass, bool local_only, bool classes_only);
|
KlassStream(instanceKlassHandle klass, bool local_only, bool classes_only, bool walk_defaults);
|
||||||
|
|
||||||
// testing
|
// testing
|
||||||
bool eos();
|
bool eos();
|
||||||
|
@ -67,6 +71,8 @@ class KlassStream VALUE_OBJ_CLASS_SPEC {
|
||||||
// accessors
|
// accessors
|
||||||
instanceKlassHandle klass() const { return _klass; }
|
instanceKlassHandle klass() const { return _klass; }
|
||||||
int index() const { return _index; }
|
int index() const { return _index; }
|
||||||
|
bool base_class_search_defaults() const { return _base_class_search_defaults; }
|
||||||
|
void base_class_search_defaults(bool b) { _base_class_search_defaults = b; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -81,17 +87,24 @@ class KlassStream VALUE_OBJ_CLASS_SPEC {
|
||||||
|
|
||||||
class MethodStream : public KlassStream {
|
class MethodStream : public KlassStream {
|
||||||
private:
|
private:
|
||||||
int length() const { return methods()->length(); }
|
int length() { return methods()->length(); }
|
||||||
Array<Method*>* methods() const { return _klass->methods(); }
|
Array<Method*>* methods() {
|
||||||
|
if (base_class_search_defaults()) {
|
||||||
|
base_class_search_defaults(false);
|
||||||
|
return _klass->default_methods();
|
||||||
|
} else {
|
||||||
|
return _klass->methods();
|
||||||
|
}
|
||||||
|
}
|
||||||
public:
|
public:
|
||||||
MethodStream(instanceKlassHandle klass, bool local_only, bool classes_only)
|
MethodStream(instanceKlassHandle klass, bool local_only, bool classes_only)
|
||||||
: KlassStream(klass, local_only, classes_only) {
|
: KlassStream(klass, local_only, classes_only, true) {
|
||||||
_index = length();
|
_index = length();
|
||||||
next();
|
next();
|
||||||
}
|
}
|
||||||
|
|
||||||
void next() { _index--; }
|
void next() { _index--; }
|
||||||
Method* method() const { return methods()->at(index()); }
|
Method* method() { return methods()->at(index()); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -107,13 +120,13 @@ class MethodStream : public KlassStream {
|
||||||
|
|
||||||
class FieldStream : public KlassStream {
|
class FieldStream : public KlassStream {
|
||||||
private:
|
private:
|
||||||
int length() const { return _klass->java_fields_count(); }
|
int length() { return _klass->java_fields_count(); }
|
||||||
|
|
||||||
fieldDescriptor _fd_buf;
|
fieldDescriptor _fd_buf;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
FieldStream(instanceKlassHandle klass, bool local_only, bool classes_only)
|
FieldStream(instanceKlassHandle klass, bool local_only, bool classes_only)
|
||||||
: KlassStream(klass, local_only, classes_only) {
|
: KlassStream(klass, local_only, classes_only, false) {
|
||||||
_index = length();
|
_index = length();
|
||||||
next();
|
next();
|
||||||
}
|
}
|
||||||
|
|
|
@ -368,8 +368,15 @@ VirtualSpace::VirtualSpace() {
|
||||||
|
|
||||||
|
|
||||||
bool VirtualSpace::initialize(ReservedSpace rs, size_t committed_size) {
|
bool VirtualSpace::initialize(ReservedSpace rs, size_t committed_size) {
|
||||||
|
const size_t max_commit_granularity = os::page_size_for_region(rs.size(), rs.size(), 1);
|
||||||
|
return initialize_with_granularity(rs, committed_size, max_commit_granularity);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool VirtualSpace::initialize_with_granularity(ReservedSpace rs, size_t committed_size, size_t max_commit_granularity) {
|
||||||
if(!rs.is_reserved()) return false; // allocation failed.
|
if(!rs.is_reserved()) return false; // allocation failed.
|
||||||
assert(_low_boundary == NULL, "VirtualSpace already initialized");
|
assert(_low_boundary == NULL, "VirtualSpace already initialized");
|
||||||
|
assert(max_commit_granularity > 0, "Granularity must be non-zero.");
|
||||||
|
|
||||||
_low_boundary = rs.base();
|
_low_boundary = rs.base();
|
||||||
_high_boundary = low_boundary() + rs.size();
|
_high_boundary = low_boundary() + rs.size();
|
||||||
|
|
||||||
|
@ -390,7 +397,7 @@ bool VirtualSpace::initialize(ReservedSpace rs, size_t committed_size) {
|
||||||
// No attempt is made to force large page alignment at the very top and
|
// No attempt is made to force large page alignment at the very top and
|
||||||
// bottom of the space if they are not aligned so already.
|
// bottom of the space if they are not aligned so already.
|
||||||
_lower_alignment = os::vm_page_size();
|
_lower_alignment = os::vm_page_size();
|
||||||
_middle_alignment = os::page_size_for_region(rs.size(), rs.size(), 1);
|
_middle_alignment = max_commit_granularity;
|
||||||
_upper_alignment = os::vm_page_size();
|
_upper_alignment = os::vm_page_size();
|
||||||
|
|
||||||
// End of each region
|
// End of each region
|
||||||
|
@ -966,17 +973,52 @@ void TestReservedSpace_test() {
|
||||||
|
|
||||||
|
|
||||||
class TestVirtualSpace : AllStatic {
|
class TestVirtualSpace : AllStatic {
|
||||||
|
enum TestLargePages {
|
||||||
|
Default,
|
||||||
|
Disable,
|
||||||
|
Reserve,
|
||||||
|
Commit
|
||||||
|
};
|
||||||
|
|
||||||
|
static ReservedSpace reserve_memory(size_t reserve_size_aligned, TestLargePages mode) {
|
||||||
|
switch(mode) {
|
||||||
|
default:
|
||||||
|
case Default:
|
||||||
|
case Reserve:
|
||||||
|
return ReservedSpace(reserve_size_aligned);
|
||||||
|
case Disable:
|
||||||
|
case Commit:
|
||||||
|
return ReservedSpace(reserve_size_aligned,
|
||||||
|
os::vm_allocation_granularity(),
|
||||||
|
/* large */ false, /* exec */ false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool initialize_virtual_space(VirtualSpace& vs, ReservedSpace rs, TestLargePages mode) {
|
||||||
|
switch(mode) {
|
||||||
|
default:
|
||||||
|
case Default:
|
||||||
|
case Reserve:
|
||||||
|
return vs.initialize(rs, 0);
|
||||||
|
case Disable:
|
||||||
|
return vs.initialize_with_granularity(rs, 0, os::vm_page_size());
|
||||||
|
case Commit:
|
||||||
|
return vs.initialize_with_granularity(rs, 0, os::page_size_for_region(rs.size(), rs.size(), 1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static void test_virtual_space_actual_committed_space(size_t reserve_size, size_t commit_size) {
|
static void test_virtual_space_actual_committed_space(size_t reserve_size, size_t commit_size,
|
||||||
|
TestLargePages mode = Default) {
|
||||||
size_t granularity = os::vm_allocation_granularity();
|
size_t granularity = os::vm_allocation_granularity();
|
||||||
size_t reserve_size_aligned = align_size_up(reserve_size, granularity);
|
size_t reserve_size_aligned = align_size_up(reserve_size, granularity);
|
||||||
|
|
||||||
ReservedSpace reserved(reserve_size_aligned);
|
ReservedSpace reserved = reserve_memory(reserve_size_aligned, mode);
|
||||||
|
|
||||||
assert(reserved.is_reserved(), "Must be");
|
assert(reserved.is_reserved(), "Must be");
|
||||||
|
|
||||||
VirtualSpace vs;
|
VirtualSpace vs;
|
||||||
bool initialized = vs.initialize(reserved, 0);
|
bool initialized = initialize_virtual_space(vs, reserved, mode);
|
||||||
assert(initialized, "Failed to initialize VirtualSpace");
|
assert(initialized, "Failed to initialize VirtualSpace");
|
||||||
|
|
||||||
vs.expand_by(commit_size, false);
|
vs.expand_by(commit_size, false);
|
||||||
|
@ -986,7 +1028,10 @@ class TestVirtualSpace : AllStatic {
|
||||||
} else {
|
} else {
|
||||||
assert_ge(vs.actual_committed_size(), commit_size);
|
assert_ge(vs.actual_committed_size(), commit_size);
|
||||||
// Approximate the commit granularity.
|
// Approximate the commit granularity.
|
||||||
size_t commit_granularity = UseLargePages ? os::large_page_size() : os::vm_page_size();
|
// Make sure that we don't commit using large pages
|
||||||
|
// if large pages has been disabled for this VirtualSpace.
|
||||||
|
size_t commit_granularity = (mode == Disable || !UseLargePages) ?
|
||||||
|
os::vm_page_size() : os::large_page_size();
|
||||||
assert_lt(vs.actual_committed_size(), commit_size + commit_granularity);
|
assert_lt(vs.actual_committed_size(), commit_size + commit_granularity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1042,9 +1087,40 @@ class TestVirtualSpace : AllStatic {
|
||||||
test_virtual_space_actual_committed_space(10 * M, 10 * M);
|
test_virtual_space_actual_committed_space(10 * M, 10 * M);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void test_virtual_space_disable_large_pages() {
|
||||||
|
if (!UseLargePages) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// These test cases verify that if we force VirtualSpace to disable large pages
|
||||||
|
test_virtual_space_actual_committed_space(10 * M, 0, Disable);
|
||||||
|
test_virtual_space_actual_committed_space(10 * M, 4 * K, Disable);
|
||||||
|
test_virtual_space_actual_committed_space(10 * M, 8 * K, Disable);
|
||||||
|
test_virtual_space_actual_committed_space(10 * M, 1 * M, Disable);
|
||||||
|
test_virtual_space_actual_committed_space(10 * M, 2 * M, Disable);
|
||||||
|
test_virtual_space_actual_committed_space(10 * M, 5 * M, Disable);
|
||||||
|
test_virtual_space_actual_committed_space(10 * M, 10 * M, Disable);
|
||||||
|
|
||||||
|
test_virtual_space_actual_committed_space(10 * M, 0, Reserve);
|
||||||
|
test_virtual_space_actual_committed_space(10 * M, 4 * K, Reserve);
|
||||||
|
test_virtual_space_actual_committed_space(10 * M, 8 * K, Reserve);
|
||||||
|
test_virtual_space_actual_committed_space(10 * M, 1 * M, Reserve);
|
||||||
|
test_virtual_space_actual_committed_space(10 * M, 2 * M, Reserve);
|
||||||
|
test_virtual_space_actual_committed_space(10 * M, 5 * M, Reserve);
|
||||||
|
test_virtual_space_actual_committed_space(10 * M, 10 * M, Reserve);
|
||||||
|
|
||||||
|
test_virtual_space_actual_committed_space(10 * M, 0, Commit);
|
||||||
|
test_virtual_space_actual_committed_space(10 * M, 4 * K, Commit);
|
||||||
|
test_virtual_space_actual_committed_space(10 * M, 8 * K, Commit);
|
||||||
|
test_virtual_space_actual_committed_space(10 * M, 1 * M, Commit);
|
||||||
|
test_virtual_space_actual_committed_space(10 * M, 2 * M, Commit);
|
||||||
|
test_virtual_space_actual_committed_space(10 * M, 5 * M, Commit);
|
||||||
|
test_virtual_space_actual_committed_space(10 * M, 10 * M, Commit);
|
||||||
|
}
|
||||||
|
|
||||||
static void test_virtual_space() {
|
static void test_virtual_space() {
|
||||||
test_virtual_space_actual_committed_space();
|
test_virtual_space_actual_committed_space();
|
||||||
test_virtual_space_actual_committed_space_one_large_page();
|
test_virtual_space_actual_committed_space_one_large_page();
|
||||||
|
test_virtual_space_disable_large_pages();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -178,6 +178,7 @@ class VirtualSpace VALUE_OBJ_CLASS_SPEC {
|
||||||
public:
|
public:
|
||||||
// Initialization
|
// Initialization
|
||||||
VirtualSpace();
|
VirtualSpace();
|
||||||
|
bool initialize_with_granularity(ReservedSpace rs, size_t committed_byte_size, size_t max_commit_ganularity);
|
||||||
bool initialize(ReservedSpace rs, size_t committed_byte_size);
|
bool initialize(ReservedSpace rs, size_t committed_byte_size);
|
||||||
|
|
||||||
// Destruction
|
// Destruction
|
||||||
|
|
|
@ -27,7 +27,6 @@
|
||||||
#include "classfile/javaClasses.hpp"
|
#include "classfile/javaClasses.hpp"
|
||||||
#include "classfile/loaderConstraints.hpp"
|
#include "classfile/loaderConstraints.hpp"
|
||||||
#include "classfile/placeholders.hpp"
|
#include "classfile/placeholders.hpp"
|
||||||
#include "classfile/symbolTable.hpp"
|
|
||||||
#include "classfile/systemDictionary.hpp"
|
#include "classfile/systemDictionary.hpp"
|
||||||
#include "ci/ciField.hpp"
|
#include "ci/ciField.hpp"
|
||||||
#include "ci/ciInstance.hpp"
|
#include "ci/ciInstance.hpp"
|
||||||
|
@ -289,6 +288,7 @@ typedef BinaryTreeDictionary<Metablock, FreeList> MetablockTreeDictionary;
|
||||||
nonstatic_field(ConstantPoolCache, _constant_pool, ConstantPool*) \
|
nonstatic_field(ConstantPoolCache, _constant_pool, ConstantPool*) \
|
||||||
nonstatic_field(InstanceKlass, _array_klasses, Klass*) \
|
nonstatic_field(InstanceKlass, _array_klasses, Klass*) \
|
||||||
nonstatic_field(InstanceKlass, _methods, Array<Method*>*) \
|
nonstatic_field(InstanceKlass, _methods, Array<Method*>*) \
|
||||||
|
nonstatic_field(InstanceKlass, _default_methods, Array<Method*>*) \
|
||||||
nonstatic_field(InstanceKlass, _local_interfaces, Array<Klass*>*) \
|
nonstatic_field(InstanceKlass, _local_interfaces, Array<Klass*>*) \
|
||||||
nonstatic_field(InstanceKlass, _transitive_interfaces, Array<Klass*>*) \
|
nonstatic_field(InstanceKlass, _transitive_interfaces, Array<Klass*>*) \
|
||||||
nonstatic_field(InstanceKlass, _fields, Array<u2>*) \
|
nonstatic_field(InstanceKlass, _fields, Array<u2>*) \
|
||||||
|
@ -323,6 +323,7 @@ typedef BinaryTreeDictionary<Metablock, FreeList> MetablockTreeDictionary;
|
||||||
nonstatic_field(nmethodBucket, _count, int) \
|
nonstatic_field(nmethodBucket, _count, int) \
|
||||||
nonstatic_field(nmethodBucket, _next, nmethodBucket*) \
|
nonstatic_field(nmethodBucket, _next, nmethodBucket*) \
|
||||||
nonstatic_field(InstanceKlass, _method_ordering, Array<int>*) \
|
nonstatic_field(InstanceKlass, _method_ordering, Array<int>*) \
|
||||||
|
nonstatic_field(InstanceKlass, _default_vtable_indices, Array<int>*) \
|
||||||
nonstatic_field(Klass, _super_check_offset, juint) \
|
nonstatic_field(Klass, _super_check_offset, juint) \
|
||||||
nonstatic_field(Klass, _secondary_super_cache, Klass*) \
|
nonstatic_field(Klass, _secondary_super_cache, Klass*) \
|
||||||
nonstatic_field(Klass, _secondary_supers, Array<Klass*>*) \
|
nonstatic_field(Klass, _secondary_supers, Array<Klass*>*) \
|
||||||
|
@ -715,11 +716,17 @@ typedef BinaryTreeDictionary<Metablock, FreeList> MetablockTreeDictionary;
|
||||||
nonstatic_field(PlaceholderEntry, _loader_data, ClassLoaderData*) \
|
nonstatic_field(PlaceholderEntry, _loader_data, ClassLoaderData*) \
|
||||||
\
|
\
|
||||||
/**************************/ \
|
/**************************/ \
|
||||||
/* ProctectionDomainEntry */ \
|
/* ProtectionDomainEntry */ \
|
||||||
/**************************/ \
|
/**************************/ \
|
||||||
\
|
\
|
||||||
nonstatic_field(ProtectionDomainEntry, _next, ProtectionDomainEntry*) \
|
nonstatic_field(ProtectionDomainEntry, _next, ProtectionDomainEntry*) \
|
||||||
nonstatic_field(ProtectionDomainEntry, _protection_domain, oop) \
|
nonstatic_field(ProtectionDomainEntry, _pd_cache, ProtectionDomainCacheEntry*) \
|
||||||
|
\
|
||||||
|
/*******************************/ \
|
||||||
|
/* ProtectionDomainCacheEntry */ \
|
||||||
|
/*******************************/ \
|
||||||
|
\
|
||||||
|
nonstatic_field(ProtectionDomainCacheEntry, _literal, oop) \
|
||||||
\
|
\
|
||||||
/*************************/ \
|
/*************************/ \
|
||||||
/* LoaderConstraintEntry */ \
|
/* LoaderConstraintEntry */ \
|
||||||
|
@ -1562,6 +1569,7 @@ typedef BinaryTreeDictionary<Metablock, FreeList> MetablockTreeDictionary;
|
||||||
declare_toplevel_type(SystemDictionary) \
|
declare_toplevel_type(SystemDictionary) \
|
||||||
declare_toplevel_type(vmSymbols) \
|
declare_toplevel_type(vmSymbols) \
|
||||||
declare_toplevel_type(ProtectionDomainEntry) \
|
declare_toplevel_type(ProtectionDomainEntry) \
|
||||||
|
declare_toplevel_type(ProtectionDomainCacheEntry) \
|
||||||
\
|
\
|
||||||
declare_toplevel_type(GenericGrowableArray) \
|
declare_toplevel_type(GenericGrowableArray) \
|
||||||
declare_toplevel_type(GrowableArray<int>) \
|
declare_toplevel_type(GrowableArray<int>) \
|
||||||
|
@ -2247,12 +2255,6 @@ typedef BinaryTreeDictionary<Metablock, FreeList> MetablockTreeDictionary;
|
||||||
declare_preprocessor_constant("PERFDATA_BIG_ENDIAN", PERFDATA_BIG_ENDIAN) \
|
declare_preprocessor_constant("PERFDATA_BIG_ENDIAN", PERFDATA_BIG_ENDIAN) \
|
||||||
declare_preprocessor_constant("PERFDATA_LITTLE_ENDIAN", PERFDATA_LITTLE_ENDIAN) \
|
declare_preprocessor_constant("PERFDATA_LITTLE_ENDIAN", PERFDATA_LITTLE_ENDIAN) \
|
||||||
\
|
\
|
||||||
/***************/ \
|
|
||||||
/* SymbolTable */ \
|
|
||||||
/***************/ \
|
|
||||||
\
|
|
||||||
declare_constant(SymbolTable::symbol_table_size) \
|
|
||||||
\
|
|
||||||
/***********************************/ \
|
/***********************************/ \
|
||||||
/* LoaderConstraintTable constants */ \
|
/* LoaderConstraintTable constants */ \
|
||||||
/***********************************/ \
|
/***********************************/ \
|
||||||
|
|
|
@ -148,6 +148,12 @@ public:
|
||||||
static void track_code_cache_memory_usage() {
|
static void track_code_cache_memory_usage() {
|
||||||
track_memory_pool_usage(_code_heap_pool);
|
track_memory_pool_usage(_code_heap_pool);
|
||||||
}
|
}
|
||||||
|
static void track_metaspace_memory_usage() {
|
||||||
|
track_memory_pool_usage(_metaspace_pool);
|
||||||
|
}
|
||||||
|
static void track_compressed_class_memory_usage() {
|
||||||
|
track_memory_pool_usage(_compressed_class_pool);
|
||||||
|
}
|
||||||
static void track_memory_pool_usage(MemoryPool* pool);
|
static void track_memory_pool_usage(MemoryPool* pool);
|
||||||
|
|
||||||
static void gc_begin(bool fullGC, bool recordGCBeginTime,
|
static void gc_begin(bool fullGC, bool recordGCBeginTime,
|
||||||
|
|
|
@ -326,6 +326,9 @@ typedef jlong s8;
|
||||||
|
|
||||||
const int max_method_code_size = 64*K - 1; // JVM spec, 2nd ed. section 4.8.1 (p.134)
|
const int max_method_code_size = 64*K - 1; // JVM spec, 2nd ed. section 4.8.1 (p.134)
|
||||||
|
|
||||||
|
// Default ProtectionDomainCacheSize values
|
||||||
|
|
||||||
|
const int defaultProtectionDomainCacheSize = NOT_LP64(137) LP64_ONLY(2017);
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------
|
||||||
// Default and minimum StringTableSize values
|
// Default and minimum StringTableSize values
|
||||||
|
@ -333,6 +336,9 @@ const int max_method_code_size = 64*K - 1; // JVM spec, 2nd ed. section 4.8.1 (
|
||||||
const int defaultStringTableSize = NOT_LP64(1009) LP64_ONLY(60013);
|
const int defaultStringTableSize = NOT_LP64(1009) LP64_ONLY(60013);
|
||||||
const int minimumStringTableSize = 1009;
|
const int minimumStringTableSize = 1009;
|
||||||
|
|
||||||
|
const int defaultSymbolTableSize = 20011;
|
||||||
|
const int minimumSymbolTableSize = 1009;
|
||||||
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------
|
||||||
// HotSwap - for JVMTI aka Class File Replacement and PopFrame
|
// HotSwap - for JVMTI aka Class File Replacement and PopFrame
|
||||||
|
|
|
@ -65,7 +65,6 @@ needs_jdk = \
|
||||||
gc/metaspace/CompressedClassSpaceSizeInJmapHeap.java \
|
gc/metaspace/CompressedClassSpaceSizeInJmapHeap.java \
|
||||||
gc/metaspace/TestMetaspacePerfCounters.java \
|
gc/metaspace/TestMetaspacePerfCounters.java \
|
||||||
runtime/6819213/TestBootNativeLibraryPath.java \
|
runtime/6819213/TestBootNativeLibraryPath.java \
|
||||||
runtime/6878713/Test6878713.sh \
|
|
||||||
runtime/6925573/SortMethodsTest.java \
|
runtime/6925573/SortMethodsTest.java \
|
||||||
runtime/7107135/Test7107135.sh \
|
runtime/7107135/Test7107135.sh \
|
||||||
runtime/7158988/FieldMonitor.java \
|
runtime/7158988/FieldMonitor.java \
|
||||||
|
@ -85,7 +84,9 @@ needs_jdk = \
|
||||||
runtime/NMT/VirtualAllocTestType.java \
|
runtime/NMT/VirtualAllocTestType.java \
|
||||||
runtime/RedefineObject/TestRedefineObject.java \
|
runtime/RedefineObject/TestRedefineObject.java \
|
||||||
runtime/XCheckJniJsig/XCheckJSig.java \
|
runtime/XCheckJniJsig/XCheckJSig.java \
|
||||||
serviceability/attach/AttachWithStalePidFile.java
|
serviceability/attach/AttachWithStalePidFile.java \
|
||||||
|
serviceability/sa/jmap-hprof/JMapHProfLargeHeapTest.java
|
||||||
|
|
||||||
|
|
||||||
# JRE adds further tests to compact3
|
# JRE adds further tests to compact3
|
||||||
#
|
#
|
||||||
|
|
|
@ -1,3 +1,25 @@
|
||||||
|
# Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
#
|
||||||
|
# This code is free software; you can redistribute it and/or modify it
|
||||||
|
# under the terms of the GNU General Public License version 2 only, as
|
||||||
|
# published by the Free Software Foundation.
|
||||||
|
#
|
||||||
|
# This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
# version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
# accompanied this code).
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License version
|
||||||
|
# 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
#
|
||||||
|
# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
# or visit www.oracle.com if you need additional information or have any
|
||||||
|
# questions.
|
||||||
|
#
|
||||||
|
|
||||||
# @test
|
# @test
|
||||||
# @bug 6888954
|
# @bug 6888954
|
||||||
# @bug 8015884
|
# @bug 8015884
|
||||||
|
@ -63,6 +85,7 @@ do
|
||||||
[ $i -lt 10 ] && i2=0$i
|
[ $i -lt 10 ] && i2=0$i
|
||||||
|
|
||||||
"$TESTJAVA/bin/java" $TESTVMOPTS -XX:+IgnoreUnrecognizedVMOptions \
|
"$TESTJAVA/bin/java" $TESTVMOPTS -XX:+IgnoreUnrecognizedVMOptions \
|
||||||
|
-XX:-TransmitErrorReport \
|
||||||
-XX:ErrorHandlerTest=${i} -version > ${i2}.out 2>&1
|
-XX:ErrorHandlerTest=${i} -version > ${i2}.out 2>&1
|
||||||
|
|
||||||
# If ErrorHandlerTest is ignored (product build), stop.
|
# If ErrorHandlerTest is ignored (product build), stop.
|
||||||
|
|
389
hotspot/test/runtime/memory/LargePages/TestLargePagesFlags.java
Normal file
389
hotspot/test/runtime/memory/LargePages/TestLargePagesFlags.java
Normal file
|
@ -0,0 +1,389 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* @test TestLargePagesFlags
|
||||||
|
* @summary Tests how large pages are choosen depending on the given large pages flag combinations.
|
||||||
|
* @library /testlibrary
|
||||||
|
* @run main TestLargePagesFlags
|
||||||
|
*/
|
||||||
|
|
||||||
|
import com.oracle.java.testlibrary.OutputAnalyzer;
|
||||||
|
import com.oracle.java.testlibrary.Platform;
|
||||||
|
import com.oracle.java.testlibrary.ProcessTools;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
public class TestLargePagesFlags {
|
||||||
|
|
||||||
|
public static void main(String [] args) throws Exception {
|
||||||
|
if (!Platform.isLinux()) {
|
||||||
|
System.out.println("Skipping. TestLargePagesFlags has only been implemented for Linux.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
testUseTransparentHugePages();
|
||||||
|
testUseHugeTLBFS();
|
||||||
|
testUseSHM();
|
||||||
|
testCombinations();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void testUseTransparentHugePages() throws Exception {
|
||||||
|
if (!canUse(UseTransparentHugePages(true))) {
|
||||||
|
System.out.println("Skipping testUseTransparentHugePages");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// -XX:-UseLargePages overrides all other flags.
|
||||||
|
new FlagTester()
|
||||||
|
.use(UseLargePages(false),
|
||||||
|
UseTransparentHugePages(true))
|
||||||
|
.expect(
|
||||||
|
UseLargePages(false),
|
||||||
|
UseTransparentHugePages(false),
|
||||||
|
UseHugeTLBFS(false),
|
||||||
|
UseSHM(false));
|
||||||
|
|
||||||
|
// Explicitly turn on UseTransparentHugePages.
|
||||||
|
new FlagTester()
|
||||||
|
.use(UseTransparentHugePages(true))
|
||||||
|
.expect(
|
||||||
|
UseLargePages(true),
|
||||||
|
UseTransparentHugePages(true),
|
||||||
|
UseHugeTLBFS(false),
|
||||||
|
UseSHM(false));
|
||||||
|
|
||||||
|
new FlagTester()
|
||||||
|
.use(UseLargePages(true),
|
||||||
|
UseTransparentHugePages(true))
|
||||||
|
.expect(
|
||||||
|
UseLargePages(true),
|
||||||
|
UseTransparentHugePages(true),
|
||||||
|
UseHugeTLBFS(false),
|
||||||
|
UseSHM(false));
|
||||||
|
|
||||||
|
// Setting a specific large pages flag will turn
|
||||||
|
// off heuristics to choose large pages type.
|
||||||
|
new FlagTester()
|
||||||
|
.use(UseLargePages(true),
|
||||||
|
UseTransparentHugePages(false))
|
||||||
|
.expect(
|
||||||
|
UseLargePages(false),
|
||||||
|
UseTransparentHugePages(false),
|
||||||
|
UseHugeTLBFS(false),
|
||||||
|
UseSHM(false));
|
||||||
|
|
||||||
|
// Don't turn on UseTransparentHugePages
|
||||||
|
// unless the user explicitly asks for them.
|
||||||
|
new FlagTester()
|
||||||
|
.use(UseLargePages(true))
|
||||||
|
.expect(
|
||||||
|
UseTransparentHugePages(false));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void testUseHugeTLBFS() throws Exception {
|
||||||
|
if (!canUse(UseHugeTLBFS(true))) {
|
||||||
|
System.out.println("Skipping testUseHugeTLBFS");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// -XX:-UseLargePages overrides all other flags.
|
||||||
|
new FlagTester()
|
||||||
|
.use(UseLargePages(false),
|
||||||
|
UseHugeTLBFS(true))
|
||||||
|
.expect(
|
||||||
|
UseLargePages(false),
|
||||||
|
UseTransparentHugePages(false),
|
||||||
|
UseHugeTLBFS(false),
|
||||||
|
UseSHM(false));
|
||||||
|
|
||||||
|
// Explicitly turn on UseHugeTLBFS.
|
||||||
|
new FlagTester()
|
||||||
|
.use(UseHugeTLBFS(true))
|
||||||
|
.expect(
|
||||||
|
UseLargePages(true),
|
||||||
|
UseTransparentHugePages(false),
|
||||||
|
UseHugeTLBFS(true),
|
||||||
|
UseSHM(false));
|
||||||
|
|
||||||
|
new FlagTester()
|
||||||
|
.use(UseLargePages(true),
|
||||||
|
UseHugeTLBFS(true))
|
||||||
|
.expect(
|
||||||
|
UseLargePages(true),
|
||||||
|
UseTransparentHugePages(false),
|
||||||
|
UseHugeTLBFS(true),
|
||||||
|
UseSHM(false));
|
||||||
|
|
||||||
|
// Setting a specific large pages flag will turn
|
||||||
|
// off heuristics to choose large pages type.
|
||||||
|
new FlagTester()
|
||||||
|
.use(UseLargePages(true),
|
||||||
|
UseHugeTLBFS(false))
|
||||||
|
.expect(
|
||||||
|
UseLargePages(false),
|
||||||
|
UseTransparentHugePages(false),
|
||||||
|
UseHugeTLBFS(false),
|
||||||
|
UseSHM(false));
|
||||||
|
|
||||||
|
// Using UseLargePages will default to UseHugeTLBFS large pages.
|
||||||
|
new FlagTester()
|
||||||
|
.use(UseLargePages(true))
|
||||||
|
.expect(
|
||||||
|
UseLargePages(true),
|
||||||
|
UseTransparentHugePages(false),
|
||||||
|
UseHugeTLBFS(true),
|
||||||
|
UseSHM(false));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void testUseSHM() throws Exception {
|
||||||
|
if (!canUse(UseSHM(true))) {
|
||||||
|
System.out.println("Skipping testUseSHM");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// -XX:-UseLargePages overrides all other flags.
|
||||||
|
new FlagTester()
|
||||||
|
.use(UseLargePages(false),
|
||||||
|
UseSHM(true))
|
||||||
|
.expect(
|
||||||
|
UseLargePages(false),
|
||||||
|
UseTransparentHugePages(false),
|
||||||
|
UseHugeTLBFS(false),
|
||||||
|
UseSHM(false));
|
||||||
|
|
||||||
|
// Explicitly turn on UseSHM.
|
||||||
|
new FlagTester()
|
||||||
|
.use(UseSHM(true))
|
||||||
|
.expect(
|
||||||
|
UseLargePages(true),
|
||||||
|
UseTransparentHugePages(false),
|
||||||
|
UseHugeTLBFS(false),
|
||||||
|
UseSHM(true)) ;
|
||||||
|
|
||||||
|
new FlagTester()
|
||||||
|
.use(UseLargePages(true),
|
||||||
|
UseSHM(true))
|
||||||
|
.expect(
|
||||||
|
UseLargePages(true),
|
||||||
|
UseTransparentHugePages(false),
|
||||||
|
UseHugeTLBFS(false),
|
||||||
|
UseSHM(true)) ;
|
||||||
|
|
||||||
|
// Setting a specific large pages flag will turn
|
||||||
|
// off heuristics to choose large pages type.
|
||||||
|
new FlagTester()
|
||||||
|
.use(UseLargePages(true),
|
||||||
|
UseSHM(false))
|
||||||
|
.expect(
|
||||||
|
UseLargePages(false),
|
||||||
|
UseTransparentHugePages(false),
|
||||||
|
UseHugeTLBFS(false),
|
||||||
|
UseSHM(false));
|
||||||
|
|
||||||
|
// Setting UseLargePages can allow the system to choose
|
||||||
|
// UseHugeTLBFS instead of UseSHM, but never UseTransparentHugePages.
|
||||||
|
new FlagTester()
|
||||||
|
.use(UseLargePages(true))
|
||||||
|
.expect(
|
||||||
|
UseLargePages(true),
|
||||||
|
UseTransparentHugePages(false));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void testCombinations() throws Exception {
|
||||||
|
if (!canUse(UseSHM(true)) || !canUse(UseHugeTLBFS(true))) {
|
||||||
|
System.out.println("Skipping testUseHugeTLBFSAndUseSHMCombination");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// UseHugeTLBFS takes precedence over SHM.
|
||||||
|
|
||||||
|
new FlagTester()
|
||||||
|
.use(UseLargePages(true),
|
||||||
|
UseHugeTLBFS(true),
|
||||||
|
UseSHM(true))
|
||||||
|
.expect(
|
||||||
|
UseLargePages(true),
|
||||||
|
UseTransparentHugePages(false),
|
||||||
|
UseHugeTLBFS(true),
|
||||||
|
UseSHM(false));
|
||||||
|
|
||||||
|
new FlagTester()
|
||||||
|
.use(UseLargePages(true),
|
||||||
|
UseHugeTLBFS(false),
|
||||||
|
UseSHM(true))
|
||||||
|
.expect(
|
||||||
|
UseLargePages(true),
|
||||||
|
UseTransparentHugePages(false),
|
||||||
|
UseHugeTLBFS(false),
|
||||||
|
UseSHM(true));
|
||||||
|
|
||||||
|
new FlagTester()
|
||||||
|
.use(UseLargePages(true),
|
||||||
|
UseHugeTLBFS(true),
|
||||||
|
UseSHM(false))
|
||||||
|
.expect(
|
||||||
|
UseLargePages(true),
|
||||||
|
UseTransparentHugePages(false),
|
||||||
|
UseHugeTLBFS(true),
|
||||||
|
UseSHM(false));
|
||||||
|
|
||||||
|
new FlagTester()
|
||||||
|
.use(UseLargePages(true),
|
||||||
|
UseHugeTLBFS(false),
|
||||||
|
UseSHM(false))
|
||||||
|
.expect(
|
||||||
|
UseLargePages(false),
|
||||||
|
UseTransparentHugePages(false),
|
||||||
|
UseHugeTLBFS(false),
|
||||||
|
UseSHM(false));
|
||||||
|
|
||||||
|
|
||||||
|
if (!canUse(UseTransparentHugePages(true))) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// UseTransparentHugePages takes precedence.
|
||||||
|
|
||||||
|
new FlagTester()
|
||||||
|
.use(UseLargePages(true),
|
||||||
|
UseTransparentHugePages(true),
|
||||||
|
UseHugeTLBFS(true),
|
||||||
|
UseSHM(true))
|
||||||
|
.expect(
|
||||||
|
UseLargePages(true),
|
||||||
|
UseTransparentHugePages(true),
|
||||||
|
UseHugeTLBFS(false),
|
||||||
|
UseSHM(false));
|
||||||
|
|
||||||
|
new FlagTester()
|
||||||
|
.use(UseTransparentHugePages(true),
|
||||||
|
UseHugeTLBFS(true),
|
||||||
|
UseSHM(true))
|
||||||
|
.expect(
|
||||||
|
UseLargePages(true),
|
||||||
|
UseTransparentHugePages(true),
|
||||||
|
UseHugeTLBFS(false),
|
||||||
|
UseSHM(false));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class FlagTester {
|
||||||
|
private Flag [] useFlags;
|
||||||
|
|
||||||
|
public FlagTester use(Flag... useFlags) {
|
||||||
|
this.useFlags = useFlags;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void expect(Flag... expectedFlags) throws Exception {
|
||||||
|
if (useFlags == null) {
|
||||||
|
throw new IllegalStateException("Must run use() before expect()");
|
||||||
|
}
|
||||||
|
|
||||||
|
OutputAnalyzer output = executeNewJVM(useFlags);
|
||||||
|
|
||||||
|
for (Flag flag : expectedFlags) {
|
||||||
|
System.out.println("Looking for: " + flag.flagString());
|
||||||
|
String strValue = output.firstMatch(".* " + flag.name() + " .* :?= (\\S+).*", 1);
|
||||||
|
|
||||||
|
if (strValue == null) {
|
||||||
|
throw new RuntimeException("Flag " + flag.name() + " couldn't be found");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!flag.value().equals(strValue)) {
|
||||||
|
throw new RuntimeException("Wrong value for: " + flag.name()
|
||||||
|
+ " expected: " + flag.value()
|
||||||
|
+ " got: " + strValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
output.shouldHaveExitValue(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static OutputAnalyzer executeNewJVM(Flag... flags) throws Exception {
|
||||||
|
ArrayList<String> args = new ArrayList<>();
|
||||||
|
for (Flag flag : flags) {
|
||||||
|
args.add(flag.flagString());
|
||||||
|
}
|
||||||
|
args.add("-XX:+PrintFlagsFinal");
|
||||||
|
args.add("-version");
|
||||||
|
|
||||||
|
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(args.toArray(new String[args.size()]));
|
||||||
|
OutputAnalyzer output = new OutputAnalyzer(pb.start());
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean canUse(Flag flag) {
|
||||||
|
try {
|
||||||
|
new FlagTester().use(flag).expect(flag);
|
||||||
|
} catch (Exception e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Flag UseLargePages(boolean value) {
|
||||||
|
return new BooleanFlag("UseLargePages", value);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Flag UseTransparentHugePages(boolean value) {
|
||||||
|
return new BooleanFlag("UseTransparentHugePages", value);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Flag UseHugeTLBFS(boolean value) {
|
||||||
|
return new BooleanFlag("UseHugeTLBFS", value);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Flag UseSHM(boolean value) {
|
||||||
|
return new BooleanFlag("UseSHM", value);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class BooleanFlag implements Flag {
|
||||||
|
private String name;
|
||||||
|
private boolean value;
|
||||||
|
|
||||||
|
BooleanFlag(String name, boolean value) {
|
||||||
|
this.name = name;
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String flagString() {
|
||||||
|
return "-XX:" + (value ? "+" : "-") + name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String name() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String value() {
|
||||||
|
return Boolean.toString(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static interface Flag {
|
||||||
|
public String flagString();
|
||||||
|
public String name();
|
||||||
|
public String value();
|
||||||
|
}
|
||||||
|
}
|
|
@ -56,6 +56,7 @@ public class ReserveMemory {
|
||||||
"-Xbootclasspath/a:.",
|
"-Xbootclasspath/a:.",
|
||||||
"-XX:+UnlockDiagnosticVMOptions",
|
"-XX:+UnlockDiagnosticVMOptions",
|
||||||
"-XX:+WhiteBoxAPI",
|
"-XX:+WhiteBoxAPI",
|
||||||
|
"-XX:-TransmitErrorReport",
|
||||||
"ReserveMemory",
|
"ReserveMemory",
|
||||||
"test");
|
"test");
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,71 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java.lang.management.ManagementFactory;
|
||||||
|
import java.lang.management.RuntimeMXBean;
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import sun.management.VMManagement;
|
||||||
|
|
||||||
|
public class JMapHProfLargeHeapProc {
|
||||||
|
private static final List<byte[]> heapGarbage = new ArrayList<>();
|
||||||
|
|
||||||
|
public static void main(String[] args) throws Exception {
|
||||||
|
|
||||||
|
buildLargeHeap(args);
|
||||||
|
|
||||||
|
// Print our pid on stdout
|
||||||
|
System.out.println("PID[" + getProcessId() + "]");
|
||||||
|
|
||||||
|
// Wait for input before termination
|
||||||
|
System.in.read();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void buildLargeHeap(String[] args) {
|
||||||
|
for (long i = 0; i < Integer.parseInt(args[0]); i++) {
|
||||||
|
heapGarbage.add(new byte[1024]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int getProcessId() throws Exception {
|
||||||
|
|
||||||
|
// Get the current process id using a reflection hack
|
||||||
|
RuntimeMXBean runtime = ManagementFactory.getRuntimeMXBean();
|
||||||
|
Field jvm = runtime.getClass().getDeclaredField("jvm");
|
||||||
|
|
||||||
|
jvm.setAccessible(true);
|
||||||
|
VMManagement mgmt = (sun.management.VMManagement) jvm.get(runtime);
|
||||||
|
|
||||||
|
Method pid_method = mgmt.getClass().getDeclaredMethod("getProcessId");
|
||||||
|
|
||||||
|
pid_method.setAccessible(true);
|
||||||
|
|
||||||
|
int pid = (Integer) pid_method.invoke(mgmt);
|
||||||
|
|
||||||
|
return pid;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,146 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
import java.io.FileReader;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.Reader;
|
||||||
|
import java.nio.CharBuffer;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Scanner;
|
||||||
|
|
||||||
|
import com.oracle.java.testlibrary.Asserts;
|
||||||
|
import com.oracle.java.testlibrary.JDKToolFinder;
|
||||||
|
import com.oracle.java.testlibrary.JDKToolLauncher;
|
||||||
|
import com.oracle.java.testlibrary.OutputAnalyzer;
|
||||||
|
import com.oracle.java.testlibrary.Platform;
|
||||||
|
import com.oracle.java.testlibrary.ProcessTools;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @test
|
||||||
|
* @bug 6313383
|
||||||
|
* @key regression
|
||||||
|
* @summary Regression test for hprof export issue due to large heaps (>2G)
|
||||||
|
* @library /testlibrary
|
||||||
|
* @compile JMapHProfLargeHeapProc.java
|
||||||
|
* @run main JMapHProfLargeHeapTest
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class JMapHProfLargeHeapTest {
|
||||||
|
private static final String HEAP_DUMP_FILE_NAME = "heap.hprof";
|
||||||
|
private static final String HPROF_HEADER_1_0_1 = "JAVA PROFILE 1.0.1";
|
||||||
|
private static final String HPROF_HEADER_1_0_2 = "JAVA PROFILE 1.0.2";
|
||||||
|
private static final long M = 1024L;
|
||||||
|
private static final long G = 1024L * M;
|
||||||
|
|
||||||
|
public static void main(String[] args) throws Exception {
|
||||||
|
// If we are on MacOSX, test if JMap tool is signed, otherwise return
|
||||||
|
// since test will fail with privilege error.
|
||||||
|
if (Platform.isOSX()) {
|
||||||
|
String jmapToolPath = JDKToolFinder.getCurrentJDKTool("jmap");
|
||||||
|
ProcessBuilder codesignProcessBuilder = new ProcessBuilder(
|
||||||
|
"codesign", "-v", jmapToolPath);
|
||||||
|
Process codesignProcess = codesignProcessBuilder.start();
|
||||||
|
OutputAnalyzer analyser = new OutputAnalyzer(codesignProcess);
|
||||||
|
try {
|
||||||
|
analyser.shouldNotContain("code object is not signed at all");
|
||||||
|
System.out.println("Signed jmap found at: " + jmapToolPath);
|
||||||
|
} catch (Exception e) {
|
||||||
|
// Abort since we can't know if the test will work
|
||||||
|
System.out
|
||||||
|
.println("Test aborted since we are on MacOSX and the jmap tool is not signed.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Small heap 22 megabytes, should create 1.0.1 file format
|
||||||
|
testHProfFileFormat("-Xmx1g", 22 * M, HPROF_HEADER_1_0_1);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This test was deliberately commented out since the test system lacks
|
||||||
|
* support to handle the requirements for this kind of heap size in a
|
||||||
|
* good way. If or when it becomes possible to run this kind of tests in
|
||||||
|
* the test environment the test should be enabled again.
|
||||||
|
* */
|
||||||
|
// Large heap 2,2 gigabytes, should create 1.0.2 file format
|
||||||
|
// testHProfFileFormat("-Xmx4g", 2 * G + 2 * M, HPROF_HEADER_1_0_2);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void testHProfFileFormat(String vmArgs, long heapSize,
|
||||||
|
String expectedFormat) throws Exception, IOException,
|
||||||
|
InterruptedException, FileNotFoundException {
|
||||||
|
ProcessBuilder procBuilder = ProcessTools.createJavaProcessBuilder(
|
||||||
|
vmArgs, "JMapHProfLargeHeapProc", String.valueOf(heapSize));
|
||||||
|
procBuilder.redirectError(ProcessBuilder.Redirect.INHERIT);
|
||||||
|
Process largeHeapProc = procBuilder.start();
|
||||||
|
|
||||||
|
try (Scanner largeHeapScanner = new Scanner(
|
||||||
|
largeHeapProc.getInputStream());) {
|
||||||
|
String pidstring = null;
|
||||||
|
while ((pidstring = largeHeapScanner.findInLine("PID\\[[0-9].*\\]")) == null) {
|
||||||
|
Thread.sleep(500);
|
||||||
|
}
|
||||||
|
int pid = Integer.parseInt(pidstring.substring(4,
|
||||||
|
pidstring.length() - 1));
|
||||||
|
System.out.println("Extracted pid: " + pid);
|
||||||
|
|
||||||
|
JDKToolLauncher jMapLauncher = JDKToolLauncher
|
||||||
|
.create("jmap", false);
|
||||||
|
jMapLauncher.addToolArg("-dump:format=b,file=" + pid + "-"
|
||||||
|
+ HEAP_DUMP_FILE_NAME);
|
||||||
|
jMapLauncher.addToolArg(String.valueOf(pid));
|
||||||
|
|
||||||
|
ProcessBuilder jMapProcessBuilder = new ProcessBuilder(
|
||||||
|
jMapLauncher.getCommand());
|
||||||
|
System.out.println("jmap command: "
|
||||||
|
+ Arrays.toString(jMapLauncher.getCommand()));
|
||||||
|
|
||||||
|
Process jMapProcess = jMapProcessBuilder.start();
|
||||||
|
OutputAnalyzer analyzer = new OutputAnalyzer(jMapProcess);
|
||||||
|
analyzer.shouldHaveExitValue(0);
|
||||||
|
analyzer.shouldContain(pid + "-" + HEAP_DUMP_FILE_NAME);
|
||||||
|
analyzer.shouldContain("Heap dump file created");
|
||||||
|
|
||||||
|
largeHeapProc.getOutputStream().write('\n');
|
||||||
|
|
||||||
|
File dumpFile = new File(pid + "-" + HEAP_DUMP_FILE_NAME);
|
||||||
|
Asserts.assertTrue(dumpFile.exists(), "Heap dump file not found.");
|
||||||
|
|
||||||
|
try (Reader reader = new BufferedReader(new FileReader(dumpFile))) {
|
||||||
|
CharBuffer buf = CharBuffer.allocate(expectedFormat.length());
|
||||||
|
reader.read(buf);
|
||||||
|
buf.clear();
|
||||||
|
Asserts.assertEQ(buf.toString(), expectedFormat,
|
||||||
|
"Wrong file format. Expected '" + expectedFormat
|
||||||
|
+ "', but found '" + buf.toString() + "'");
|
||||||
|
}
|
||||||
|
|
||||||
|
System.out.println("Success!");
|
||||||
|
|
||||||
|
} finally {
|
||||||
|
largeHeapProc.destroyForcibly();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -23,20 +23,17 @@
|
||||||
|
|
||||||
package com.oracle.java.testlibrary;
|
package com.oracle.java.testlibrary;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
import com.oracle.java.testlibrary.JDKToolFinder;
|
|
||||||
import com.oracle.java.testlibrary.ProcessTools;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A utility for constructing command lines for starting JDK tool processes.
|
* A utility for constructing command lines for starting JDK tool processes.
|
||||||
*
|
*
|
||||||
* The JDKToolLauncher can in particular be combined with a
|
* The JDKToolLauncher can in particular be combined with a
|
||||||
* java.lang.ProcessBuilder to easily run a JDK tool. For example, the
|
* java.lang.ProcessBuilder to easily run a JDK tool. For example, the following
|
||||||
* following code run {@code jmap -heap} against a process with GC logging
|
* code run {@code jmap -heap} against a process with GC logging turned on for
|
||||||
* turned on for the {@code jmap} process:
|
* the {@code jmap} process:
|
||||||
*
|
*
|
||||||
* <pre>
|
* <pre>
|
||||||
* {@code
|
* {@code
|
||||||
|
@ -55,19 +52,39 @@ public class JDKToolLauncher {
|
||||||
private final List<String> vmArgs = new ArrayList<String>();
|
private final List<String> vmArgs = new ArrayList<String>();
|
||||||
private final List<String> toolArgs = new ArrayList<String>();
|
private final List<String> toolArgs = new ArrayList<String>();
|
||||||
|
|
||||||
private JDKToolLauncher(String tool) {
|
private JDKToolLauncher(String tool, boolean useCompilerJDK) {
|
||||||
|
if (useCompilerJDK) {
|
||||||
executable = JDKToolFinder.getJDKTool(tool);
|
executable = JDKToolFinder.getJDKTool(tool);
|
||||||
|
} else {
|
||||||
|
executable = JDKToolFinder.getCurrentJDKTool(tool);
|
||||||
|
}
|
||||||
vmArgs.addAll(Arrays.asList(ProcessTools.getPlatformSpecificVMArgs()));
|
vmArgs.addAll(Arrays.asList(ProcessTools.getPlatformSpecificVMArgs()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new JDKToolLauncher for the specified tool. Using tools path
|
||||||
|
* from the compiler JDK.
|
||||||
|
*
|
||||||
|
* @param tool
|
||||||
|
* The name of the tool
|
||||||
|
* @return A new JDKToolLauncher
|
||||||
|
*/
|
||||||
|
public static JDKToolLauncher create(String tool) {
|
||||||
|
return new JDKToolLauncher(tool, true);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new JDKToolLauncher for the specified tool.
|
* Creates a new JDKToolLauncher for the specified tool.
|
||||||
*
|
*
|
||||||
* @param tool The name of the tool
|
* @param tool
|
||||||
|
* The name of the tool
|
||||||
|
* @param useCompilerPath
|
||||||
|
* If true use the compiler JDK path, otherwise use the tested
|
||||||
|
* JDK path.
|
||||||
* @return A new JDKToolLauncher
|
* @return A new JDKToolLauncher
|
||||||
*/
|
*/
|
||||||
public static JDKToolLauncher create(String tool) {
|
public static JDKToolLauncher create(String tool, boolean useCompilerJDK) {
|
||||||
return new JDKToolLauncher(tool);
|
return new JDKToolLauncher(tool, useCompilerJDK);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -80,7 +97,8 @@ public class JDKToolLauncher {
|
||||||
* automatically added.
|
* automatically added.
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* @param arg The argument to VM running the tool
|
* @param arg
|
||||||
|
* The argument to VM running the tool
|
||||||
* @return The JDKToolLauncher instance
|
* @return The JDKToolLauncher instance
|
||||||
*/
|
*/
|
||||||
public JDKToolLauncher addVMArg(String arg) {
|
public JDKToolLauncher addVMArg(String arg) {
|
||||||
|
@ -91,7 +109,8 @@ public class JDKToolLauncher {
|
||||||
/**
|
/**
|
||||||
* Adds an argument to the tool.
|
* Adds an argument to the tool.
|
||||||
*
|
*
|
||||||
* @param arg The argument to the tool
|
* @param arg
|
||||||
|
* The argument to the tool
|
||||||
* @return The JDKToolLauncher instance
|
* @return The JDKToolLauncher instance
|
||||||
*/
|
*/
|
||||||
public JDKToolLauncher addToolArg(String arg) {
|
public JDKToolLauncher addToolArg(String arg) {
|
||||||
|
|
|
@ -232,3 +232,4 @@ d6a32e3831aab20a9a3bc78cdc0a60aaad725c6c jdk8-b107
|
||||||
8ade3eed63da87067a7137c111f684a821e9e531 jdk8-b108
|
8ade3eed63da87067a7137c111f684a821e9e531 jdk8-b108
|
||||||
02bfab2aa93899e0f02584f1e85537485a196553 jdk8-b109
|
02bfab2aa93899e0f02584f1e85537485a196553 jdk8-b109
|
||||||
4c84c5b447b09aff27f3b72667ab3a5401e85968 jdk8-b110
|
4c84c5b447b09aff27f3b72667ab3a5401e85968 jdk8-b110
|
||||||
|
17ee0d3e97fdb412e48f14d87f504946a708f846 jdk8-b111
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
* DO NOT REMOVE OR ALTER!
|
* DO NOT REMOVE OR ALTER!
|
||||||
*/
|
*/
|
||||||
/*
|
/*
|
||||||
* Copyright 1999-2004 The Apache Software Foundation.
|
* Copyright 1999-2005 The Apache Software Foundation.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -18,7 +18,7 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
/*
|
/*
|
||||||
* $Id: XSLTErrorResources_de.java,v 1.2.4.1 2005/09/13 10:08:18 pvedula Exp $
|
* $Id: XSLTErrorResources_de.java /st_wptg_1.8.0.0.0jdk/2 2013/09/16 04:56:10 gmolloy Exp $
|
||||||
*/
|
*/
|
||||||
package com.sun.org.apache.xalan.internal.res;
|
package com.sun.org.apache.xalan.internal.res;
|
||||||
|
|
||||||
|
@ -1207,7 +1207,7 @@ public class XSLTErrorResources_de extends ListResourceBundle
|
||||||
"Funktionsname darf nicht null sein."},
|
"Funktionsname darf nicht null sein."},
|
||||||
|
|
||||||
{ ER_XPATH_RESOLVER_NEGATIVE_ARITY,
|
{ ER_XPATH_RESOLVER_NEGATIVE_ARITY,
|
||||||
"Anzahl von Argumenten darf nicht negativ sein."},
|
"Argumentanzahl darf nicht negativ sein."},
|
||||||
// Warnings...
|
// Warnings...
|
||||||
|
|
||||||
{ WG_FOUND_CURLYBRACE,
|
{ WG_FOUND_CURLYBRACE,
|
||||||
|
@ -1359,7 +1359,7 @@ public class XSLTErrorResources_de extends ListResourceBundle
|
||||||
{ "optionQ", " [-Q (Stiller Modus)]"},
|
{ "optionQ", " [-Q (Stiller Modus)]"},
|
||||||
{ "optionLF", " [-LF (Nur Zeilenvorsch\u00FCbe bei Ausgabe verwenden {Standard ist CR/LF})]"},
|
{ "optionLF", " [-LF (Nur Zeilenvorsch\u00FCbe bei Ausgabe verwenden {Standard ist CR/LF})]"},
|
||||||
{ "optionCR", " [-CR (Nur Zeilenschaltungen bei Ausgabe verwenden {Standard ist CR/LF})]"},
|
{ "optionCR", " [-CR (Nur Zeilenschaltungen bei Ausgabe verwenden {Standard ist CR/LF})]"},
|
||||||
{ "optionESCAPE", " [-ESCAPE (Escape-Zeichen {Standard ist <>&\"\'\r\n}]"},
|
{ "optionESCAPE", " [-ESCAPE (Escapezeichen {Standard ist <>&\"'\r\n}]"},
|
||||||
{ "optionINDENT", " [-INDENT (Steuern, wie viele Leerzeichen der Einzug enthalten soll {Standard ist 0})]"},
|
{ "optionINDENT", " [-INDENT (Steuern, wie viele Leerzeichen der Einzug enthalten soll {Standard ist 0})]"},
|
||||||
{ "optionTT", " [-TT (Vorlagen verfolgen, wenn diese aufgerufen werden.)]"},
|
{ "optionTT", " [-TT (Vorlagen verfolgen, wenn diese aufgerufen werden.)]"},
|
||||||
{ "optionTG", " [-TG (Jedes Generierungsereignis verfolgen.)]"},
|
{ "optionTG", " [-TG (Jedes Generierungsereignis verfolgen.)]"},
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue