This commit is contained in:
Lana Steuck 2013-10-17 14:20:57 -07:00
commit c71f3cdbe6
1328 changed files with 50430 additions and 32076 deletions

View file

@ -232,3 +232,4 @@ b5ed503c26ad38869c247c5e32debec217fd056b jdk8-b104
74049f7a28b48c14910106a75d9f2504169c352e jdk8-b108
af9a674e12a16da1a4bd53e4990ddb1121a21ef1 jdk8-b109
b5d2bf482a3ea1cca08c994512804ffbc73de0a1 jdk8-b110
b9a0f6c693f347a6f4b9bb994957f4eaa05bdedd jdk8-b111

View file

@ -232,3 +232,4 @@ b7e64be81c8a7690703df5711f4fc2375da8a9cb jdk8-b103
9286a6e61291246d88af713f1ef79adeea30fe2e jdk8-b108
91f47e8da5c60de58ed195e9b57f3bf192a18f83 jdk8-b109
4faa09c7fe555de086dd9048d3c5cc92317d6f45 jdk8-b110
d086227bfc45d124f09b3bd72a07956b4073bf71 jdk8-b111

View file

@ -707,7 +707,6 @@ AC_DEFUN_ONCE([BASIC_CHECK_SRC_PERMS],
AC_DEFUN_ONCE([BASIC_TEST_USABILITY_ISSUES],
[
AC_MSG_CHECKING([if build directory is on local disk])
BASIC_CHECK_DIR_ON_LOCAL_DISK($OUTPUT_ROOT,
[OUTPUT_DIR_IS_LOCAL="yes"],
@ -734,5 +733,4 @@ else
# Hide it the next time around...
$TOUCH $SRC_ROOT/build/.hide-configure-performance-hints > /dev/null 2>&1
fi
])

View file

@ -53,7 +53,6 @@ AC_DEFUN([BPERF_CHECK_CORES],
AC_MSG_RESULT([could not detect number of cores, defaulting to 1])
AC_MSG_WARN([This will disable all parallelism from build!])
fi
])
AC_DEFUN([BPERF_CHECK_MEMORY_SIZE],
@ -331,5 +330,4 @@ else
SJAVAC_SERVER_DIR=
fi
AC_SUBST(SJAVAC_SERVER_DIR)
])

View file

@ -88,7 +88,6 @@ check_hg_updates() {
check_autoconf_timestamps
fi
fi
fi
}

View file

@ -3818,7 +3818,7 @@ fi
#CUSTOM_AUTOCONF_INCLUDE
# 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.
# Locate the directory of this script.
@ -7847,7 +7846,6 @@ fi
###############################################################################
#
# Set the debug level
@ -16023,7 +16021,6 @@ BOOT_JDK_JVMARGS=$boot_jdk_jvmargs
###############################################################################
# Where are the sources. Any of these can be overridden
# using --with-override-corba and the likes.
LANGTOOLS_TOPDIR="$SRC_ROOT/langtools"
@ -16316,7 +16313,6 @@ $as_echo "yes with $JDK_TOPDIR" >&6; }
fi
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
DEVKIT_LIBS="$thelibs"
fi
# Found devkit
PATH="$DEVKIT/bin:$PATH"
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
elif test "x$OPENJDK_TARGET_OS" = xwindows; then
# 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=`$ECHO $COMPILER_VERSION_TEST | $SED -n "s/^.*Version \([1-9][0-9.]*\) .*/\1/p"`
COMPILER_VENDOR="Microsoft CL.EXE"
@ -21258,7 +21255,7 @@ $as_echo "$as_me: The result from running with -V was: \"$COMPILER_VERSION_TEST\
fi
elif test "x$OPENJDK_TARGET_OS" = xwindows; then
# 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=`$ECHO $COMPILER_VERSION_TEST | $SED -n "s/^.*Version \([1-9][0-9.]*\) .*/\1/p"`
COMPILER_VENDOR="Microsoft CL.EXE"
@ -28937,6 +28934,7 @@ else
$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
fi
rm -f core conftest.err conftest.$ac_objext \
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
/* end confdefs.h. */
int i;
_ACEOF
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
/* end confdefs.h. */
int i;
_ACEOF
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
/* end confdefs.h. */
int i;
_ACEOF
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
/* end confdefs.h. */
int i;
_ACEOF
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
do :
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>
"
if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
cat >>confdefs.h <<_ACEOF
@ -30739,9 +30731,12 @@ if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
cat >>confdefs.h <<_ACEOF
#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
_ACEOF
CUPS_FOUND=yes
CUPS_CFLAGS=
DEFAULT_CUPS=yes
fi
done
@ -31362,6 +31357,7 @@ $as_echo_n "checking for freetype in some standard locations... " >&6; }
LDFLAGS="$LDFLAGS $DEFAULT_FREETYPE_LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include<ft2build.h>
#include FT_FREETYPE_H
int main() { return 0; }
@ -31378,6 +31374,7 @@ else
FREETYPE2_FOUND=no
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
@ -31473,7 +31470,6 @@ fi
###############################################################################
#
# 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
#define HAVE_ALSA_ASOUNDLIB_H 1
_ACEOF
ALSA_FOUND=yes
ALSA_CFLAGS=-Iignoreme
ALSA_LIBS=-lasound
DEFAULT_ALSA=yes
else
ALSA_FOUND=no
fi
@ -31794,7 +31792,6 @@ fi
###############################################################################
#
# 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: Maths library was not found" >&6;}
fi
@ -32188,7 +32186,6 @@ LIBDL="$LIBS"
LIBS="$save_LIBS"
###############################################################################
#
# 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
# 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_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;}
fi
else
NUM_CORES=$with_num_cores
fi
@ -32975,7 +32969,6 @@ fi
# Can the C/C++ compiler use precompiled headers?
@ -33174,7 +33167,6 @@ $as_echo "no, disabling ccaching of precompiled headers" >&6; }
fi
{ $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; }
@ -33226,7 +33218,6 @@ else
fi
# At the end, call the custom hook. (Dummy macro if no custom sources available)

View file

@ -135,7 +135,6 @@ if test "x$OPENJDK_TARGET_OS" = "xmacosx"; then
fi
AC_SUBST(MACOSX_UNIVERSAL)
])
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}"
fi
AC_SUBST(SALIB_NAME)
])
AC_DEFUN_ONCE([JDKOPT_SETUP_DEBUG_SYMBOLS],

View file

@ -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],
[X11_A_OK=yes],
[X11_A_OK=no; break],
[ # include <X11/Xlib.h>
[
# include <X11/Xlib.h>
# include <X11/Xutil.h>
])
]
)
CFLAGS="$OLD_CFLAGS"
AC_LANG_POP(C)
@ -243,9 +245,12 @@ else
if test "x$CUPS_FOUND" = xno; then
# Are the cups headers installed in the default /usr/include location?
AC_CHECK_HEADERS([cups/cups.h cups/ppd.h],
[CUPS_FOUND=yes
[
CUPS_FOUND=yes
CUPS_CFLAGS=
DEFAULT_CUPS=yes])
DEFAULT_CUPS=yes
]
)
fi
if test "x$CUPS_FOUND" = xno; then
# Getting nervous now? Lets poke around for standard Solaris third-party
@ -377,7 +382,8 @@ else
PREV_LDFLAGS="$LDFLAGS"
CXXFLAGS="$CXXFLAGS $DEFAULT_FREETYPE_CFLAGS"
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
int main() { return 0; }
]])],
@ -389,7 +395,8 @@ else
],
[
FREETYPE2_FOUND=no
])
]
)
CXXCFLAGS="$PREV_CXXFLAGS"
LDFLAGS="$PREV_LDFLAGS"
AC_MSG_RESULT([$FREETYPE2_FOUND])
@ -415,7 +422,6 @@ AC_SUBST(USING_SYSTEM_FT_LIB)
AC_SUBST(FREETYPE2_LIB_PATH)
AC_SUBST(FREETYPE2_CFLAGS)
AC_SUBST(FREETYPE2_LIBS)
])
AC_DEFUN_ONCE([LIB_SETUP_ALSA],
@ -467,10 +473,12 @@ else
fi
if test "x$ALSA_FOUND" = xno; then
AC_CHECK_HEADERS([alsa/asoundlib.h],
[ALSA_FOUND=yes
[
ALSA_FOUND=yes
ALSA_CFLAGS=-Iignoreme
ALSA_LIBS=-lasound
DEFAULT_ALSA=yes],
DEFAULT_ALSA=yes
],
[ALSA_FOUND=no])
fi
if test "x$ALSA_FOUND" = xno; then
@ -481,7 +489,6 @@ fi
AC_SUBST(ALSA_CFLAGS)
AC_SUBST(ALSA_LIBS)
])
AC_DEFUN_ONCE([LIB_SETUP_MISC_LIBS],
@ -614,7 +621,8 @@ fi
AC_CHECK_LIB(m, cos, [],
[
AC_MSG_NOTICE([Maths library was not found])
])
]
)
AC_SUBST(LIBM)
###############################################################################
@ -627,7 +635,6 @@ AC_CHECK_LIB(dl,dlopen)
LIBDL="$LIBS"
AC_SUBST(LIBDL)
LIBS="$save_LIBS"
])
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
AC_SUBST(LIBCXX)
])

View file

@ -355,7 +355,6 @@ AC_DEFUN([PLATFORM_SETUP_LEGACY_VARS],
*) ZERO_ARCHDEF=$(echo "${OPENJDK_TARGET_CPU_LEGACY_LIB}" | tr a-z A-Z)
esac
AC_SUBST(ZERO_ARCHDEF)
])
AC_DEFUN([PLATFORM_SET_RELEASE_FILE_OS_VALUES],

View file

@ -25,7 +25,6 @@
AC_DEFUN_ONCE([SRCDIRS_SETUP_TOPDIRS],
[
# Where are the sources. Any of these can be overridden
# using --with-override-corba and the likes.
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_RESULT([yes with $JDK_TOPDIR])
fi
])
AC_DEFUN_ONCE([SRCDIRS_SETUP_OUTPUT_DIRS],

View file

@ -46,7 +46,7 @@ AC_DEFUN([TOOLCHAIN_CHECK_COMPILER_VERSION],
fi
elif test "x$OPENJDK_TARGET_OS" = xwindows; then
# 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=`$ECHO $COMPILER_VERSION_TEST | $SED -n "s/^.*Version \(@<:@1-9@:>@@<:@0-9.@:>@*\) .*/\1/p"`
COMPILER_VENDOR="Microsoft CL.EXE"
@ -216,7 +216,8 @@ AC_SUBST(BUILD_LD)
# will be found by AC_PROG_CC et al.
DEVKIT=
BDEPS_CHECK_MODULE(DEVKIT, devkit, xxx,
[# Found devkit
[
# Found devkit
PATH="$DEVKIT/bin:$PATH"
SYS_ROOT="$DEVKIT/${rewritten_target}/sys-root"
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_ERROR([The selected compiler $CXX does not support -mstackrealign! Try to put another compiler in the path.])
])
]
)
fi
C_FLAG_DEPS="-MMD -MF"
@ -1046,18 +1048,16 @@ AC_DEFUN([TOOLCHAIN_COMPILER_CHECK_ARGUMENTS],
saved_cflags="$CFLAGS"
CFLAGS="$CFLAGS $1"
AC_LANG_PUSH([C])
AC_COMPILE_IFELSE([
AC_LANG_SOURCE([[int i;]])
], [], [supports=no])
AC_COMPILE_IFELSE([AC_LANG_SOURCE([[int i;]])], [],
[supports=no])
AC_LANG_POP([C])
CFLAGS="$saved_cflags"
saved_cxxflags="$CXXFLAGS"
CXXFLAGS="$CXXFLAG $1"
AC_LANG_PUSH([C++])
AC_COMPILE_IFELSE([
AC_LANG_SOURCE([[int i;]])
], [], [supports=no])
AC_COMPILE_IFELSE([AC_LANG_SOURCE([[int i;]])], [],
[supports=no])
AC_LANG_POP([C++])
CXXFLAGS="$saved_cxxflags"

View file

@ -86,7 +86,7 @@ define SetupArchive
# 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))
$(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))
$1_JARMAIN:=$(strip $$($1_JARMAIN))
@ -111,9 +111,9 @@ define SetupArchive
ifeq ($$(word 20,$$($1_GREP_INCLUDE_PATTERNS)),)
$1_GREP_INCLUDES:=| $(GREP) $$(patsubst %,$(SPACE)-e$(SPACE)$(DQUOTE)%$(DQUOTE),$$($1_GREP_INCLUDE_PATTERNS))
else
$1_GREP_INCLUDE_OUTPUT:=$(RM) $$($1_BIN)/_the.$$($1_JARNAME)_include && \
$$(strip $$(call ListPathsSafely,$1_GREP_INCLUDE_PATTERNS,\n, \
>> $$($1_BIN)/_the.$$($1_JARNAME)_include))
$1_GREP_INCLUDE_OUTPUT:=$(RM) $$($1_BIN)/_the.$$($1_JARNAME)_include $$(NEWLINE) \
$$(call ListPathsSafely,$1_GREP_INCLUDE_PATTERNS,\n, \
>> $$($1_BIN)/_the.$$($1_JARNAME)_include)
$1_GREP_INCLUDES:=| $(GREP) -f $$($1_BIN)/_the.$$($1_JARNAME)_include
endif
endif
@ -124,9 +124,9 @@ define SetupArchive
ifeq ($$(word 20,$$($1_GREP_EXCLUDE_PATTERNS)),)
$1_GREP_EXCLUDES:=| $(GREP) -v $$(patsubst %,$(SPACE)-e$(SPACE)$(DQUOTE)%$(DQUOTE),$$($1_GREP_EXCLUDE_PATTERNS))
else
$1_GREP_EXCLUDE_OUTPUT=$(RM) $$($1_BIN)/_the.$$($1_JARNAME)_exclude && \
$$(strip $$(call ListPathsSafely,$1_GREP_EXCLUDE_PATTERNS,\n, \
>> $$($1_BIN)/_the.$$($1_JARNAME)_exclude))
$1_GREP_EXCLUDE_OUTPUT=$(RM) $$($1_BIN)/_the.$$($1_JARNAME)_exclude $$(NEWLINE) \
$$(call ListPathsSafely,$1_GREP_EXCLUDE_PATTERNS,\n, \
>> $$($1_BIN)/_the.$$($1_JARNAME)_exclude)
$1_GREP_EXCLUDES:=| $(GREP) -v -f $$($1_BIN)/_the.$$($1_JARNAME)_exclude
endif
endif

View file

@ -56,7 +56,8 @@ define ListPathsSafely_If
endef
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
# Receipt example:
@ -66,6 +67,7 @@ endef
# if instead , , (a space) is supplied, then spaces remain spaces.
define ListPathsSafely
$(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,251,500)
$(call ListPathsSafely_If,$1,$2,501,750)

View file

@ -119,5 +119,3 @@ clean :
FORCE :
.PHONY : $(configs) $(platforms)

View file

@ -41,7 +41,6 @@ EXCLUDE_PKGS = \
org.w3c.dom.stylesheets \
org.w3c.dom.traversal \
org.w3c.dom.ranges \
org.w3c.dom.views \
org.omg.stub.javax.management.remote.rmi
#
@ -295,6 +294,7 @@ CORE_PKGS = \
org.w3c.dom.events \
org.w3c.dom.bootstrap \
org.w3c.dom.ls \
org.w3c.dom.views \
org.xml.sax \
org.xml.sax.ext \
org.xml.sax.helpers

View file

@ -116,8 +116,7 @@ BUG_SUBMIT_LINE = <a href="$(BUG_SUBMIT_URL)">Submit a bug or feature</a>
# Url to devdocs page
# 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
# This isn't added in old build yet.
#DEV_DOCS_URL-8 = http://download.oracle.com/javase/7/docs/index.html
DEV_DOCS_URL-8 = http://download.oracle.com/javase/8/docs/index.html
DEV_DOCS_URL = $(DEV_DOCS_URL-$(JDK_MINOR_VERSION))
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 \
evaluation. \
</div> </div>
endif
#################################################################

View file

@ -232,3 +232,4 @@ d411c60a8c2fe8fdc572af907775e90f7eefd513 jdk8-b104
a4bb3b4500164748a9c33b2283cfda76d89f25ab jdk8-b108
428428cf5e06163322144cfb5367e1faa86acf20 jdk8-b109
3d2b7ce93c5c2e3db748f29c3d29620a8b3b748a jdk8-b110
85c1c94e723582f9a1dd0251502c42b73d6deea7 jdk8-b111

View file

@ -144,6 +144,7 @@ $(CORBA_OUTPUTDIR)/logwrappers/_the_wrappers.d : $(CORBA_OUTPUTDIR)/btjars/logut
-include $(CORBA_OUTPUTDIR)/logwrappers/_the_wrappers.d
ifeq ($(LOGWRAPPERS_ARE_CREATED), yes)
$(eval $(call SetupIdlCompilation,BUILD_IDLS, \
IDLJ := $(JAVA) -jar $(CORBA_OUTPUTDIR)/btjars/idlj.jar, \
SRC := $(CORBA_TOPDIR)/src/share/classes, \
@ -166,6 +167,7 @@ ifeq ($(LOGWRAPPERS_ARE_CREATED),yes)
-include $(CORBA_OUTPUTDIR)/gensrc/_the_idls.d
ifeq ($(IDLS_ARE_CREATED), yes)
$(eval $(call SetupJavaCompilation,BUILD_CORBA, \
SETUP := GENERATE_NEWBYTECODE, \
SRC := $(CORBA_TOPDIR)/src/share/classes $(CORBA_OUTPUTDIR)/gensrc $(CORBA_OUTPUTDIR)/logwrappers, \

View file

@ -384,3 +384,5 @@ c81dd5393a5e333df7cb1f6621f5897ada6522b5 jdk8-b109
6209b0ed51c086d4127bac0e086c8f326d1764d7 jdk8-b110
562a3d356de67670b4172b82aca2d30743449e04 hs25-b53
f6962730bbde82f279a0ae3a1c14bc5e58096c6e jdk8-b111
4a845c7a463844cead9e1e1641d6bcfb8a77f1c7 hs25-b54
0ed9a90f45e1b392c671005f9ee22ce1acf02984 jdk8-b112

View file

@ -44,6 +44,7 @@
// close all file descriptors
static void close_files(struct ps_prochandle* ph) {
lib_info* lib = NULL;
// close core file descriptor
if (ph->core->core_fd >= 0)
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
// 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;
map_info *mp;
@ -230,9 +230,9 @@ struct FileMapHeader {
size_t _used; // for setting space top on read
// 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
// Hotspot on BSD we assume the corresponding C type is char but
// licensees on BSD versions may need to adjust the type of these fields.
// the C type matching the C++ bool type on any given platform.
// We assume the corresponding C type is char but licensees
// may need to adjust the type of these fields.
char _read_only; // read only 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"
// mangled name of Arguments::SharedArchivePath
#define SHARED_ARCHIVE_PATH_SYM "_ZN9Arguments17SharedArchivePathE"
#define LIBJVM_NAME "/libjvm.dylib"
#else
#define USE_SHARED_SPACES_SYM "UseSharedSpaces"
// mangled name of Arguments::SharedArchivePath
#define SHARED_ARCHIVE_PATH_SYM "__ZN9Arguments17SharedArchivePathE"
#define LIBJVM_NAME "/libjvm.so"
#endif // __APPLE_
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
// libjvm.so.
const char *jvm_name = 0;
#ifdef __APPLE__
if ((jvm_name = strstr(lib->name, "/libjvm.dylib")) != 0)
#else
if ((jvm_name = strstr(lib->name, "/libjvm.so")) != 0)
#endif // __APPLE__
{
if ((jvm_name = strstr(lib->name, LIBJVM_NAME)) != 0) {
char classes_jsa[PATH_MAX];
struct FileMapHeader header;
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
* 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)
* 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* 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;
}
// we want to process only PT_LOAD segments that are not writable.
// i.e., text segments. The read/write/exec (data) segments would
// have been already added from core file segments.
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 (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;
}
} 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++;
}
@ -1192,7 +1218,7 @@ err:
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) {
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
// 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,
sizeof(uintptr_t)) != PS_OK) {
print_debug("can't read ld base address\n");
return false;
}
ph->core->ld_base_addr = ld_base_addr;
*/
#else
ph->core->ld_base_addr = 0;
#endif
print_debug("interpreter base address is 0x%lx\n", ld_base_addr);
// now read segments from interp (i.e ld-elf.so.1)
if (read_interp_segments(ph) != true)
// now read segments from interp (i.e ld.so or ld-linux.so or ld-elf.so)
if (read_interp_segments(ph) != true) {
return false;
}
// after adding interpreter (ld.so) mappings sort again
if (sort_map_array(ph) != true)
if (sort_map_array(ph) != true) {
return false;
}
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);
// Map info is added for the library (lib_name) so
// 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;
}
} else {
print_debug("can't read ELF header for shared object %s\n", lib_name);
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));
if (ph == NULL) {
print_debug("cant allocate ps_prochandle\n");
print_debug("can't allocate ps_prochandle\n");
return NULL;
}
@ -1449,33 +1478,40 @@ struct ps_prochandle* Pgrab_core(const char* exec_file, const char* core_file) {
}
// process core file segments
if (read_core_segments(ph, &core_ehdr) != true)
if (read_core_segments(ph, &core_ehdr) != true) {
goto err;
}
// process exec file segments
if (read_exec_segments(ph, &exec_ehdr) != true)
if (read_exec_segments(ph, &exec_ehdr) != true) {
goto err;
}
// exec file is also treated like a shared object for symbol search
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;
}
// allocate and sort maps into map_array, we need to do this
// here because read_shared_lib_info needs to read from debuggee
// address space
if (sort_map_array(ph) != true)
if (sort_map_array(ph) != true) {
goto err;
}
if (read_shared_lib_info(ph) != true)
if (read_shared_lib_info(ph) != true) {
goto err;
}
// 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;
}
if (init_classsharing_workaround(ph) != true)
if (init_classsharing_workaround(ph) != true) {
goto err;
}
print_debug("Leave Pgrab_core\n");
return ph;

View file

@ -41,7 +41,7 @@
// ps_prochandle cleanup helper functions
// 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;
// close core file descriptor
@ -64,7 +64,9 @@ static void close_elf_files(struct ps_prochandle* ph) {
lib = ph->libs;
while (lib) {
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;
}
}
@ -94,7 +96,7 @@ static void destroy_map_info(struct ps_prochandle* ph) {
// ps_prochandle operations
static void core_release(struct ps_prochandle* ph) {
if (ph->core) {
close_elf_files(ph);
close_files(ph);
destroy_map_info(ph);
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
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) {
map_info* map;
if ((map = allocate_init_map(ph->core->classes_jsa_fd,
offset, vaddr, memsz)) == NULL) {
return;
return NULL;
}
map->next = ph->core->class_share_maps;
ph->core->class_share_maps = map;
return map;
}
// 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.
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;
map_info *mp;
while (hi - lo > 1) {
mid = (lo + hi) / 2;
if (addr >= ph->core->map_array[mid]->vaddr)
if (addr >= ph->core->map_array[mid]->vaddr) {
lo = mid;
else
} else {
hi = mid;
}
}
if (addr < ph->core->map_array[hi]->vaddr)
if (addr < ph->core->map_array[hi]->vaddr) {
mp = ph->core->map_array[lo];
else
} else {
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);
}
// 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.
mp = ph->core->class_share_maps;
if (mp) {
print_debug("can't locate map_info at 0x%lx, trying class share maps\n",
addr);
print_debug("can't locate map_info at 0x%lx, trying class share maps\n", addr);
}
while (mp) {
if (addr >= mp->vaddr && addr < mp->vaddr + mp->memsz) {
print_debug("located map_info at 0x%lx from class share maps\n",
addr);
print_debug("located map_info at 0x%lx from class share maps\n", addr);
return (mp);
}
mp = mp->next;
@ -226,9 +229,9 @@ struct FileMapHeader {
size_t _used; // for setting space top on read
// 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
// Hotspot on Linux we assume the corresponding C type is char but
// licensees on Linux versions may need to adjust the type of these fields.
// the C type matching the C++ bool type on any given platform.
// We assume the corresponding C type is char but licensees
// may need to adjust the type of these fields.
char _read_only; // read only 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) {
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;
return true;
} else {
@ -263,12 +266,15 @@ static bool read_string(struct ps_prochandle* ph, uintptr_t addr, char* buf, siz
char c = ' ';
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;
if (i < size - 1)
}
if (i < size - 1) {
buf[i] = c;
else // smaller buffer
} else {
// smaller buffer
return false;
}
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"
// mangled name of Arguments::SharedArchivePath
#define SHARED_ARCHIVE_PATH_SYM "_ZN9Arguments17SharedArchivePathE"
#define LIBJVM_NAME "/libjvm.so"
static bool init_classsharing_workaround(struct ps_prochandle* ph) {
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
// libjvm.so.
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];
struct FileMapHeader header;
int fd = -1;
int m = 0;
size_t n = 0;
int fd = -1, m = 0;
uintptr_t base = 0, useSharedSpacesAddr = 0;
uintptr_t sharedArchivePathAddrAddr = 0, sharedArchivePathAddr = 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 *rhs = *((const map_info **)rhsp);
if (lhs->vaddr == rhs->vaddr)
if (lhs->vaddr == rhs->vaddr) {
return (0);
}
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
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;
// sort the map_info array by base virtual address.
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;
int fd;
if (mp == NULL)
if (mp == NULL) {
break; /* No mapping for this address */
}
fd = mp->fd;
mapoff = addr - mp->vaddr;
len = MIN(resid, mp->memsz - mapoff);
off = mp->offset + mapoff;
if ((len = pread(fd, buf, len, off)) <= 0)
if ((len = pread(fd, buf, len, off)) <= 0) {
break;
}
resid -= 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);
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;
}
}
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
* 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)
* 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++) {
switch (core_php->p_type) {
case PT_NOTE:
if (core_handle_note(ph, core_php) != true) goto err;
if (core_handle_note(ph, core_php) != true) {
goto err;
}
break;
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);
// now read segments from interp (i.e ld.so or ld-linux.so)
if (read_interp_segments(ph) != true)
// now read segments from interp (i.e ld.so or ld-linux.so or ld-elf.so)
if (read_interp_segments(ph) != true) {
return false;
}
// after adding interpreter (ld.so) mappings sort again
if (sort_map_array(ph) != true)
if (sort_map_array(ph) != true) {
return false;
}
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
if (read_core_segments(ph, &core_ehdr) != true)
if (read_core_segments(ph, &core_ehdr) != true) {
goto err;
}
// process exec file segments
if (read_exec_segments(ph, &exec_ehdr) != true)
if (read_exec_segments(ph, &exec_ehdr) != true) {
goto err;
}
// exec file is also treated like a shared object for symbol search
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;
}
// allocate and sort maps into map_array, we need to do this
// here because read_shared_lib_info needs to read from debuggee
// address space
if (sort_map_array(ph) != true)
if (sort_map_array(ph) != true) {
goto err;
}
if (read_shared_lib_info(ph) != true)
if (read_shared_lib_info(ph) != true) {
goto err;
}
// 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;
}
if (init_classsharing_workaround(ph) != true)
if (init_classsharing_workaround(ph) != true) {
goto err;
}
return ph;

View file

@ -67,6 +67,13 @@ public class Disassembler {
String libname = "hsdis";
String arch = System.getProperty("os.arch");
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);
libname += ".dll";
} else if (os.lastIndexOf("SunOS", 0) != -1) {

View file

@ -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));
}
}

View file

@ -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.
*
* 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 {
private static AddressField nextField;
private static sun.jvm.hotspot.types.OopField protectionDomainField;
private static AddressField pdCacheField;
static {
VM.registerVMInitializedObserver(new Observer() {
@ -46,7 +46,7 @@ public class ProtectionDomainEntry extends VMObject {
Type type = db.lookupType("ProtectionDomainEntry");
nextField = type.getAddressField("_next");
protectionDomainField = type.getOopField("_protection_domain");
pdCacheField = type.getAddressField("_pd_cache");
}
public ProtectionDomainEntry(Address addr) {
@ -54,10 +54,12 @@ public class ProtectionDomainEntry extends VMObject {
}
public ProtectionDomainEntry next() {
return (ProtectionDomainEntry) VMObjectFactory.newObject(ProtectionDomainEntry.class, addr);
return (ProtectionDomainEntry) VMObjectFactory.newObject(ProtectionDomainEntry.class, nextField.getValue(addr));
}
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();
}
}

View file

@ -44,12 +44,10 @@ public class SymbolTable extends sun.jvm.hotspot.utilities.Hashtable {
private static synchronized void initialize(TypeDataBase db) {
Type type = db.lookupType("SymbolTable");
theTableField = type.getAddressField("_the_table");
symbolTableSize = db.lookupIntConstant("SymbolTable::symbol_table_size").intValue();
}
// Fields
private static AddressField theTableField;
private static int symbolTableSize;
// Accessors
public static SymbolTable getTheTable() {
@ -57,10 +55,6 @@ public class SymbolTable extends sun.jvm.hotspot.utilities.Hashtable {
return (SymbolTable) VMObjectFactory.newObject(SymbolTable.class, tmp);
}
public static int getSymbolTableSize() {
return symbolTableSize;
}
public SymbolTable(Address addr) {
super(addr);
}

View file

@ -59,6 +59,7 @@ public abstract class AbstractHeapGraphWriter implements HeapGraphWriter {
public boolean doObj(Oop oop) {
try {
writeHeapRecordPrologue();
if (oop instanceof TypeArray) {
writePrimitiveArray((TypeArray)oop);
} else if (oop instanceof ObjArray) {
@ -97,6 +98,7 @@ public abstract class AbstractHeapGraphWriter implements HeapGraphWriter {
// not-a-Java-visible oop
writeInternalObject(oop);
}
writeHeapRecordEpilogue();
} catch (IOException exp) {
throw new RuntimeException(exp);
}
@ -416,6 +418,12 @@ public abstract class AbstractHeapGraphWriter implements HeapGraphWriter {
protected void writeHeapFooter() throws IOException {
}
protected void writeHeapRecordPrologue() throws IOException {
}
protected void writeHeapRecordEpilogue() throws IOException {
}
// HeapVisitor, OopVisitor methods can't throw any non-runtime
// exception. But, derived class write methods (which are called
// from visitor callbacks) may throw IOException. Hence, we throw

View file

@ -44,7 +44,7 @@ import sun.jvm.hotspot.runtime.*;
* WARNING: This format is still under development, and is subject to
* 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
* UTF8 strings, objects, stack traces, etc. They usually
* have the same size as host pointers. For example, on
@ -292,11 +292,34 @@ import sun.jvm.hotspot.runtime.*;
* 0x00000002: cpu sampling on/off
* 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 {
// 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
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
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_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
// constants in enum HprofGcTag
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_CLASS = 'L';
public synchronized void write(String fileName) throws IOException {
// open file stream and create buffered data output stream
FileOutputStream fos = new FileOutputStream(fileName);
FileChannel chn = fos.getChannel();
fos = new FileOutputStream(fileName);
out = new DataOutputStream(new BufferedOutputStream(fos));
VM vm = VM.getVM();
@ -385,6 +410,9 @@ public class HeapHprofBinWriter extends AbstractHeapGraphWriter {
FLOAT_SIZE = objectHeap.getFloatSize();
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
writeFileHeader();
@ -394,38 +422,87 @@ public class HeapHprofBinWriter extends AbstractHeapGraphWriter {
// hprof UTF-8 symbols section
writeSymbols();
// HPROF_LOAD_CLASS records for all classes
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
writeClassDumpRecords();
// this will write heap data into the buffer stream
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.
out.flush();
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
long dumpEnd = chn.position();
long dumpEnd = fos.getChannel().position();
// 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
chn.position(dumpStart);
fos.getChannel().position(currentSegmentStart);
int dumpLen = (int) dumpLenLong;
// write length as integer
fos.write((dumpLen >>> 24) & 0xFF);
@ -433,8 +510,8 @@ public class HeapHprofBinWriter extends AbstractHeapGraphWriter {
fos.write((dumpLen >>> 8) & 0xFF);
fos.write((dumpLen >>> 0) & 0xFF);
// close the file stream
fos.close();
//Reset to previous current position
fos.getChannel().position(currentPosition);
}
private void writeClassDumpRecords() throws IOException {
@ -443,7 +520,9 @@ public class HeapHprofBinWriter extends AbstractHeapGraphWriter {
sysDict.allClassesDo(new SystemDictionary.ClassVisitor() {
public void visit(Klass k) {
try {
writeHeapRecordPrologue();
writeClassDumpRecord(k);
writeHeapRecordEpilogue();
} catch (IOException e) {
throw new RuntimeException(e);
}
@ -884,7 +963,12 @@ public class HeapHprofBinWriter extends AbstractHeapGraphWriter {
// writes hprof binary file header
private void writeFileHeader() throws IOException {
// 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');
// 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 DataOutputStream out;
private FileOutputStream fos;
private Debugger dbg;
private ObjectHeap objectHeap;
private SymbolTable symTbl;
@ -983,6 +1068,10 @@ public class HeapHprofBinWriter extends AbstractHeapGraphWriter {
// oopSize of the debuggee
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 BYTE_BASE_OFFSET;
private long CHAR_BASE_OFFSET;
@ -1005,6 +1094,7 @@ public class HeapHprofBinWriter extends AbstractHeapGraphWriter {
private static class ClassData {
int instSize;
List fields;
ClassData(int instSize, List fields) {
this.instSize = instSize;
this.fields = fields;

View file

@ -35,7 +35,7 @@ HOTSPOT_VM_COPYRIGHT=Copyright 2013
HS_MAJOR_VER=25
HS_MINOR_VER=0
HS_BUILD_NUMBER=53
HS_BUILD_NUMBER=54
JDK_MAJOR_VER=1
JDK_MINOR_VER=8

View file

@ -44,6 +44,7 @@ CXX=cl.exe
# /GS Inserts security stack checks in some functions (VS2005 default)
# /Oi Use intrinsics (in /O2)
# /Od Disable all optimizations
# /MP Use multiple cores for compilation
#
# 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
GX_OPTION = /EHsc
LD_FLAGS = /manifest $(LD_FLAGS)
MP_FLAG = /MP
# Manifest Tool - used in VS2005 and later to adjust manifests stored
# as resources inside build artifacts.
!if "x$(MT)" == "x"
@ -222,6 +224,7 @@ FASTDEBUG_OPT_OPTION = /O2 /Oy-
DEBUG_OPT_OPTION = /Od
GX_OPTION = /EHsc
LD_FLAGS = /manifest $(LD_FLAGS)
MP_FLAG = /MP
# Manifest Tool - used in VS2005 and later to adjust manifests stored
# as resources inside build artifacts.
!if "x$(MT)" == "x"
@ -238,6 +241,7 @@ FASTDEBUG_OPT_OPTION = /O2 /Oy-
DEBUG_OPT_OPTION = /Od
GX_OPTION = /EHsc
LD_FLAGS = /manifest $(LD_FLAGS)
MP_FLAG = /MP
# Manifest Tool - used in VS2005 and later to adjust manifests stored
# as resources inside build artifacts.
!if "x$(MT)" == "x"
@ -250,6 +254,8 @@ SAFESEH_FLAG = /SAFESEH
LD_FLAGS = $(SAFESEH_FLAG) $(LD_FLAGS)
!endif
CXX_FLAGS = $(CXX_FLAGS) $(MP_FLAG)
# If NO_OPTIMIZATIONS is defined in the environment, turn everything off
!ifdef NO_OPTIMIZATIONS
PRODUCT_OPT_OPTION = $(DEBUG_OPT_OPTION)

View file

@ -38,7 +38,7 @@ default:: $(BUILD_PCH_FILE) $(AOUT) checkAndBuildSA
!include ../local.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 local.make

View file

@ -102,7 +102,10 @@ SA_CFLAGS = $(SA_CFLAGS) -ZI
!if "$(MT)" != ""
SA_LD_FLAGS = -manifest $(SA_LD_FLAGS)
!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)
!if "$(ENABLE_FULL_DEBUG_SYMBOLS)" == "1"
SA_LFLAGS = $(SA_LFLAGS) -map -debug
@ -111,22 +114,24 @@ SA_LFLAGS = $(SA_LFLAGS) -map -debug
SA_LFLAGS = $(SAFESEH_FLAG) $(SA_LFLAGS)
!endif
SA_CFLAGS = $(SA_CFLAGS) $(MP_FLAG)
# Note that we do not keep sawindbj.obj around as it would then
# 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
# 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:
$(SAWINDBG): $(SASRCFILE)
$(SAWINDBG): $(SASRCFILES)
set INCLUDE=$(SA_INCLUDE)$(INCLUDE)
$(CXX) @<<
-I"$(BootStrapDir)/include" -I"$(BootStrapDir)/include/win32"
-I"$(GENERATED)" $(SA_CFLAGS)
$(SASRCFILE)
$(SASRCFILES)
-out:$*.obj
<<
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)" != ""
$(MT) -manifest $(@F).manifest -outputresource:$(@F);#2
!endif

View file

@ -37,6 +37,9 @@
#include "runtime/vframeArray.hpp"
#include "utilities/macros.hpp"
#include "vmreg_sparc.inline.hpp"
#if INCLUDE_ALL_GCS
#include "gc_implementation/g1/g1SATBCardTableModRefBS.hpp"
#endif
// Implementation of StubAssembler
@ -912,7 +915,7 @@ OopMapSet* Runtime1::generate_code_for(StubID id, StubAssembler* sasm) {
Register tmp2 = G3_scratch;
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
__ 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>
__ 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");
__ 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.
// Use return-from-leaf
__ retl();

View file

@ -3752,7 +3752,7 @@ static void generate_dirty_card_log_enqueue(jbyte* byte_map_base) {
#define __ masm.
address start = __ pc();
Label not_already_dirty, restart, refill;
Label not_already_dirty, restart, refill, young_card;
#ifdef _LP64
__ 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>
__ 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");
__ 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.
// Use return-from-leaf
__ retl();

View file

@ -38,6 +38,9 @@
#include "runtime/vframeArray.hpp"
#include "utilities/macros.hpp"
#include "vmreg_x86.inline.hpp"
#if INCLUDE_ALL_GCS
#include "gc_implementation/g1/g1SATBCardTableModRefBS.hpp"
#endif
// Implementation of StubAssembler
@ -1753,13 +1756,17 @@ OopMapSet* Runtime1::generate_code_for(StubID id, StubAssembler* sasm) {
__ leal(card_addr, __ as_Address(ArrayAddress(cardtable, index)));
#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);
// storing region crossing non-NULL, card is clean.
// dirty card and log.
__ movb(Address(card_addr, 0), 0);
__ movb(Address(card_addr, 0), (int)CardTableModRefBS::dirty_card_val());
__ cmpl(queue_index, 0);
__ jcc(Assembler::equal, runtime);

View file

@ -3389,13 +3389,18 @@ void MacroAssembler::g1_write_barrier_post(Register store_addr,
const Register card_addr = tmp;
lea(card_addr, as_Address(ArrayAddress(cardtable, index)));
#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);
// storing a region crossing, non-NULL oop, card is clean.
// dirty card and log.
movb(Address(card_addr, 0), 0);
movb(Address(card_addr, 0), (int)CardTableModRefBS::dirty_card_val());
cmpl(queue_index, 0);
jcc(Assembler::equal, runtime);

View file

@ -42,7 +42,7 @@
#ifdef __APPLE__
typedef thread_t thread_id_t;
#else
typedef pthread_t thread_id_t;
typedef pid_t thread_id_t;
#endif
// _pthread_id is the pthread id, which is used by library calls

View file

@ -100,6 +100,7 @@
# include <stdint.h>
# include <inttypes.h>
# include <sys/ioctl.h>
# include <sys/syscall.h>
#if defined(__FreeBSD__) || defined(__NetBSD__)
# include <elf.h>
@ -152,6 +153,7 @@ sigset_t SR_sigset;
// utility functions
static int SR_initialize();
static void unpackTime(timespec* absTime, bool isAbsolute, jlong time);
julong os::available_memory() {
return Bsd::available_memory();
@ -247,7 +249,17 @@ void os::Bsd::initialize_system_info() {
* since it returns a 64 bit value)
*/
mib[0] = CTL_HW;
#if defined (HW_MEMSIZE) // Apple
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);
if (sysctl(mib, 2, &mem_val, &len, NULL, 0) != -1) {
assert(len == sizeof(mem_val), "unexpected data size");
@ -679,18 +691,12 @@ static void *java_start(Thread *thread) {
return NULL;
}
#ifdef __APPLE__
// 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);
osthread->set_thread_id(os::Bsd::gettid());
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");
osthread->set_unique_thread_id(unique_thread_id);
#else
// thread_id is pthread_id on BSD
osthread->set_thread_id(::pthread_self());
#endif
// initialize signal mask for this thread
os::Bsd::hotspot_sigmask(thread);
@ -847,18 +853,13 @@ bool os::create_attached_thread(JavaThread* thread) {
return false;
}
osthread->set_thread_id(os::Bsd::gettid());
// Store pthread info into the OSThread
#ifdef __APPLE__
// 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, "just checking");
osthread->set_thread_id(thread_id);
uint64_t unique_thread_id = locate_unique_thread_id(thread_id);
uint64_t unique_thread_id = locate_unique_thread_id(osthread->thread_id());
guarantee(unique_thread_id != 0, "just checking");
osthread->set_unique_thread_id(unique_thread_id);
#else
osthread->set_thread_id(::pthread_self());
#endif
osthread->set_pthread_id(::pthread_self());
@ -1125,6 +1126,30 @@ size_t os::lasterror(char *buf, size_t len) {
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() {
#ifdef __APPLE__
return (intx)::pthread_mach_thread_np(::pthread_self());
@ -1132,6 +1157,7 @@ intx os::current_thread_id() {
return (intx)::pthread_self();
#endif
}
int os::current_process_id() {
// 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);
private:
jlong currenttime() const;
semaphore_t _semaphore;
os_semaphore_t _semaphore;
};
Semaphore::Semaphore() : _semaphore(0) {
@ -1972,7 +1998,7 @@ bool Semaphore::trywait() {
bool Semaphore::timedwait(unsigned int sec, int nsec) {
struct timespec ts;
jlong endtime = unpackTime(&ts, false, (sec * NANOSECS_PER_SEC) + nsec);
unpackTime(&ts, false, (sec * NANOSECS_PER_SEC) + nsec);
while (1) {
int result = sem_timedwait(&_semaphore, &ts);

View file

@ -84,6 +84,7 @@ class Bsd {
static void hotspot_sigmask(Thread* thread);
static bool is_initial_thread(void);
static pid_t gettid();
static int page_size(void) { return _page_size; }
static void set_page_size(int val) { _page_size = val; }

View file

@ -53,7 +53,7 @@
// Defines Linux-specific default values. The flags are available on all
// 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, UseOSErrorReporting, false);
define_pd_global(bool, UseThreadPriorities, true) ;

View file

@ -3361,13 +3361,15 @@ bool os::Linux::setup_large_page_type(size_t page_size) {
if (FLAG_IS_DEFAULT(UseHugeTLBFS) &&
FLAG_IS_DEFAULT(UseSHM) &&
FLAG_IS_DEFAULT(UseTransparentHugePages)) {
// If UseLargePages is specified on the command line try all methods,
// if it's default, then try only UseTransparentHugePages.
if (FLAG_IS_DEFAULT(UseLargePages)) {
UseTransparentHugePages = true;
} else {
UseHugeTLBFS = UseTransparentHugePages = UseSHM = true;
}
// The type of large pages has not been specified by the user.
// Try UseHugeTLBFS and then UseSHM.
UseHugeTLBFS = 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) {
@ -3393,9 +3395,19 @@ bool os::Linux::setup_large_page_type(size_t page_size) {
}
void os::large_page_init() {
if (!UseLargePages) {
UseHugeTLBFS = false;
if (!UseLargePages &&
!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;
UseHugeTLBFS = false;
UseSHM = false;
return;
}

View file

@ -4080,8 +4080,7 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
// Generate any default methods - default methods are interface methods
// that have a default implementation. This is new with Lambda project.
if (has_default_methods && !access_flags.is_interface() &&
local_interfaces->length() > 0) {
if (has_default_methods && !access_flags.is_interface() ) {
DefaultMethods::generate_default_methods(
this_klass(), &all_mirandas, CHECK_(nullHandle));
}

View file

@ -345,7 +345,6 @@ class MethodFamily : public ResourceObj {
}
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;
public:
@ -404,20 +403,19 @@ class MethodFamily : public ResourceObj {
_exception_message = generate_no_defaults_message(CHECK);
_exception_name = vmSymbols::java_lang_AbstractMethodError();
} else if (qualified_methods.length() == 1) {
// leave abstract methods alone, they will be found via normal search path
Method* method = qualified_methods.at(0);
if (method->is_abstract()) {
_exception_message = generate_abstract_method_message(method, CHECK);
_exception_name = vmSymbols::java_lang_AbstractMethodError();
} else {
if (!method->is_abstract()) {
_selected_target = qualified_methods.at(0);
}
} else {
_exception_message = generate_conflicts_message(&qualified_methods,CHECK);
_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) {
@ -475,20 +473,6 @@ Symbol* MethodFamily::generate_no_defaults_message(TRAPS) const {
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 {
stringStream ss;
ss.print("Conflicting default methods:");
@ -595,6 +579,18 @@ class EmptyVtableSlot : public ResourceObj {
#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(
InstanceKlass* klass, GrowableArray<Method*>* mirandas, TRAPS) {
@ -604,8 +600,10 @@ static GrowableArray<EmptyVtableSlot*>* find_empty_vtable_slots(
// All miranda methods are obvious candidates
for (int i = 0; i < mirandas->length(); ++i) {
EmptyVtableSlot* slot = new EmptyVtableSlot(mirandas->at(i));
slots->append(slot);
Method* m = mirandas->at(i);
if (!already_in_vtable_slots(slots, m)) {
slots->append(new EmptyVtableSlot(m));
}
}
// 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.
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));
}
}
}
}
// 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();
}
@ -679,7 +696,7 @@ class FindMethodsByErasedSig : public HierarchyVisitor<FindMethodsByErasedSig> {
// private interface methods are not candidates for default methods
// invokespecial to private interface methods doesn't use default method logic
// 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) {
_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);
static void generate_erased_defaults(
@ -721,6 +738,8 @@ static void generate_erased_defaults(
static void merge_in_new_methods(InstanceKlass* klass,
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
// after the classfile has been parsed if some ancestor has default methods.
@ -782,7 +801,7 @@ void DefaultMethods::generate_default_methods(
}
#endif // ndef PRODUCT
create_overpasses(empty_slots, klass, CHECK);
create_defaults_and_exceptions(empty_slots, klass, CHECK);
#ifndef PRODUCT
if (TraceDefaultMethods) {
@ -791,66 +810,6 @@ void DefaultMethods::generate_default_methods(
#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(
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
// an implementation and a generically-compatible, but different, signature.
// Bridges have actual bytecode implementation in classfiles.
// An "overpass", on the other hand, performs the same function as a bridge
// but does not occur in a classfile; the VM creates overpass itself,
// when it needs a path to get from a call site to an default method, and
// a bridge doesn't exist.
static void create_overpasses(
// Create default_methods list for the current class.
// With the VM only processing erased signatures, the VM only
// creates an overpass in a conflict case or a case with no candidates.
// This allows virtual methods to override the overpass, but ensures
// that a local method search will find the exception rather than an abstract
// or default method that is not a valid candidate.
static void create_defaults_and_exceptions(
GrowableArray<EmptyVtableSlot*>* slots,
InstanceKlass* klass, TRAPS) {
GrowableArray<Method*> overpasses;
GrowableArray<Method*> defaults;
BytecodeConstantPool bpool(klass->constants());
for (int i = 0; i < slots->length(); ++i) {
@ -943,7 +902,6 @@ static void create_overpasses(
if (slot->is_bound()) {
MethodFamily* method = slot->get_binding();
int max_stack = 0;
BytecodeBuffer buffer;
#ifndef PRODUCT
@ -953,26 +911,27 @@ static void create_overpasses(
tty->print_cr("");
if (method->has_target()) {
method->print_selected(tty, 1);
} else {
} else if (method->throws_exception()) {
method->print_exception(tty, 1);
}
}
#endif // ndef PRODUCT
if (method->has_target()) {
Method* selected = method->get_selected_target();
if (selected->method_holder()->is_interface()) {
max_stack = assemble_redirect(
&bpool, &buffer, slot->signature(), selected, CHECK);
defaults.push(selected);
}
} else if (method->throws_exception()) {
max_stack = assemble_method_error(&bpool, &buffer, method->get_exception_name(), method->get_exception_message(), CHECK);
}
if (max_stack != 0) {
int max_stack = assemble_method_error(&bpool, &buffer,
method->get_exception_name(), method->get_exception_message(), CHECK);
AccessFlags flags = accessFlags_from(
JVM_ACC_PUBLIC | JVM_ACC_SYNTHETIC | JVM_ACC_BRIDGE);
Method* m = new_method(&bpool, &buffer, slot->name(), slot->signature(),
flags, max_stack, slot->size_of_parameters(),
ConstMethod::OVERPASS, CHECK);
// We push to the methods list:
// overpass methods which are exception throwing methods
if (m != NULL) {
overpasses.push(m);
}
@ -983,12 +942,32 @@ static void create_overpasses(
#ifndef PRODUCT
if (TraceDefaultMethods) {
tty->print_cr("Created %d overpass methods", overpasses.length());
tty->print_cr("Created %d default methods", defaults.length());
}
#endif // ndef PRODUCT
if (overpasses.length() > 0) {
switchover_constant_pool(&bpool, 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) {
// Note that this must sort using the same key as is used for sorting

View file

@ -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.
*
* This code is free software; you can redistribute it and/or modify it
@ -25,6 +25,7 @@
#include "precompiled.hpp"
#include "classfile/dictionary.hpp"
#include "classfile/systemDictionary.hpp"
#include "memory/iterator.hpp"
#include "oops/oop.inline.hpp"
#include "prims/jvmtiRedefineClassesTrace.hpp"
#include "utilities/hashtable.inline.hpp"
@ -38,17 +39,21 @@ Dictionary::Dictionary(int table_size)
: TwoOopHashtable<Klass*, mtClass>(table_size, sizeof(DictionaryEntry)) {
_current_class_index = 0;
_current_class_entry = NULL;
_pd_cache_table = new ProtectionDomainCacheTable(defaultProtectionDomainCacheSize);
};
Dictionary::Dictionary(int table_size, HashtableBucket<mtClass>* t,
int number_of_entries)
: TwoOopHashtable<Klass*, mtClass>(table_size, sizeof(DictionaryEntry), t, number_of_entries) {
_current_class_index = 0;
_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,
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);
if (!contains_protection_domain(protection_domain)) {
ProtectionDomainCacheEntry* entry = dict->cache_get(protection_domain);
ProtectionDomainEntry* new_head =
new ProtectionDomainEntry(protection_domain, _pd_set);
new ProtectionDomainEntry(entry, _pd_set);
// Warning: Preserve store ordering. The SystemDictionary is read
// without locks. The new ProtectionDomainEntry must be
// 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) {
// 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 (DictionaryEntry *probe = bucket(index);
probe != NULL;
@ -201,10 +210,13 @@ void Dictionary::always_strong_oops_do(OopClosure* blk) {
Klass* e = probe->klass();
ClassLoaderData* loader_data = probe->loader_data();
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) {
for (int index = 0; index < table_size(); index++) {
for (DictionaryEntry* probe = bucket(index);
probe != NULL;
probe = probe->next()) {
probe->protection_domain_set_oops_do(f);
// Only the protection domain oops contain references into the heap. Iterate
// over all of them.
_pd_cache_table->oops_do(f);
}
}
}
void Dictionary::methods_do(void f(Method*)) {
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() {
while (true) {
@ -306,7 +317,6 @@ Klass* Dictionary::try_get_next_class() {
// never reached
}
// Add a loaded class to the system dictionary.
// Readers of the SystemDictionary aren't always locked, so _buckets
// 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,
"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()),
"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)
: Hashtable<Symbol*, mtSymbol>(table_size, sizeof(SymbolPropertyEntry))
{
@ -532,11 +682,13 @@ void Dictionary::print() {
tty->cr();
}
}
tty->cr();
_pd_cache_table->print();
tty->cr();
}
#endif
void Dictionary::verify() {
guarantee(number_of_entries() >= 0, "Verify of system dictionary failed");
@ -563,5 +715,7 @@ void Dictionary::verify() {
guarantee(number_of_entries() == element_count,
"Verify of system dictionary failed");
debug_only(verify_lookup_length((double)number_of_entries() / table_size()));
_pd_cache_table->verify();
}

View file

@ -27,11 +27,14 @@
#include "classfile/systemDictionary.hpp"
#include "oops/instanceKlass.hpp"
#include "oops/oop.hpp"
#include "oops/oop.inline.hpp"
#include "utilities/hashtable.hpp"
class DictionaryEntry;
class PSPromotionManager;
class ProtectionDomainCacheTable;
class ProtectionDomainCacheEntry;
class BoolObjectClosure;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// The data structure for the system dictionary (and the shared system
@ -45,6 +48,8 @@ private:
// pointer to the current hash table entry.
static DictionaryEntry* _current_class_entry;
ProtectionDomainCacheTable* _pd_cache_table;
DictionaryEntry* get_entry(int index, unsigned int hash,
Symbol* name, ClassLoaderData* loader_data);
@ -93,6 +98,7 @@ public:
void methods_do(void f(Method*));
void unlink(BoolObjectClosure* is_alive);
// Classes loaded by the bootstrap loader are always strongly reachable.
// If we're not doing class unloading, all classes are strongly reachable.
@ -118,6 +124,7 @@ public:
// Sharing support
void reorder_dictionary();
ProtectionDomainCacheEntry* cache_get(oop protection_domain);
#ifndef PRODUCT
void print();
@ -126,21 +133,112 @@ public:
};
// 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> {
friend class VMStructs;
public:
ProtectionDomainEntry* _next;
oop _protection_domain;
ProtectionDomainCacheEntry* _pd_cache;
ProtectionDomainEntry(oop protection_domain, ProtectionDomainEntry* next) {
_protection_domain = protection_domain;
ProtectionDomainEntry(ProtectionDomainCacheEntry* pd_cache, ProtectionDomainEntry* next) {
_pd_cache = pd_cache;
_next = 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
@ -151,6 +249,24 @@ class DictionaryEntry : public HashtableEntry<Klass*, mtClass> {
private:
// Contains the set of approved protection domains that can access
// 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;
ClassLoaderData* _loader_data;
@ -158,7 +274,7 @@ class DictionaryEntry : public HashtableEntry<Klass*, mtClass> {
// Tells whether a protection is in the approved set.
bool contains_protection_domain(oop protection_domain) const;
// 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_addr() { return (Klass**)literal_addr(); }
@ -189,12 +305,11 @@ class DictionaryEntry : public HashtableEntry<Klass*, mtClass> {
: contains_protection_domain(protection_domain());
}
void protection_domain_set_oops_do(OopClosure* f) {
void set_strongly_reachable() {
for (ProtectionDomainEntry* current = _pd_set;
current != NULL;
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;
current != NULL;
current = current->_next) {
current->_protection_domain->verify();
current->_pd_cache->protection_domain()->verify();
}
}

View file

@ -1376,8 +1376,15 @@ char* java_lang_Throwable::print_stack_element_to_buffer(Handle mirror,
const char* klass_name = holder->external_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);
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();
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;
}
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
Klass* k = SystemDictionary::StackTraceElement_klass();
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);
java_lang_StackTraceElement::set_declaringClass(element(), classname);
// Fill in method name
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);
java_lang_StackTraceElement::set_methodName(element(), methodname);

View file

@ -107,18 +107,13 @@ private:
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);
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)
: Hashtable<Symbol*, mtSymbol>(symbol_table_size, sizeof (HashtableEntry<Symbol*, mtSymbol>), t,
: Hashtable<Symbol*, mtSymbol>(SymbolTableSize, sizeof (HashtableEntry<Symbol*, mtSymbol>), t,
number_of_entries) {}
// Arena for permanent symbols (null class loader) that are never unloaded
@ -136,6 +131,9 @@ public:
// The symbol 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() {
assert(_the_table == NULL, "One symbol table allowed.");
_the_table = new SymbolTable();
@ -145,8 +143,11 @@ public:
static void create_table(HashtableBucket<mtSymbol>* t, int length,
int number_of_entries) {
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);
// if CDS give symbol table a default arena size since most symbols
// are already allocated in the shared misc section.

View file

@ -1697,6 +1697,24 @@ int SystemDictionary::calculate_systemdictionary_size(int classcount) {
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
// Note: anonymous classes are not in the SD.
bool SystemDictionary::do_unloading(BoolObjectClosure* is_alive) {
@ -1708,6 +1726,14 @@ bool SystemDictionary::do_unloading(BoolObjectClosure* is_alive) {
constraints()->purge_loader_constraints();
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;
}

View file

@ -2441,6 +2441,11 @@ void ClassVerifier::verify_invoke_instructions(
current_class()->super()->name()))) {
bool subtype = ref_class_type.is_assignable_from(
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) {
verify_error(ErrorContext::bad_code(bci),
"Bad invokespecial instruction: "
@ -2448,6 +2453,7 @@ void ClassVerifier::verify_invoke_instructions(
return;
}
}
}
// Match method descriptor with operand stack
for (int i = nargs - 1; i >= 0; i--) { // Run backwards
current_frame->pop_stack(sig_types[i], CHECK_VERIFY(this));
@ -2461,7 +2467,28 @@ void ClassVerifier::verify_invoke_instructions(
} else { // other methods
// Ensures that target class is assignable to method class.
if (opcode == Bytecodes::_invokespecial) {
if (!current_class()->is_anonymous()) {
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) {
VerificationType stack_object_type =
current_frame->pop_stack(ref_class_type, CHECK_VERIFY(this));

View file

@ -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.
*
* This code is free software; you can redistribute it and/or modify it
@ -812,8 +812,8 @@ class ClassHierarchyWalker {
Klass* k = ctxk;
Method* lm = k->lookup_method(m->name(), m->signature());
if (lm == NULL && k->oop_is_instance()) {
// It might be an abstract interface method, devoid of mirandas.
lm = ((InstanceKlass*)k)->lookup_method_in_all_interfaces(m->name(),
// It might be an interface method
lm = ((InstanceKlass*)k)->lookup_method_in_ordered_interfaces(m->name(),
m->signature());
}
if (lm == m)

View file

@ -6035,8 +6035,12 @@ void G1CollectedHeap::verify_dirty_region(HeapRegion* hr) {
// is dirty.
G1SATBCardTableModRefBS* ct_bs = g1_barrier_set();
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);
}
}
void G1CollectedHeap::verify_dirty_young_list(HeapRegion* head) {
G1SATBCardTableModRefBS* ct_bs = g1_barrier_set();

View file

@ -29,6 +29,7 @@
#include "gc_implementation/g1/g1CollectedHeap.hpp"
#include "gc_implementation/g1/g1AllocRegion.inline.hpp"
#include "gc_implementation/g1/g1CollectorPolicy.hpp"
#include "gc_implementation/g1/g1SATBCardTableModRefBS.hpp"
#include "gc_implementation/g1/heapRegionSeq.inline.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");
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 {

View file

@ -319,10 +319,10 @@ G1CollectorPolicy::G1CollectorPolicy() :
}
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 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) {
vm_exit_during_initialization("Invalid survivor ratio specified");
}

View file

@ -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()) {
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.
jbyte new_val = val;
if (val == clean_card_val()) {
@ -85,6 +91,19 @@ bool G1SATBCardTableModRefBS::mark_card_deferred(size_t card_index) {
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(MemRegion whole_heap,
int max_covered_regions) :
@ -97,7 +116,11 @@ G1SATBCardTableLoggingModRefBS(MemRegion whole_heap,
void
G1SATBCardTableLoggingModRefBS::write_ref_field_work(void* field,
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) {
*byte = dirty_card;
Thread* thr = Thread::current();
@ -129,7 +152,7 @@ G1SATBCardTableLoggingModRefBS::write_ref_field_static(void* field,
void
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());
Thread* thr = Thread::current();
if (whole_heap) {
@ -138,25 +161,35 @@ G1SATBCardTableLoggingModRefBS::invalidate(MemRegion mr, bool whole_heap) {
byte++;
}
} else {
// skip all consecutive young cards
for (; byte <= last_byte && *byte == g1_young_gen; byte++);
if (byte <= last_byte) {
OrderAccess::storeload();
// Enqueue if necessary.
if (thr->is_Java_thread()) {
JavaThread* jt = (JavaThread*)thr;
while (byte <= last_byte) {
for (; byte <= last_byte; byte++) {
if (*byte == g1_young_gen) {
continue;
}
if (*byte != dirty_card) {
*byte = dirty_card;
jt->dirty_card_queue().enqueue(byte);
}
byte++;
}
} else {
MutexLockerEx x(Shared_DirtyCardQ_lock,
Mutex::_no_safepoint_check_flag);
while (byte <= last_byte) {
for (; byte <= last_byte; byte++) {
if (*byte == g1_young_gen) {
continue;
}
if (*byte != dirty_card) {
*byte = dirty_card;
_dcqs.shared_dirty_card_queue()->enqueue(byte);
}
byte++;
}
}
}
}

View file

@ -38,7 +38,14 @@ class DirtyCardQueueSet;
// snapshot-at-the-beginning marking.
class G1SATBCardTableModRefBS: public CardTableModRefBSForCTRS {
protected:
enum G1CardValues {
g1_young_gen = CT_MR_BS_last_reserved << 1
};
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
// pre-marking object graph.
static void enqueue(oop pre_val);
@ -118,6 +125,9 @@ public:
_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 is_card_deferred(size_t card_index) {

View file

@ -80,6 +80,10 @@ public:
void reset() { if (_buf != NULL) _index = _sz; }
void enqueue(volatile void* ptr) {
enqueue((void*)(ptr));
}
// Enqueues the given "obj".
void enqueue(void* ptr) {
if (!_active) return;

View file

@ -214,9 +214,6 @@ class VM_CollectForMetadataAllocation: public VM_GC_Operation {
: VM_GC_Operation(gc_count_before, gc_cause, full_gc_count_before, true),
_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 void doit();
MetaWord* result() const { return _result; }

View file

@ -202,12 +202,6 @@ void CollectedHeap::collect_as_vm_thread(GCCause::Cause cause) {
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() {
// Used for ReduceInitialCardMarks (when COMPILER2 is used);

View file

@ -475,11 +475,6 @@ class CollectedHeap : public CHeapObj<mtInternal> {
// the context of the vm thread.
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
BarrierSet* barrier_set() { return _barrier_set; }

View file

@ -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.
*
* 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
// 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) {
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) {
vmIntrinsics::ID iid = result_oop->intrinsic_id();
if (MethodHandles::is_signature_polymorphic(iid)) {
@ -234,6 +244,7 @@ void LinkResolver::lookup_method_in_klasses(methodHandle& result, KlassHandle kl
}
// 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) {
Method* result_oop = klass->uncached_lookup_method(name, signature);
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());
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);
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) {
@ -625,6 +661,12 @@ void LinkResolver::resolve_interface_method(methodHandle& resolved_method,
resolved_method->method_holder()->internal_name()
);
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();
}
}
@ -853,6 +895,7 @@ void LinkResolver::linktime_resolve_special_method(methodHandle& resolved_method
resolved_method->signature()));
THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(), buf);
}
if (TraceItables && Verbose) {
ResourceMark rm(THREAD);
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->access_flags().print_on(tty);
if (resolved_method->method_holder()->is_interface() &&
!resolved_method->is_abstract()) {
if (resolved_method->is_default_method()) {
tty->print("default");
}
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->access_flags().print_on(tty);
if (sel_method->method_holder()->is_interface() &&
!sel_method->is_abstract()) {
if (sel_method->is_default_method()) {
tty->print("default");
}
if (sel_method->is_overpass()) {
tty->print("overpass");
}
tty->cr();
}
@ -1007,8 +1051,7 @@ void LinkResolver::linktime_resolve_virtual_method(methodHandle &resolved_method
resolved_method->method_holder()->internal_name()
);
resolved_method->access_flags().print_on(tty);
if (resolved_method->method_holder()->is_interface() &&
!resolved_method->is_abstract()) {
if (resolved_method->is_default_method()) {
tty->print("default");
}
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
if (resolved_method->method_holder()->is_interface()) { // miranda method
vtable_index = vtable_index_of_miranda_method(resolved_klass,
resolved_method->name(),
resolved_method->signature(), CHECK);
vtable_index = vtable_index_of_interface_method(resolved_klass,
resolved_method, CHECK);
assert(vtable_index >= 0 , "we should have valid vtable index at this point");
InstanceKlass* inst = InstanceKlass::cast(recv_klass());
@ -1104,11 +1145,10 @@ void LinkResolver::runtime_resolve_virtual_method(CallInfo& result,
vtable_index
);
selected_method->access_flags().print_on(tty);
if (selected_method->method_holder()->is_interface() &&
!selected_method->is_abstract()) {
if (selected_method->is_default_method()) {
tty->print("default");
}
if (resolved_method->is_overpass()) {
if (selected_method->is_overpass()) {
tty->print("overpass");
}
tty->cr();
@ -1191,7 +1231,6 @@ void LinkResolver::runtime_resolve_interface_method(CallInfo& result, methodHand
sel_method->name(),
sel_method->signature()));
}
// check if abstract
if (check_null_and_abstract && sel_method->is_abstract()) {
ResourceMark rm(THREAD);
@ -1220,11 +1259,10 @@ void LinkResolver::runtime_resolve_interface_method(CallInfo& result, methodHand
sel_method->method_holder()->internal_name()
);
sel_method->access_flags().print_on(tty);
if (sel_method->method_holder()->is_interface() &&
!sel_method->is_abstract()) {
if (sel_method->is_default_method()) {
tty->print("default");
}
if (resolved_method->is_overpass()) {
if (sel_method->is_overpass()) {
tty->print("overpass");
}
tty->cr();

View file

@ -130,8 +130,7 @@ class LinkResolver: AllStatic {
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);
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_pool (KlassHandle& resolved_klass, Symbol*& method_name, Symbol*& method_signature, KlassHandle& current_klass, constantPoolHandle pool, int index, TRAPS);

View file

@ -47,85 +47,53 @@
// 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() {
assert(max_alignment() >= min_alignment(),
assert(_max_alignment >= _min_alignment,
err_msg("max_alignment: " SIZE_FORMAT " less than min_alignment: " SIZE_FORMAT,
max_alignment(), min_alignment()));
assert(max_alignment() % min_alignment() == 0,
_max_alignment, _min_alignment));
assert(_max_alignment % _min_alignment == 0,
err_msg("max_alignment: " SIZE_FORMAT " not aligned by min_alignment: " SIZE_FORMAT,
max_alignment(), min_alignment()));
_max_alignment, _min_alignment));
if (MaxHeapSize < InitialHeapSize) {
vm_exit_during_initialization("Incompatible initial and maximum heap sizes specified");
}
// Do not use FLAG_SET_ERGO to update MaxMetaspaceSize, since this will
// 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");
}
MinHeapDeltaBytes = align_size_up(MinHeapDeltaBytes, _min_alignment);
}
void CollectorPolicy::initialize_size_info() {
// User inputs from -mx and ms must be aligned
set_min_heap_byte_size(align_size_up(Arguments::min_heap_size(), min_alignment()));
set_initial_heap_byte_size(align_size_up(InitialHeapSize, min_alignment()));
set_max_heap_byte_size(align_size_up(MaxHeapSize, max_alignment()));
_min_heap_byte_size = align_size_up(Arguments::min_heap_size(), _min_alignment);
_initial_heap_byte_size = align_size_up(InitialHeapSize, _min_alignment);
_max_heap_byte_size = align_size_up(MaxHeapSize, _max_alignment);
// Check heap parameter properties
if (initial_heap_byte_size() < M) {
if (_initial_heap_byte_size < M) {
vm_exit_during_initialization("Too small initial heap");
}
// Check heap parameter properties
if (min_heap_byte_size() < M) {
if (_min_heap_byte_size < M) {
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
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");
}
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");
}
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");
}
if (PrintGCDetails && Verbose) {
gclog_or_tty->print_cr("Minimum heap " SIZE_FORMAT " Initial heap "
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 x = base_size / (NewRatio+1);
size_t new_gen_size = x > min_alignment() ?
align_size_down(x, min_alignment()) :
min_alignment();
size_t new_gen_size = x > _min_alignment ?
align_size_down(x, _min_alignment) :
_min_alignment;
return new_gen_size;
}
size_t GenCollectorPolicy::bound_minus_alignment(size_t desired_size,
size_t maximum_size) {
size_t alignment = min_alignment();
size_t alignment = _min_alignment;
size_t max_minus = maximum_size - alignment;
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() {
// All sizes must be multiples of the generation granularity.
set_min_alignment((uintx) Generation::GenGrain);
set_max_alignment(compute_max_alignment());
_min_alignment = (uintx) Generation::GenGrain;
_max_alignment = compute_max_alignment();
CollectorPolicy::initialize_flags();
@ -218,26 +186,26 @@ void GenCollectorPolicy::initialize_flags() {
if (NewSize > MaxNewSize) {
MaxNewSize = NewSize;
}
NewSize = align_size_down(NewSize, min_alignment());
MaxNewSize = align_size_down(MaxNewSize, min_alignment());
NewSize = align_size_down(NewSize, _min_alignment);
MaxNewSize = align_size_down(MaxNewSize, _min_alignment);
// Check validity of heap flags
assert(NewSize % min_alignment() == 0, "eden space alignment");
assert(MaxNewSize % min_alignment() == 0, "survivor space alignment");
assert(NewSize % _min_alignment == 0, "eden 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
vm_exit_during_initialization("Too small new size specified");
}
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() {
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)) {
// 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");
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;
InitialHeapSize = calculated_heapsize;
}
MaxHeapSize = align_size_up(MaxHeapSize, max_alignment());
MaxHeapSize = align_size_up(MaxHeapSize, _max_alignment);
// adjust max heap size if necessary
if (NewSize + OldSize > MaxHeapSize) {
@ -260,18 +228,18 @@ void TwoGenerationCollectorPolicy::initialize_flags() {
uintx calculated_size = NewSize + OldSize;
double shrink_factor = (double) MaxHeapSize / calculated_size;
// 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
// max_alignment(), and we just made sure that NewSize is aligned to
// min_alignment(). In initialize_flags() we verified that max_alignment()
// is a multiple of min_alignment().
// _max_alignment, and we just made sure that NewSize is aligned to
// _min_alignment. In initialize_flags() we verified that _max_alignment
// is a multiple of _min_alignment.
OldSize = MaxHeapSize - NewSize;
} else {
MaxHeapSize = NewSize + OldSize;
}
}
// 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
if (NewSize + OldSize > MaxHeapSize) {
@ -281,24 +249,24 @@ void TwoGenerationCollectorPolicy::initialize_flags() {
uintx calculated_size = NewSize + OldSize;
double shrink_factor = (double) MaxHeapSize / calculated_size;
// 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
// max_alignment(), and we just made sure that NewSize is aligned to
// min_alignment(). In initialize_flags() we verified that max_alignment()
// is a multiple of min_alignment().
// _max_alignment, and we just made sure that NewSize is aligned to
// _min_alignment. In initialize_flags() we verified that _max_alignment
// is a multiple of _min_alignment.
OldSize = MaxHeapSize - NewSize;
} else {
MaxHeapSize = NewSize + OldSize;
}
}
// need to do this again
MaxHeapSize = align_size_up(MaxHeapSize, max_alignment());
MaxHeapSize = align_size_up(MaxHeapSize, _max_alignment);
always_do_update_barrier = UseConcMarkSweepGC;
// Check validity of heap flags
assert(OldSize % min_alignment() == 0, "old space alignment");
assert(MaxHeapSize % max_alignment() == 0, "maximum heap alignment");
assert(OldSize % _min_alignment == 0, "old space alignment");
assert(MaxHeapSize % _max_alignment == 0, "maximum heap alignment");
}
// Values set on the command line win over any ergonomically
@ -313,7 +281,7 @@ void TwoGenerationCollectorPolicy::initialize_flags() {
void GenCollectorPolicy::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
// collectors that sometimes causes unwanted rounding up of
// generations sizes.
@ -322,18 +290,18 @@ void GenCollectorPolicy::initialize_size_info() {
size_t max_new_size = 0;
if (FLAG_IS_CMDLINE(MaxNewSize) || FLAG_IS_ERGO(MaxNewSize)) {
if (MaxNewSize < min_alignment()) {
max_new_size = min_alignment();
if (MaxNewSize < _min_alignment) {
max_new_size = _min_alignment;
}
if (MaxNewSize >= max_heap_byte_size()) {
max_new_size = align_size_down(max_heap_byte_size() - min_alignment(),
min_alignment());
if (MaxNewSize >= _max_heap_byte_size) {
max_new_size = align_size_down(_max_heap_byte_size - _min_alignment,
_min_alignment);
warning("MaxNewSize (" SIZE_FORMAT "k) is equal to or "
"greater than the entire heap (" SIZE_FORMAT "k). A "
"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 {
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
@ -351,7 +319,7 @@ void GenCollectorPolicy::initialize_size_info() {
// just accept those choices. The choices currently made are
// not always "wise".
} 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
// would have been NewSize and because the NewRatio calculation could
// 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
// 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 generations minimum and initial must be the
// same as its maximum.
set_min_gen0_size(max_new_size);
set_initial_gen0_size(max_new_size);
set_max_gen0_size(max_new_size);
_min_gen0_size = max_new_size;
_initial_gen0_size = max_new_size;
_max_gen0_size = max_new_size;
} else {
size_t desired_new_size = 0;
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
// NewRatio is overly large, the resulting sizes can be too
// small.
_min_gen0_size = MAX2(scale_by_NewRatio_aligned(min_heap_byte_size()),
NewSize);
_min_gen0_size = MAX2(scale_by_NewRatio_aligned(_min_heap_byte_size), NewSize);
desired_new_size =
MAX2(scale_by_NewRatio_aligned(initial_heap_byte_size()),
NewSize);
MAX2(scale_by_NewRatio_aligned(_initial_heap_byte_size), NewSize);
}
assert(_min_gen0_size > 0, "Sanity check");
set_initial_gen0_size(desired_new_size);
set_max_gen0_size(max_new_size);
_initial_gen0_size = desired_new_size;
_max_gen0_size = max_new_size;
// At this point the desirable initial and minimum sizes have been
// determined without regard to the maximum sizes.
// Bound the sizes by the corresponding overall heap sizes.
set_min_gen0_size(
bound_minus_alignment(_min_gen0_size, min_heap_byte_size()));
set_initial_gen0_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()));
_min_gen0_size = bound_minus_alignment(_min_gen0_size, _min_heap_byte_size);
_initial_gen0_size = bound_minus_alignment(_initial_gen0_size, _initial_heap_byte_size);
_max_gen0_size = bound_minus_alignment(_max_gen0_size, _max_heap_byte_size);
// At this point all three sizes have been checked against the
// maximum sizes but have not been checked for consistency
// among the three.
// Final check min <= initial <= max
set_min_gen0_size(MIN2(_min_gen0_size, _max_gen0_size));
set_initial_gen0_size(
MAX2(MIN2(_initial_gen0_size, _max_gen0_size), _min_gen0_size));
set_min_gen0_size(MIN2(_min_gen0_size, _initial_gen0_size));
_min_gen0_size = MIN2(_min_gen0_size, _max_gen0_size);
_initial_gen0_size = MAX2(MIN2(_initial_gen0_size, _max_gen0_size), _min_gen0_size);
_min_gen0_size = MIN2(_min_gen0_size, _initial_gen0_size);
}
if (PrintGCDetails && Verbose) {
gclog_or_tty->print_cr("1: Minimum gen0 " SIZE_FORMAT " Initial gen0 "
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 ((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
*gen0_size_ptr = heap_size - min_gen1_size;
*gen0_size_ptr =
MAX2((uintx)align_size_down(*gen0_size_ptr, min_alignment()),
min_alignment());
MAX2((uintx)align_size_down(*gen0_size_ptr, _min_alignment), _min_alignment);
assert(*gen0_size_ptr > 0, "Min gen0 is too large");
result = true;
} else {
*gen1_size_ptr = heap_size - *gen0_size_ptr;
*gen1_size_ptr =
MAX2((uintx)align_size_down(*gen1_size_ptr, min_alignment()),
min_alignment());
MAX2((uintx)align_size_down(*gen1_size_ptr, _min_alignment), _min_alignment);
}
}
return result;
@ -480,10 +440,9 @@ void TwoGenerationCollectorPolicy::initialize_size_info() {
// The maximum gen1 size can be determined from the maximum gen0
// and maximum heap size since no explicit flags exits
// 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 =
MAX2((uintx)align_size_down(_max_gen1_size, min_alignment()),
min_alignment());
MAX2((uintx)align_size_down(_max_gen1_size, _min_alignment), _min_alignment);
// If no explicit command line flag has been set for the
// gen1 size, use what is left for gen1.
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
// the minimum, maximum and initial sizes consistent
// 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");
set_min_gen1_size(min_heap_byte_size() - min_gen0_size());
set_min_gen1_size(
MAX2((uintx)align_size_down(_min_gen1_size, min_alignment()),
min_alignment()));
set_initial_gen1_size(initial_heap_byte_size() - initial_gen0_size());
set_initial_gen1_size(
MAX2((uintx)align_size_down(_initial_gen1_size, min_alignment()),
min_alignment()));
_min_gen1_size = _min_heap_byte_size - _min_gen0_size;
_min_gen1_size =
MAX2((uintx)align_size_down(_min_gen1_size, _min_alignment), _min_alignment);
_initial_gen1_size = _initial_heap_byte_size - _initial_gen0_size;
_initial_gen1_size =
MAX2((uintx)align_size_down(_initial_gen1_size, _min_alignment), _min_alignment);
} else {
// It's been explicitly set on the command line. Use the
// OldSize and then determine the consequences.
set_min_gen1_size(OldSize);
set_initial_gen1_size(OldSize);
_min_gen1_size = OldSize;
_initial_gen1_size = OldSize;
// If the user has explicitly set an OldSize that is inconsistent
// with other command line flags, issue a warning.
// The generation minimums and the overall heap mimimum should
// be within one heap alignment.
if ((_min_gen1_size + _min_gen0_size + min_alignment()) <
min_heap_byte_size()) {
if ((_min_gen1_size + _min_gen0_size + _min_alignment) < _min_heap_byte_size) {
warning("Inconsistency between minimum heap size and minimum "
"generation sizes: using minimum heap = " SIZE_FORMAT,
min_heap_byte_size());
_min_heap_byte_size);
}
if ((OldSize > _max_gen1_size)) {
warning("Inconsistency between maximum heap size and maximum "
"generation sizes: using maximum heap = " SIZE_FORMAT
" -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
// initial size of gen0, since OldSize was explicitly set, OldSize wins.
if (adjust_gen0_sizes(&_min_gen0_size, &_min_gen1_size,
min_heap_byte_size(), OldSize)) {
_min_heap_byte_size, OldSize)) {
if (PrintGCDetails && Verbose) {
gclog_or_tty->print_cr("2: Minimum gen0 " SIZE_FORMAT " Initial gen0 "
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
if (adjust_gen0_sizes(&_initial_gen0_size, &_initial_gen1_size,
initial_heap_byte_size(), OldSize)) {
_initial_heap_byte_size, OldSize)) {
if (PrintGCDetails && Verbose) {
gclog_or_tty->print_cr("3: Minimum gen0 " SIZE_FORMAT " Initial gen0 "
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.
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
set_initial_gen1_size(MAX2(_initial_gen1_size, _min_gen1_size));
set_initial_gen1_size(MIN2(_initial_gen1_size, _max_gen1_size));
_initial_gen1_size = MAX2(_initial_gen1_size, _min_gen1_size);
_initial_gen1_size = MIN2(_initial_gen1_size, _max_gen1_size);
if (PrintGCDetails && Verbose) {
gclog_or_tty->print_cr("Minimum gen1 " SIZE_FORMAT " Initial gen1 "
SIZE_FORMAT " Maximum gen1 " SIZE_FORMAT,
min_gen1_size(), initial_gen1_size(), max_gen1_size());
_min_gen1_size, _initial_gen1_size, _max_gen1_size);
}
}

View file

@ -101,17 +101,12 @@ class CollectorPolicy : public CHeapObj<mtGC> {
// Return maximum heap alignment that may be imposed by the policy
static size_t compute_max_alignment();
void set_min_alignment(size_t align) { _min_alignment = align; }
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 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; }
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; }
void set_min_heap_byte_size(size_t v) { _min_heap_byte_size = v; }
enum Name {
CollectorPolicyKind,
@ -249,11 +244,8 @@ class GenCollectorPolicy : public CollectorPolicy {
public:
// Accessors
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; }
void set_initial_gen0_size(size_t v) { _initial_gen0_size = v; }
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;
@ -303,11 +295,8 @@ class TwoGenerationCollectorPolicy : public GenCollectorPolicy {
public:
// Accessors
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; }
void set_initial_gen1_size(size_t v) { _initial_gen1_size = v; }
size_t max_gen1_size() { return _max_gen1_size; }
void set_max_gen1_size(size_t v) { _max_gen1_size = v; }
// Inherited methods
TwoGenerationCollectorPolicy* as_two_generation_policy() { return this; }

View file

@ -26,6 +26,7 @@
#define SHARE_VM_MEMORY_FILEMAP_HPP
#include "memory/metaspaceShared.hpp"
#include "memory/metaspace.hpp"
// Layout of the file:
// header: dump of archive instance plus versioning info, datestamp, etc.

View file

@ -73,6 +73,10 @@
"Number of bytes used by the InstanceKlass::methods() array") \
f(method_ordering_bytes, IK_method_ordering, \
"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, \
"Number of bytes used by the InstanceKlass::local_interfaces() array") \
f(transitive_interfaces_bytes, IK_transitive_interfaces, \

File diff suppressed because it is too large Load diff

View file

@ -87,9 +87,10 @@ class Metaspace : public CHeapObj<mtClass> {
friend class MetaspaceAux;
public:
enum MetadataType {ClassType = 0,
NonClassType = ClassType + 1,
MetadataTypeCount = ClassType + 2
enum MetadataType {
ClassType,
NonClassType,
MetadataTypeCount
};
enum MetaspaceType {
StandardMetaspaceType,
@ -103,6 +104,9 @@ class Metaspace : public CHeapObj<mtClass> {
private:
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,
size_t chunk_word_size,
size_t chunk_bunch);
@ -123,6 +127,9 @@ class Metaspace : public CHeapObj<mtClass> {
static size_t _first_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() const { return _vsm; }
@ -191,12 +198,17 @@ class Metaspace : public CHeapObj<mtClass> {
Metaspace(Mutex* lock, MetaspaceType type);
~Metaspace();
// Initialize globals for Metaspace
static void ergo_initialize();
static void global_initialize();
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 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;
size_t used_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();
static void report_metadata_oome(ClassLoaderData* loader_data, size_t word_size,
MetadataType mdtype, TRAPS);
void print_on(outputStream* st) const;
// Debugging support
void verify();
@ -352,17 +367,10 @@ class MetaspaceAux : AllStatic {
class MetaspaceGC : AllStatic {
// The current high-water-mark for inducing a GC. When
// the capacity of all space in the virtual lists reaches this value,
// a GC is induced and the value is increased. This should be changed
// to the space actually used for allocations to avoid affects of
// 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;
// The current high-water-mark for inducing a GC.
// When committed memory of all metaspaces reaches this value,
// a GC is induced and the value is increased. Size is in bytes.
static volatile intptr_t _capacity_until_GC;
// For a CMS collection, signal that a concurrent collection should
// be started.
@ -370,20 +378,16 @@ class MetaspaceGC : AllStatic {
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; }
void set_shrink_factor(uint v) { _shrink_factor = v; }
public:
static size_t capacity_until_GC() { return _capacity_until_GC; }
static void inc_capacity_until_GC(size_t v) { _capacity_until_GC += v; }
static void dec_capacity_until_GC(size_t v) {
_capacity_until_GC = _capacity_until_GC > v ? _capacity_until_GC - v : 0;
}
static bool expand_after_GC() { return _expand_after_GC; }
static void set_expand_after_GC(bool v) { _expand_after_GC = v; }
static void initialize() { _capacity_until_GC = MetaspaceSize; }
static size_t capacity_until_GC();
static size_t inc_capacity_until_GC(size_t v);
static size_t dec_capacity_until_GC(size_t v);
static bool should_concurrent_collect() { return _should_concurrent_collect; }
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)
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
// has been used and a GC should be considered.
static bool should_expand(VirtualSpaceList* vsl, size_t word_size);
// Tells if we have can expand metaspace without hitting set limits.
static bool can_expand(size_t words, bool is_class);
// 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
// a GC.

View file

@ -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,
int itable_len,
@ -263,6 +270,8 @@ InstanceKlass::InstanceKlass(int vtable_len,
set_array_klasses(NULL);
set_methods(NULL);
set_method_ordering(NULL);
set_default_methods(NULL);
set_default_vtable_indices(NULL);
set_local_interfaces(NULL);
set_transitive_interfaces(NULL);
init_implementor();
@ -376,6 +385,21 @@ void InstanceKlass::deallocate_contents(ClassLoaderData* loader_data) {
}
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 place would be the only caller and it can share memory with transitive
// interfaces.
@ -456,14 +480,14 @@ objArrayOop InstanceKlass::signers() const {
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 java_lang_Class::init_lock(java_mirror());
}
void InstanceKlass::eager_initialize_impl(instanceKlassHandle this_oop) {
EXCEPTION_MARK;
volatile oop init_lock = this_oop->init_lock();
oop init_lock = this_oop->init_lock();
ObjectLocker ol(init_lock, THREAD);
// abort if someone beat us to the initialization
@ -608,7 +632,7 @@ bool InstanceKlass::link_class_impl(
// verification & rewriting
{
volatile oop init_lock = this_oop->init_lock();
oop init_lock = this_oop->init_lock();
ObjectLocker ol(init_lock, THREAD);
// rewritten will have been set if loader constraint error found
// 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
// Step 1
{
volatile oop init_lock = this_oop->init_lock();
oop init_lock = this_oop->init_lock();
ObjectLocker ol(init_lock, 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) {
volatile oop init_lock = this_oop->init_lock();
oop init_lock = this_oop->init_lock();
ObjectLocker ol(init_lock, THREAD);
this_oop->set_init_state(state);
ol.notify_all(CHECK);
@ -1354,32 +1378,44 @@ static int binary_search(Array<Method*>* methods, Symbol* name) {
return -1;
}
// find_method looks up the name/signature in the local methods array
Method* InstanceKlass::find_method(Symbol* name, Symbol* signature) const {
return InstanceKlass::find_method(methods(), name, signature);
}
// find_method looks up the name/signature in the local methods array
Method* InstanceKlass::find_method(
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);
if (hit != -1) {
Method* m = methods->at(hit);
// Do linear search to find matching signature. First, quick check
// for common case
if (m->signature() == signature) return m;
if (m->signature() == signature) return hit;
// search downwards through overloaded methods
int i;
for (i = hit - 1; i >= 0; --i) {
Method* m = methods->at(i);
assert(m->is_method(), "must be method");
if (m->name() != name) break;
if (m->signature() == signature) return m;
if (m->signature() == signature) return i;
}
// search upwards
for (i = hit + 1; i < methods->length(); ++i) {
Method* m = methods->at(i);
assert(m->is_method(), "must be method");
if (m->name() != name) break;
if (m->signature() == signature) return m;
if (m->signature() == signature) return i;
}
// not found
#ifdef ASSERT
@ -1387,9 +1423,8 @@ Method* InstanceKlass::find_method(
assert(index == -1, err_msg("binary search should have found entry %d", index));
#endif
}
return NULL;
return -1;
}
int InstanceKlass::find_method_by_name(Symbol* name, int* end) {
return find_method_by_name(methods(), name, end);
}
@ -1408,6 +1443,7 @@ int InstanceKlass::find_method_by_name(
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 {
Klass* klass = const_cast<InstanceKlass*>(this);
while (klass != NULL) {
@ -1418,6 +1454,21 @@ Method* InstanceKlass::uncached_lookup_method(Symbol* name, Symbol* signature) c
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
// Do NOT return private or static methods, new in JDK8 which are not externally visible
// 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;
}
#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
void InstanceKlass::add_osr_nmethod(nmethod* n) {
// 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"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"trans. interfaces: "); transitive_interfaces()->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
if (jni_ids() != NULL) {
jni_ids()->verify(this);

View file

@ -269,12 +269,18 @@ class InstanceKlass: public Klass {
// Method array.
Array<Method*>* _methods;
// Default Method Array, concrete methods inherited from interfaces
Array<Method*>* _default_methods;
// Interface (Klass*s) this class declares locally to implement.
Array<Klass*>* _local_interfaces;
// Interface (Klass*s) this class implements transitively.
Array<Klass*>* _transitive_interfaces;
// Int array containing the original order of method in the class file (for JVMTI).
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
// [access, name index, sig index, initval index, low_offset, high_offset]
// 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 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
Array<Klass*>* local_interfaces() const { return _local_interfaces; }
void set_local_interfaces(Array<Klass*>* a) {
@ -501,12 +516,18 @@ class InstanceKlass: public Klass {
Method* find_method(Symbol* name, Symbol* signature) const;
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)
Method* uncached_lookup_method(Symbol* name, Symbol* signature) const;
// lookup a method in all the interfaces that this class implements
// (returns NULL if not found)
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
// 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
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
void oop_follow_contents(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
// cannot lock it (like the mirror).
// 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:
// Static methods that are used to implement member methods where an exposed this pointer

View file

@ -83,7 +83,7 @@ void klassVtable::compute_vtable_size_and_num_mirandas(
GrowableArray<Method*> new_mirandas(20);
// 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();
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*");
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) {
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);
// 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
if (PrintVtables && Verbose) {
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: ",
supersuperklass->internal_name(),
_klass->internal_name(), (target_method() != NULL) ?
target_method()->name()->as_C_string() : "<NULL>", vtable_index);
_klass->internal_name(), sig, vtable_index);
super_method->access_flags().print_on(tty);
if (super_method->is_default_method()) {
tty->print("default");
}
tty->print("overriders flags: ");
target_method->access_flags().print_on(tty);
tty->cr();
if (target_method->is_default_method()) {
tty->print("default");
}
}
#endif /*PRODUCT*/
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.
// Only called for InstanceKlass's, i.e. not for arrays
// 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) {
ResourceMark rm;
bool allocate_new = true;
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".
// If we allocate a vtable entry, we will update it to a non-negative number.
target_method()->set_vtable_index(Method::nonvirtual_vtable_index);
}
// Static and <init> methods are never in
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.
// This method will either be assigned its own itable index later,
// 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);
}
@ -307,8 +357,15 @@ bool klassVtable::update_inherited_vtable(InstanceKlass* klass, methodHandle tar
Symbol* name = target_method()->name();
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++) {
Method* super_method = method_at(i);
// 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
InstanceKlass* super_klass = super_method->method_holder();
if ((super_klass->is_override(super_method, target_loader, target_classname, THREAD)) ||
((klass->major_version() >= VTABLE_TRANSITIVE_OVERRIDE_VERSION)
&& ((super_klass = find_transitive_override(super_klass, target_method, i, target_loader,
target_classname, THREAD)) != (InstanceKlass*)NULL))) {
if (is_default
|| ((super_klass->is_override(super_method, target_loader, target_classname, THREAD))
|| ((klass->major_version() >= VTABLE_TRANSITIVE_OVERRIDE_VERSION)
&& ((super_klass = find_transitive_override(super_klass,
target_method, i, target_loader,
target_classname, THREAD))
!= (InstanceKlass*)NULL))))
{
// overriding, so no new entry
allocate_new = false;
@ -347,7 +408,7 @@ bool klassVtable::update_inherited_vtable(InstanceKlass* klass, methodHandle tar
"%s used in the signature";
char* sig = target_method()->name_and_sig_as_C_string();
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());
char* failed_type_name = failed_type_symbol->as_C_string();
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);
if (!is_default) {
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
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: ",
_klass->internal_name(), (target_method() != NULL) ?
target_method()->name()->as_C_string() : "<NULL>", i);
target_klass->internal_name(), sig, i);
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: ");
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();
}
#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
#ifndef PRODUCT
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: ",
_klass->internal_name(), (target_method() != NULL) ?
target_method()->name()->as_C_string() : "<NULL>", i);
target_klass->internal_name(), sig,i);
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: ");
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();
}
#endif /*PRODUCT*/
@ -438,6 +535,14 @@ bool klassVtable::needs_new_vtable_entry(methodHandle target_method,
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
if (super == NULL) {
return true;
@ -526,26 +631,30 @@ bool klassVtable::is_miranda_entry_at(int i) {
if (mhk->is_interface()) {
assert(m->is_public(), "should be public");
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 false;
}
// check if a method is a miranda method, given a class's methods table and its super
// "miranda" means not static, not defined by this class, and not defined
// in super unless it is private and therefore inaccessible to this class.
// check if a method is a miranda method, given a class's methods table,
// its default_method table and its super
// "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
// Miranda methods only include public interface instance methods
// Not private methods, not static methods, not default = concrete abstract
bool klassVtable::is_miranda(Method* m, Array<Method*>* class_methods, Klass* super) {
if (m->is_static()) {
// Not private methods, not static methods, not default == concrete abstract
bool klassVtable::is_miranda(Method* m, Array<Method*>* class_methods,
Array<Method*>* default_methods, Klass* super) {
if (m->is_static() || m->is_private()) {
return false;
}
Symbol* name = m->name();
Symbol* signature = m->signature();
if (InstanceKlass::find_method(class_methods, name, signature) == NULL) {
// 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) {
// super doesn't exist
return true;
@ -557,12 +666,13 @@ bool klassVtable::is_miranda(Method* m, Array<Method*>* class_methods, Klass* su
return true;
}
}
}
return false;
}
// 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
// not null; in addition, those that are not duplicates of miranda methods
// 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(
GrowableArray<Method*>* new_mirandas, GrowableArray<Method*>* all_mirandas,
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
int num_methods = current_interface_methods->length();
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_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);
// check if it is a duplicate of a super's miranda
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,
GrowableArray<Method*>* all_mirandas,
Klass* super, Array<Method*>* class_methods,
Array<Method*>* default_methods,
Array<Klass*>* local_interfaces) {
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++) {
InstanceKlass *ik = InstanceKlass::cast(local_interfaces->at(i));
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
Array<Klass*>* super_ifs = ik->transitive_interfaces();
int num_super_ifs = super_ifs->length();
for (int j = 0; j < num_super_ifs; j++) {
InstanceKlass *sik = InstanceKlass::cast(super_ifs->at(j));
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) {
GrowableArray<Method*> mirandas(20);
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++) {
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);
++initialized;
}
@ -648,6 +776,26 @@ void klassVtable::copy_vtable_to(vtableEntry* start) {
}
#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,
int methods_length, bool * trace_name_printed) {
// 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++) {
if (unchecked_method_at(index) == old_method) {
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 (!(*trace_name_printed)) {
// 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()));
*trace_name_printed = true;
}
// 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->signature()->as_C_string()));
new_method->signature()->as_C_string(),
updated_default ? "true" : "false"));
}
// cannot 'break' here; see for-loop comment above.
}
@ -701,6 +857,12 @@ void klassVtable::dump_vtable() {
if (m != NULL) {
tty->print(" (%5d) ", i);
m->access_flags().print_on(tty);
if (m->is_default_method()) {
tty->print("default");
}
if (m->is_overpass()) {
tty->print("overpass");
}
tty->print(" -- ");
m->print_name(tty);
tty->cr();
@ -757,9 +919,9 @@ static int initialize_count = 0;
// Initialization
void klassItable::initialize_itable(bool checkconstraints, TRAPS) {
if (_klass->is_interface()) {
// This needs to go after vtable indexes are assigned but
// before implementors need to know the number of itable indexes.
assign_itable_indexes_for_interface(_klass());
// This needs to go after vtable indices are assigned but
// before implementors need to know the number of itable indices.
assign_itable_indices_for_interface(_klass());
}
// Cannot be setup doing bootstrapping, interfaces don't have
@ -803,7 +965,7 @@ inline bool interface_method_needs_itable_index(Method* m) {
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
if (TraceItables) tty->print_cr("%3d: Initializing itable for interface %s", ++initialize_count,
klass->name()->as_C_string());
@ -846,7 +1008,7 @@ int klassItable::method_count_for_interface(Klass* interf) {
}
nof_methods -= 1;
}
// no methods have itable indexes
// no methods have itable indices
return 0;
}
@ -907,6 +1069,21 @@ void klassItable::initialize_itable_for_interface(int method_table_offset, Klass
int ime_num = m->itable_index();
assert(ime_num < ime_count, "oob");
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) {
tty->print(" (%5d) ", i);
m->access_flags().print_on(tty);
if (m->is_default_method()) {
tty->print("default");
}
tty->print(" -- ");
m->print_name(tty);
tty->cr();
@ -1116,7 +1296,7 @@ Method* klassItable::method_for_itable_index(Klass* intf, int itable_index) {
Array<Method*>* methods = InstanceKlass::cast(intf)->methods();
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;
Method* m = methods->at(index);

View file

@ -97,6 +97,7 @@ class klassVtable : public ResourceObj {
// trace_name_printed is set to true if the current call has
// printed the klass name so that other routines in the adjust_*
// 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,
int methods_length, bool * trace_name_printed);
bool check_no_old_or_obsolete_entries();
@ -118,24 +119,28 @@ class klassVtable : public ResourceObj {
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);
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,
Handle target_loader, Symbol* target_classname, Thread* THREAD);
// support for miranda methods
bool is_miranda_entry_at(int i);
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(
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,
Array<Method*>* default_methods,
Klass* super);
static void get_mirandas(
GrowableArray<Method*>* new_mirandas,
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);
inline InstanceKlass* ik() const;
};
@ -290,7 +295,7 @@ class klassItable : public ResourceObj {
#endif // INCLUDE_JVMTI
// 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 compute_itable_size(Array<Klass*>* transitive_interfaces);
static void setup_itable_offset_table(instanceKlassHandle klass);

View file

@ -511,9 +511,9 @@ bool Method::compute_has_loops_flag() {
bool Method::is_final_method(AccessFlags class_access_flags) const {
// 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.
if (is_overpass()) return false;
if (is_overpass() || is_default_method()) return false;
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());
}
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 {
if (is_final_method(class_access_flags)) return true;
#ifdef ASSERT
ResourceMark rm;
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
assert(valid_vtable_index() || valid_itable_index(), "method must be linked before we ask this question");
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
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();
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);
}
// Reset method ordering
if (set_idnums) {
for (int i = 0; i < length; i++) {
Method* m = methods->at(i);
m->set_method_idnum(i);
}
}
}
}
//-----------------------------------------------------------------------------------
// Non-product code unless JVM/TI needs it

View file

@ -567,6 +567,7 @@ class Method : public Metadata {
// checks method and its method holder
bool is_final_method() 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)
bool can_be_statically_bound() const;
@ -846,7 +847,7 @@ class Method : public Metadata {
#endif
// 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
void deallocate_contents(ClassLoaderData* loader_data);

View file

@ -3713,7 +3713,8 @@ void GraphKit::g1_write_barrier_post(Node* oop_store,
Node* no_base = __ top();
float likely = PROB_LIKELY(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);
// 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
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);
} __ end_if();
} __ end_if();
} __ end_if();
} __ end_if();
} else {
// Object.clone() instrinsic uses this path.
g1_mark_card(ideal, card_adr, oop_store, alias_idx, index, index_adr, buffer, tf);

View file

@ -1591,10 +1591,8 @@ static jmethodID get_method_id(JNIEnv *env, jclass clazz, const char *name_str,
}
} else {
m = klass->lookup_method(name, signature);
// Look up interfaces
if (m == NULL && klass->oop_is_instance()) {
m = InstanceKlass::cast(klass())->lookup_method_in_all_interfaces(name,
signature);
m = InstanceKlass::cast(klass())->lookup_method_in_ordered_interfaces(name, signature);
}
}
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(
env, string);
#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
DTRACE_PROBE1(hotspot_jni, GetStringLength__return, ret);
#else /* USDT2 */
@ -3230,11 +3232,13 @@ JNI_QUICK_ENTRY(const jchar*, jni_GetStringChars(
HOTSPOT_JNI_GETSTRINGCHARS_ENTRY(
env, string, (uintptr_t *) isCopy);
#endif /* USDT2 */
jchar* buf = NULL;
oop s = JNIHandles::resolve_non_null(string);
int s_len = java_lang_String::length(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);
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 */
if (buf != NULL) {
if (s_len > 0) {
@ -3246,6 +3250,7 @@ JNI_QUICK_ENTRY(const jchar*, jni_GetStringChars(
*isCopy = JNI_TRUE;
}
}
}
#ifndef USDT2
DTRACE_PROBE1(hotspot_jni, GetStringChars__return, buf);
#else /* USDT2 */
@ -3313,7 +3318,11 @@ JNI_ENTRY(jsize, jni_GetStringUTFLength(JNIEnv *env, jstring string))
HOTSPOT_JNI_GETSTRINGUTFLENGTH_ENTRY(
env, string);
#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
DTRACE_PROBE1(hotspot_jni, GetStringUTFLength__return, ret);
#else /* USDT2 */
@ -3332,16 +3341,19 @@ JNI_ENTRY(const char*, jni_GetStringUTFChars(JNIEnv *env, jstring string, jboole
HOTSPOT_JNI_GETSTRINGUTFCHARS_ENTRY(
env, string, (uintptr_t *) isCopy);
#endif /* USDT2 */
char* result = NULL;
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);
/* 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) {
java_lang_String::as_utf8_string(java_string, result, (int) length + 1);
if (isCopy != NULL) {
*isCopy = JNI_TRUE;
}
}
}
#ifndef USDT2
DTRACE_PROBE1(hotspot_jni, GetStringUTFChars__return, result);
#else /* USDT2 */

View file

@ -1324,18 +1324,19 @@ JNI_ENTRY_CHECKED(const jchar *,
IN_VM(
checkString(thr, str);
)
jchar* newResult = NULL;
const jchar *result = UNCHECKED()->GetStringChars(env,str,isCopy);
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
jint* tagLocation = (jint*) AllocateHeap(len * sizeof(jchar) + sizeof(jint), mtInternal);
*tagLocation = STRING_TAG;
jchar* newResult = (jchar*) (tagLocation + 1);
newResult = (jchar*) (tagLocation + 1);
memcpy(newResult, result, len * sizeof(jchar));
// 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.
FreeHeap((char*)result);
}
functionExit(env);
return newResult;
JNI_END
@ -1394,18 +1395,19 @@ JNI_ENTRY_CHECKED(const char *,
IN_VM(
checkString(thr, str);
)
char* newResult = NULL;
const char *result = UNCHECKED()->GetStringUTFChars(env,str,isCopy);
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
jint* tagLocation = (jint*) AllocateHeap(len + sizeof(jint), mtInternal);
*tagLocation = STRING_UTF_TAG;
char* newResult = (char*) (tagLocation + 1);
newResult = (char*) (tagLocation + 1);
strcpy(newResult, result);
// 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.
FreeHeap((char*)result, mtInternal);
}
functionExit(env);
return newResult;
JNI_END

View file

@ -668,13 +668,12 @@ JVM_END
JVM_ENTRY(jclass, JVM_GetCallerClass(JNIEnv* env, int depth))
JVMWrapper("JVM_GetCallerClass");
// Pre-JDK 8 and early builds of JDK 8 don't have a CallerSensitive annotation.
if (SystemDictionary::reflect_CallerSensitive_klass() == NULL) {
// Pre-JDK 8 and early builds of JDK 8 don't have a CallerSensitive annotation; or
// 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);
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.
@ -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 //////////////////////////////////////////////////////////////

View file

@ -374,6 +374,9 @@ JVM_NewMultiArray(JNIEnv *env, jclass eltClass, jintArray dim);
/*
* java.lang.Class and java.lang.ClassLoader
*/
#define JVM_CALLER_DEPTH -1
/*
* Returns the class in which the code invoking the native method
* belongs.

View file

@ -35,22 +35,6 @@ jclass find_class_from_class_loader(JNIEnv* env, Symbol* name, jboolean init, Ha
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
*/

View file

@ -2755,13 +2755,26 @@ void VM_RedefineClasses::AdjustCpoolCacheAndVtable::do_klass(Klass* k) {
// InstanceKlass around to hold obsolete methods so we don't have
// any other InstanceKlass embedded vtables to update. The vtable
// 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
ResourceMark rm(_thread);
ik->vtable()->adjust_method_entries(_matching_old_methods,
_matching_new_methods,
_matching_methods_length,
&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
@ -2931,7 +2944,8 @@ void VM_RedefineClasses::check_methods_and_mark_as_obsolete(
old_method->set_is_obsolete();
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();
if (num != ConstMethod::UNSET_IDNUM) {
old_method->set_method_idnum(num);

View file

@ -187,12 +187,34 @@ oop MethodHandles::init_method_MemberName(Handle mname, CallInfo& info) {
receiver_limit = m->method_holder();
assert(receiver_limit->verify_itable_index(vmindex), "");
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;
case CallInfo::vtable_call:
vmindex = info.vtable_index();
flags |= IS_METHOD | (JVM_REF_invokeVirtual << REFERENCE_KIND_SHIFT);
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;
case CallInfo::direct_call:

View file

@ -129,10 +129,6 @@ extern "C" {
#define FN_PTR(f) CAST_FROM_FN_PTR(void*, &f)
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_java_lang_invoke_MethodHandleNatives_registerNatives", NULL, FN_PTR(JVM_RegisterMethodHandleMethods) },
{ 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) {
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);
for (; i < count; i++) {
for (int i = 0; i < count; i++) {
// NB: To ignore the jni prefix and jni postfix strstr is used matching.
if (strstr(jni_name, lookup_special_native_methods[i].name) != NULL) {
return CAST_FROM_FN_PTR(address, lookup_special_native_methods[i].fnPtr);

View file

@ -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.
*
* 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));
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++) {
oop argument_oop = argumentArray->obj_at(i);
oop argument_oop = argumentArray_ah->obj_at(i);
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();
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();
for (int i = 0; i < parser.num_arguments(); i++) {
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)));
char buf[VALUE_MAXLEN];
arg->value_as_str(buf, sizeof(buf));
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

View file

@ -2045,6 +2045,9 @@ bool Arguments::check_vm_args_consistency() {
status = status && verify_interval(StringTableSize, minimumStringTableSize,
(max_uintx / StringTable::bucket_size()), "StringTable size");
status = status && verify_interval(SymbolTableSize, minimumSymbolTableSize,
(max_uintx / SymbolTable::bucket_size()), "SymbolTable size");
if (MinHeapFreeRatio > MaxHeapFreeRatio) {
jio_fprintf(defaultStream::error_stream(),
"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);
// -Xmn for compatibility with other JVM vendors
} else if (match_option(option, "-Xmn", &tail)) {
julong long_initial_eden_size = 0;
ArgsRange errcode = parse_memory_size(tail, &long_initial_eden_size, 1);
julong long_initial_young_size = 0;
ArgsRange errcode = parse_memory_size(tail, &long_initial_young_size, 1);
if (errcode != arg_in_range) {
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);
return JNI_EINVAL;
}
FLAG_SET_CMDLINE(uintx, MaxNewSize, (uintx)long_initial_eden_size);
FLAG_SET_CMDLINE(uintx, NewSize, (uintx)long_initial_eden_size);
FLAG_SET_CMDLINE(uintx, MaxNewSize, (uintx)long_initial_young_size);
FLAG_SET_CMDLINE(uintx, NewSize, (uintx)long_initial_young_size);
// -Xms
} else if (match_option(option, "-Xms", &tail)) {
julong long_initial_heap_size = 0;
@ -3663,6 +3666,9 @@ jint Arguments::apply_ergo() {
assert(verify_serial_gc_flags(), "SerialGC unset");
#endif // INCLUDE_ALL_GCS
// Initialize Metaspace flags and alignments.
Metaspace::ergo_initialize();
// Set bytecode rewriting flags
set_bytecode_flags();

File diff suppressed because it is too large Load diff

View file

@ -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.
*
* This code is free software; you can redistribute it and/or modify it
@ -27,8 +27,11 @@
#include "memory/universe.inline.hpp"
#include "runtime/reflectionUtils.hpp"
KlassStream::KlassStream(instanceKlassHandle klass, bool local_only, bool classes_only) {
_klass = klass;
KlassStream::KlassStream(instanceKlassHandle klass, bool local_only,
bool classes_only, bool walk_defaults) {
_klass = _base_klass = klass;
_base_class_search_defaults = false;
_defaults_checked = false;
if (classes_only) {
_interfaces = Universe::the_empty_klass_array();
} else {
@ -37,6 +40,7 @@ KlassStream::KlassStream(instanceKlassHandle klass, bool local_only, bool classe
_interface_index = _interfaces->length();
_local_only = local_only;
_classes_only = classes_only;
_walk_defaults = walk_defaults;
}
bool KlassStream::eos() {
@ -45,7 +49,13 @@ bool KlassStream::eos() {
if (!_klass->is_interface() && _klass->super() != NULL) {
// go up superclass chain (not for interfaces)
_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 {
// Next walk transitive interfaces
if (_interface_index > 0) {
_klass = _interfaces->at(--_interface_index);
} else {

View file

@ -38,7 +38,7 @@
// and (super)interfaces. Streaming is done in reverse order (subclasses first,
// 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();
// ...
// }
@ -46,17 +46,21 @@
class KlassStream VALUE_OBJ_CLASS_SPEC {
protected:
instanceKlassHandle _klass; // current klass/interface iterated over
instanceKlassHandle _base_klass; // initial klass/interface to iterate over
Array<Klass*>* _interfaces; // transitive interfaces for initial class
int _interface_index; // current interface being processed
bool _local_only; // process initial class/interface only
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;
virtual int length() const = 0;
virtual int length() = 0;
public:
// constructor
KlassStream(instanceKlassHandle klass, bool local_only, bool classes_only);
KlassStream(instanceKlassHandle klass, bool local_only, bool classes_only, bool walk_defaults);
// testing
bool eos();
@ -67,6 +71,8 @@ class KlassStream VALUE_OBJ_CLASS_SPEC {
// accessors
instanceKlassHandle klass() const { return _klass; }
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 {
private:
int length() const { return methods()->length(); }
Array<Method*>* methods() const { return _klass->methods(); }
int length() { return methods()->length(); }
Array<Method*>* methods() {
if (base_class_search_defaults()) {
base_class_search_defaults(false);
return _klass->default_methods();
} else {
return _klass->methods();
}
}
public:
MethodStream(instanceKlassHandle klass, bool local_only, bool classes_only)
: KlassStream(klass, local_only, classes_only) {
: KlassStream(klass, local_only, classes_only, true) {
_index = length();
next();
}
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 {
private:
int length() const { return _klass->java_fields_count(); }
int length() { return _klass->java_fields_count(); }
fieldDescriptor _fd_buf;
public:
FieldStream(instanceKlassHandle klass, bool local_only, bool classes_only)
: KlassStream(klass, local_only, classes_only) {
: KlassStream(klass, local_only, classes_only, false) {
_index = length();
next();
}

View file

@ -368,8 +368,15 @@ VirtualSpace::VirtualSpace() {
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.
assert(_low_boundary == NULL, "VirtualSpace already initialized");
assert(max_commit_granularity > 0, "Granularity must be non-zero.");
_low_boundary = rs.base();
_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
// bottom of the space if they are not aligned so already.
_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();
// End of each region
@ -966,17 +973,52 @@ void TestReservedSpace_test() {
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:
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 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");
VirtualSpace vs;
bool initialized = vs.initialize(reserved, 0);
bool initialized = initialize_virtual_space(vs, reserved, mode);
assert(initialized, "Failed to initialize VirtualSpace");
vs.expand_by(commit_size, false);
@ -986,7 +1028,10 @@ class TestVirtualSpace : AllStatic {
} else {
assert_ge(vs.actual_committed_size(), commit_size);
// 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);
}
@ -1042,9 +1087,40 @@ class TestVirtualSpace : AllStatic {
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() {
test_virtual_space_actual_committed_space();
test_virtual_space_actual_committed_space_one_large_page();
test_virtual_space_disable_large_pages();
}
};

View file

@ -178,6 +178,7 @@ class VirtualSpace VALUE_OBJ_CLASS_SPEC {
public:
// Initialization
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);
// Destruction

View file

@ -27,7 +27,6 @@
#include "classfile/javaClasses.hpp"
#include "classfile/loaderConstraints.hpp"
#include "classfile/placeholders.hpp"
#include "classfile/symbolTable.hpp"
#include "classfile/systemDictionary.hpp"
#include "ci/ciField.hpp"
#include "ci/ciInstance.hpp"
@ -289,6 +288,7 @@ typedef BinaryTreeDictionary<Metablock, FreeList> MetablockTreeDictionary;
nonstatic_field(ConstantPoolCache, _constant_pool, ConstantPool*) \
nonstatic_field(InstanceKlass, _array_klasses, Klass*) \
nonstatic_field(InstanceKlass, _methods, Array<Method*>*) \
nonstatic_field(InstanceKlass, _default_methods, Array<Method*>*) \
nonstatic_field(InstanceKlass, _local_interfaces, Array<Klass*>*) \
nonstatic_field(InstanceKlass, _transitive_interfaces, Array<Klass*>*) \
nonstatic_field(InstanceKlass, _fields, Array<u2>*) \
@ -323,6 +323,7 @@ typedef BinaryTreeDictionary<Metablock, FreeList> MetablockTreeDictionary;
nonstatic_field(nmethodBucket, _count, int) \
nonstatic_field(nmethodBucket, _next, nmethodBucket*) \
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, _secondary_super_cache, Klass*) \
nonstatic_field(Klass, _secondary_supers, Array<Klass*>*) \
@ -715,11 +716,17 @@ typedef BinaryTreeDictionary<Metablock, FreeList> MetablockTreeDictionary;
nonstatic_field(PlaceholderEntry, _loader_data, ClassLoaderData*) \
\
/**************************/ \
/* ProctectionDomainEntry */ \
/* 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 */ \
@ -1562,6 +1569,7 @@ typedef BinaryTreeDictionary<Metablock, FreeList> MetablockTreeDictionary;
declare_toplevel_type(SystemDictionary) \
declare_toplevel_type(vmSymbols) \
declare_toplevel_type(ProtectionDomainEntry) \
declare_toplevel_type(ProtectionDomainCacheEntry) \
\
declare_toplevel_type(GenericGrowableArray) \
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_LITTLE_ENDIAN", PERFDATA_LITTLE_ENDIAN) \
\
/***************/ \
/* SymbolTable */ \
/***************/ \
\
declare_constant(SymbolTable::symbol_table_size) \
\
/***********************************/ \
/* LoaderConstraintTable constants */ \
/***********************************/ \

View file

@ -148,6 +148,12 @@ public:
static void track_code_cache_memory_usage() {
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 gc_begin(bool fullGC, bool recordGCBeginTime,

View file

@ -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)
// Default ProtectionDomainCacheSize values
const int defaultProtectionDomainCacheSize = NOT_LP64(137) LP64_ONLY(2017);
//----------------------------------------------------------------------------------------------------
// 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 minimumStringTableSize = 1009;
const int defaultSymbolTableSize = 20011;
const int minimumSymbolTableSize = 1009;
//----------------------------------------------------------------------------------------------------
// HotSwap - for JVMTI aka Class File Replacement and PopFrame

View file

@ -65,7 +65,6 @@ needs_jdk = \
gc/metaspace/CompressedClassSpaceSizeInJmapHeap.java \
gc/metaspace/TestMetaspacePerfCounters.java \
runtime/6819213/TestBootNativeLibraryPath.java \
runtime/6878713/Test6878713.sh \
runtime/6925573/SortMethodsTest.java \
runtime/7107135/Test7107135.sh \
runtime/7158988/FieldMonitor.java \
@ -85,7 +84,9 @@ needs_jdk = \
runtime/NMT/VirtualAllocTestType.java \
runtime/RedefineObject/TestRedefineObject.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
#

View file

@ -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
# @bug 6888954
# @bug 8015884
@ -63,6 +85,7 @@ do
[ $i -lt 10 ] && i2=0$i
"$TESTJAVA/bin/java" $TESTVMOPTS -XX:+IgnoreUnrecognizedVMOptions \
-XX:-TransmitErrorReport \
-XX:ErrorHandlerTest=${i} -version > ${i2}.out 2>&1
# If ErrorHandlerTest is ignored (product build), stop.

View 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();
}
}

View file

@ -56,6 +56,7 @@ public class ReserveMemory {
"-Xbootclasspath/a:.",
"-XX:+UnlockDiagnosticVMOptions",
"-XX:+WhiteBoxAPI",
"-XX:-TransmitErrorReport",
"ReserveMemory",
"test");

View file

@ -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;
}
}

View file

@ -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();
}
}
}

View file

@ -23,20 +23,17 @@
package com.oracle.java.testlibrary;
import java.util.List;
import java.util.ArrayList;
import java.util.Arrays;
import com.oracle.java.testlibrary.JDKToolFinder;
import com.oracle.java.testlibrary.ProcessTools;
import java.util.List;
/**
* A utility for constructing command lines for starting JDK tool processes.
*
* The JDKToolLauncher can in particular be combined with a
* java.lang.ProcessBuilder to easily run a JDK tool. For example, the
* following code run {@code jmap -heap} against a process with GC logging
* turned on for the {@code jmap} process:
* java.lang.ProcessBuilder to easily run a JDK tool. For example, the following
* code run {@code jmap -heap} against a process with GC logging turned on for
* the {@code jmap} process:
*
* <pre>
* {@code
@ -55,19 +52,39 @@ public class JDKToolLauncher {
private final List<String> vmArgs = 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);
} else {
executable = JDKToolFinder.getCurrentJDKTool(tool);
}
vmArgs.addAll(Arrays.asList(ProcessTools.getPlatformSpecificVMArgs()));
}
/**
* Creates a new JDKToolLauncher for the specified tool. Using tools path
* from the compiler JDK.
*
* @param tool
* The name of the tool
* @return A new JDKToolLauncher
*/
public static JDKToolLauncher create(String tool) {
return new JDKToolLauncher(tool, true);
}
/**
* Creates a new JDKToolLauncher for the specified tool.
*
* @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
*/
public static JDKToolLauncher create(String tool) {
return new JDKToolLauncher(tool);
public static JDKToolLauncher create(String tool, boolean useCompilerJDK) {
return new JDKToolLauncher(tool, useCompilerJDK);
}
/**
@ -80,7 +97,8 @@ public class JDKToolLauncher {
* automatically added.
*
*
* @param arg The argument to VM running the tool
* @param arg
* The argument to VM running the tool
* @return The JDKToolLauncher instance
*/
public JDKToolLauncher addVMArg(String arg) {
@ -91,7 +109,8 @@ public class JDKToolLauncher {
/**
* Adds an argument to the tool.
*
* @param arg The argument to the tool
* @param arg
* The argument to the tool
* @return The JDKToolLauncher instance
*/
public JDKToolLauncher addToolArg(String arg) {

View file

@ -232,3 +232,4 @@ d6a32e3831aab20a9a3bc78cdc0a60aaad725c6c jdk8-b107
8ade3eed63da87067a7137c111f684a821e9e531 jdk8-b108
02bfab2aa93899e0f02584f1e85537485a196553 jdk8-b109
4c84c5b447b09aff27f3b72667ab3a5401e85968 jdk8-b110
17ee0d3e97fdb412e48f14d87f504946a708f846 jdk8-b111

View file

@ -3,7 +3,7 @@
* 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");
* you may not use this file except in compliance with the License.
@ -18,7 +18,7 @@
* 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;
@ -1207,7 +1207,7 @@ public class XSLTErrorResources_de extends ListResourceBundle
"Funktionsname darf nicht null sein."},
{ ER_XPATH_RESOLVER_NEGATIVE_ARITY,
"Anzahl von Argumenten darf nicht negativ sein."},
"Argumentanzahl darf nicht negativ sein."},
// Warnings...
{ WG_FOUND_CURLYBRACE,
@ -1359,7 +1359,7 @@ public class XSLTErrorResources_de extends ListResourceBundle
{ "optionQ", " [-Q (Stiller Modus)]"},
{ "optionLF", " [-LF (Nur Zeilenvorsch\u00FCbe 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})]"},
{ "optionTT", " [-TT (Vorlagen verfolgen, wenn diese aufgerufen werden.)]"},
{ "optionTG", " [-TG (Jedes Generierungsereignis verfolgen.)]"},

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