# HG changeset patch # User duke # Date 1499273979 -7200 # Node ID f1a01fb5f958e97c1167c9879c6526ab5ce14e5c # Parent 41b9fc8961f6842c965a7e03918a512edd479718# Parent 5996ac1cc4db6a9d401990ffb08b6eb8572384e3 Merge diff -r 41b9fc8961f6 -r f1a01fb5f958 .hgtags-top-repo --- a/.hgtags-top-repo Thu Jun 13 09:49:19 2013 -0700 +++ b/.hgtags-top-repo Wed Jul 05 18:59:39 2017 +0200 @@ -215,3 +215,4 @@ cb51fb4789ac0b8be4056482077ddfb8f3bd3805 jdk8-b91 3a36c926a7aafa9d4a892a45ef3678e87ad8359b jdk8-b92 27c51c6e31c1ef36afa0e6efb031f9b13f26c12b jdk8-b93 +50d2bde060f2a9bbbe4da0c8986e20aca61f2e2e jdk8-b94 diff -r 41b9fc8961f6 -r f1a01fb5f958 common/autoconf/basics.m4 --- a/common/autoconf/basics.m4 Thu Jun 13 09:49:19 2013 -0700 +++ b/common/autoconf/basics.m4 Wed Jul 05 18:59:39 2017 +0200 @@ -363,7 +363,11 @@ AC_MSG_ERROR([Cannot specify both --with-devkit and --with-tools-dir at the same time]) fi TOOLS_DIR=$with_devkit/bin - SYS_ROOT=$with_devkit/$host_alias/libc + if test -d "$with_devkit/$host_alias/libc"; then + SYS_ROOT=$with_devkit/$host_alias/libc + elif test -d "$with_devkit/$host/sys-root"; then + SYS_ROOT=$with_devkit/$host/sys-root + fi ]) ]) diff -r 41b9fc8961f6 -r f1a01fb5f958 common/autoconf/build-performance.m4 --- a/common/autoconf/build-performance.m4 Thu Jun 13 09:49:19 2013 -0700 +++ b/common/autoconf/build-performance.m4 Wed Jul 05 18:59:39 2017 +0200 @@ -162,7 +162,12 @@ [disable using ccache to speed up recompilations @<:@enabled@:>@])], [ENABLE_CCACHE=${enable_ccache}], [ENABLE_CCACHE=yes]) if test "x$ENABLE_CCACHE" = xyes; then + OLD_PATH="$PATH" + if test "x$TOOLS_DIR" != x; then + PATH=$TOOLS_DIR:$PATH + fi AC_PATH_PROG(CCACHE, ccache) + PATH="$OLD_PATH" else AC_MSG_CHECKING([for ccache]) AC_MSG_RESULT([explicitly disabled]) diff -r 41b9fc8961f6 -r f1a01fb5f958 common/autoconf/generated-configure.sh --- a/common/autoconf/generated-configure.sh Thu Jun 13 09:49:19 2013 -0700 +++ b/common/autoconf/generated-configure.sh Wed Jul 05 18:59:39 2017 +0200 @@ -3782,7 +3782,7 @@ #CUSTOM_AUTOCONF_INCLUDE # Do not change or remove the following line, it is needed for consistency checks: -DATE_WHEN_GENERATED=1370949244 +DATE_WHEN_GENERATED=1371547824 ############################################################################### # @@ -7471,7 +7471,11 @@ as_fn_error $? "Cannot specify both --with-devkit and --with-tools-dir at the same time" "$LINENO" 5 fi TOOLS_DIR=$with_devkit/bin - SYS_ROOT=$with_devkit/$host_alias/libc + if test -d "$with_devkit/$host_alias/libc"; then + SYS_ROOT=$with_devkit/$host_alias/libc + elif test -d "$with_devkit/$host/sys-root"; then + SYS_ROOT=$with_devkit/$host/sys-root + fi fi @@ -29144,7 +29148,6 @@ case $COMPILER_TYPE in CC ) - D_FLAG="-g" case $COMPILER_NAME in gcc ) case $OPENJDK_TARGET_OS in @@ -29159,17 +29162,17 @@ C_O_FLAG_HI="-O3" C_O_FLAG_NORM="-O2" C_O_FLAG_NONE="-O0" - CFLAGS_DEBUG_SYMBOLS="-g" - CXXFLAGS_DEBUG_SYMBOLS="-g" - if test "x$OPENJDK_TARGET_CPU_BITS" = "x64" && test "x$DEBUG_LEVEL" = "xfastdebug"; then - CFLAGS_DEBUG_SYMBOLS="-g1" - CXXFLAGS_DEBUG_SYMBOLS="-g1" - fi ;; esac CXX_O_FLAG_HI="$C_O_FLAG_HI" CXX_O_FLAG_NORM="$C_O_FLAG_NORM" CXX_O_FLAG_NONE="$C_O_FLAG_NONE" + CFLAGS_DEBUG_SYMBOLS="-g" + CXXFLAGS_DEBUG_SYMBOLS="-g" + if test "x$OPENJDK_TARGET_CPU_BITS" = "x64" && test "x$DEBUG_LEVEL" = "xfastdebug"; then + CFLAGS_DEBUG_SYMBOLS="-g1" + CXXFLAGS_DEBUG_SYMBOLS="-g1" + fi ;; ossc ) # @@ -29250,7 +29253,6 @@ esac ;; CL ) - D_FLAG= C_O_FLAG_HIGHEST="-O2" C_O_FLAG_HI="-O1" C_O_FLAG_NORM="-O1" @@ -29389,6 +29391,28 @@ ############################################################################### +# Adjust flags according to debug level. +case $DEBUG_LEVEL in + fastdebug ) + CFLAGS_JDK="$CFLAGS_JDK $CFLAGS_DEBUG_SYMBOLS" + CXXFLAGS_JDK="$CXXFLAGS_JDK $CXXFLAGS_DEBUG_SYMBOLS" + C_O_FLAG_HI="$C_O_FLAG_NORM" + C_O_FLAG_NORM="$C_O_FLAG_NORM" + CXX_O_FLAG_HI="$CXX_O_FLAG_NORM" + CXX_O_FLAG_NORM="$CXX_O_FLAG_NORM" + JAVAC_FLAGS="$JAVAC_FLAGS -g" + ;; + slowdebug ) + CFLAGS_JDK="$CFLAGS_JDK $CFLAGS_DEBUG_SYMBOLS" + CXXFLAGS_JDK="$CXXFLAGS_JDK $CXXFLAGS_DEBUG_SYMBOLS" + C_O_FLAG_HI="$C_O_FLAG_NONE" + C_O_FLAG_NORM="$C_O_FLAG_NONE" + CXX_O_FLAG_HI="$CXX_O_FLAG_NONE" + CXX_O_FLAG_NORM="$CXX_O_FLAG_NONE" + JAVAC_FLAGS="$JAVAC_FLAGS -g" + ;; +esac + CCXXFLAGS_JDK="$CCXXFLAGS_JDK $ADD_LP64" # The package path is used only on macosx? @@ -29532,23 +29556,6 @@ fi fi -# Adjust flags according to debug level. -case $DEBUG_LEVEL in - fastdebug ) - CFLAGS="$CFLAGS $D_FLAG" - JAVAC_FLAGS="$JAVAC_FLAGS -g" - ;; - slowdebug ) - CFLAGS="$CFLAGS $D_FLAG" - C_O_FLAG_HI="$C_O_FLAG_NONE" - C_O_FLAG_NORM="$C_O_FLAG_NONE" - CXX_O_FLAG_HI="$CXX_O_FLAG_NONE" - CXX_O_FLAG_NORM="$CXX_O_FLAG_NONE" - JAVAC_FLAGS="$JAVAC_FLAGS -g" - ;; -esac - - @@ -29907,11 +29914,17 @@ if test "x$x_includes" = xNONE; then if test -f "$SYS_ROOT/usr/X11R6/include/X11/Xlib.h"; then x_includes="$SYS_ROOT/usr/X11R6/include" + elif test -f "$SYS_ROOT/usr/include/X11/Xlib.h"; then + x_includes="$SYS_ROOT/usr/include" fi fi if test "x$x_libraries" = xNONE; then if test -f "$SYS_ROOT/usr/X11R6/lib/libX11.so"; then x_libraries="$SYS_ROOT/usr/X11R6/lib" + elif test "$SYS_ROOT/usr/lib64/libX11.so" && test "x$OPENJDK_TARGET_CPU_BITS" = x64; then + x_libraries="$SYS_ROOT/usr/lib64" + elif test -f "$SYS_ROOT/usr/lib/libX11.so"; then + x_libraries="$SYS_ROOT/usr/lib" fi fi fi @@ -30642,8 +30655,7 @@ if test "x$OPENJDK_TARGET_OS" = xlinux; then if test -d "$SYS_ROOT/usr/X11R6"; then OPENWIN_HOME="$SYS_ROOT/usr/X11R6" - fi - if test -d "$SYS_ROOT/usr/include/X11"; then + elif test -d "$SYS_ROOT/usr/include/X11"; then OPENWIN_HOME="$SYS_ROOT/usr" fi fi @@ -31536,12 +31548,12 @@ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for freetype in some standard locations" >&5 $as_echo_n "checking for freetype in some standard locations... " >&6; } - if test -s /usr/X11/include/ft2build.h && test -d /usr/X11/include/freetype2/freetype; then - DEFAULT_FREETYPE_CFLAGS="-I/usr/X11/include/freetype2 -I/usr/X11/include" - DEFAULT_FREETYPE_LIBS="-L/usr/X11/lib -lfreetype" + if test -s $SYS_ROOT/usr/X11/include/ft2build.h && test -d $SYS_ROOT/usr/X11/include/freetype2/freetype; then + DEFAULT_FREETYPE_CFLAGS="-I$SYS_ROOT/usr/X11/include/freetype2 -I$SYS_ROOT/usr/X11/include" + DEFAULT_FREETYPE_LIBS="-L$SYS_ROOT/usr/X11/lib -lfreetype" fi - if test -s /usr/include/ft2build.h && test -d /usr/include/freetype2/freetype; then - DEFAULT_FREETYPE_CFLAGS="-I/usr/include/freetype2" + if test -s $SYS_ROOT/usr/include/ft2build.h && test -d $SYS_ROOT/usr/include/freetype2/freetype; then + DEFAULT_FREETYPE_CFLAGS="-I$SYS_ROOT/usr/include/freetype2" DEFAULT_FREETYPE_LIBS="-lfreetype" fi @@ -33217,6 +33229,10 @@ fi if test "x$ENABLE_CCACHE" = xyes; then + OLD_PATH="$PATH" + if test "x$TOOLS_DIR" != x; then + PATH=$TOOLS_DIR:$PATH + fi # Extract the first word of "ccache", so it can be a program name with args. set dummy ccache; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 @@ -33257,6 +33273,7 @@ fi + PATH="$OLD_PATH" else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ccache" >&5 $as_echo_n "checking for ccache... " >&6; } diff -r 41b9fc8961f6 -r f1a01fb5f958 common/autoconf/libraries.m4 --- a/common/autoconf/libraries.m4 Thu Jun 13 09:49:19 2013 -0700 +++ b/common/autoconf/libraries.m4 Wed Jul 05 18:59:39 2017 +0200 @@ -123,11 +123,17 @@ if test "x$x_includes" = xNONE; then if test -f "$SYS_ROOT/usr/X11R6/include/X11/Xlib.h"; then x_includes="$SYS_ROOT/usr/X11R6/include" + elif test -f "$SYS_ROOT/usr/include/X11/Xlib.h"; then + x_includes="$SYS_ROOT/usr/include" fi fi if test "x$x_libraries" = xNONE; then if test -f "$SYS_ROOT/usr/X11R6/lib/libX11.so"; then x_libraries="$SYS_ROOT/usr/X11R6/lib" + elif test "$SYS_ROOT/usr/lib64/libX11.so" && test "x$OPENJDK_TARGET_CPU_BITS" = x64; then + x_libraries="$SYS_ROOT/usr/lib64" + elif test -f "$SYS_ROOT/usr/lib/libX11.so"; then + x_libraries="$SYS_ROOT/usr/lib" fi fi fi @@ -153,8 +159,7 @@ if test "x$OPENJDK_TARGET_OS" = xlinux; then if test -d "$SYS_ROOT/usr/X11R6"; then OPENWIN_HOME="$SYS_ROOT/usr/X11R6" - fi - if test -d "$SYS_ROOT/usr/include/X11"; then + elif test -d "$SYS_ROOT/usr/include/X11"; then OPENWIN_HOME="$SYS_ROOT/usr" fi fi @@ -359,12 +364,12 @@ if test "x$FREETYPE2_FOUND" = xno; then AC_MSG_CHECKING([for freetype in some standard locations]) - if test -s /usr/X11/include/ft2build.h && test -d /usr/X11/include/freetype2/freetype; then - DEFAULT_FREETYPE_CFLAGS="-I/usr/X11/include/freetype2 -I/usr/X11/include" - DEFAULT_FREETYPE_LIBS="-L/usr/X11/lib -lfreetype" + if test -s $SYS_ROOT/usr/X11/include/ft2build.h && test -d $SYS_ROOT/usr/X11/include/freetype2/freetype; then + DEFAULT_FREETYPE_CFLAGS="-I$SYS_ROOT/usr/X11/include/freetype2 -I$SYS_ROOT/usr/X11/include" + DEFAULT_FREETYPE_LIBS="-L$SYS_ROOT/usr/X11/lib -lfreetype" fi - if test -s /usr/include/ft2build.h && test -d /usr/include/freetype2/freetype; then - DEFAULT_FREETYPE_CFLAGS="-I/usr/include/freetype2" + if test -s $SYS_ROOT/usr/include/ft2build.h && test -d $SYS_ROOT/usr/include/freetype2/freetype; then + DEFAULT_FREETYPE_CFLAGS="-I$SYS_ROOT/usr/include/freetype2" DEFAULT_FREETYPE_LIBS="-lfreetype" fi diff -r 41b9fc8961f6 -r f1a01fb5f958 common/autoconf/spec.gmk.in --- a/common/autoconf/spec.gmk.in Thu Jun 13 09:49:19 2013 -0700 +++ b/common/autoconf/spec.gmk.in Wed Jul 05 18:59:39 2017 +0200 @@ -275,6 +275,8 @@ FREETYPE2_CFLAGS:=@FREETYPE2_CFLAGS@ USING_SYSTEM_FT_LIB=@USING_SYSTEM_FT_LIB@ CUPS_CFLAGS:=@CUPS_CFLAGS@ +ALSA_LIBS:=@ALSA_LIBS@ +ALSA_CFLAGS:=@ALSA_CFLAGS@ PACKAGE_PATH=@PACKAGE_PATH@ diff -r 41b9fc8961f6 -r f1a01fb5f958 common/autoconf/toolchain.m4 --- a/common/autoconf/toolchain.m4 Thu Jun 13 09:49:19 2013 -0700 +++ b/common/autoconf/toolchain.m4 Wed Jul 05 18:59:39 2017 +0200 @@ -629,7 +629,6 @@ case $COMPILER_TYPE in CC ) - D_FLAG="-g" case $COMPILER_NAME in gcc ) case $OPENJDK_TARGET_OS in @@ -644,17 +643,17 @@ C_O_FLAG_HI="-O3" C_O_FLAG_NORM="-O2" C_O_FLAG_NONE="-O0" - CFLAGS_DEBUG_SYMBOLS="-g" - CXXFLAGS_DEBUG_SYMBOLS="-g" - if test "x$OPENJDK_TARGET_CPU_BITS" = "x64" && test "x$DEBUG_LEVEL" = "xfastdebug"; then - CFLAGS_DEBUG_SYMBOLS="-g1" - CXXFLAGS_DEBUG_SYMBOLS="-g1" - fi ;; esac CXX_O_FLAG_HI="$C_O_FLAG_HI" CXX_O_FLAG_NORM="$C_O_FLAG_NORM" CXX_O_FLAG_NONE="$C_O_FLAG_NONE" + CFLAGS_DEBUG_SYMBOLS="-g" + CXXFLAGS_DEBUG_SYMBOLS="-g" + if test "x$OPENJDK_TARGET_CPU_BITS" = "x64" && test "x$DEBUG_LEVEL" = "xfastdebug"; then + CFLAGS_DEBUG_SYMBOLS="-g1" + CXXFLAGS_DEBUG_SYMBOLS="-g1" + fi ;; ossc ) # @@ -735,7 +734,6 @@ esac ;; CL ) - D_FLAG= C_O_FLAG_HIGHEST="-O2" C_O_FLAG_HI="-O1" C_O_FLAG_NORM="-O1" @@ -861,6 +859,28 @@ ############################################################################### +# Adjust flags according to debug level. +case $DEBUG_LEVEL in + fastdebug ) + CFLAGS_JDK="$CFLAGS_JDK $CFLAGS_DEBUG_SYMBOLS" + CXXFLAGS_JDK="$CXXFLAGS_JDK $CXXFLAGS_DEBUG_SYMBOLS" + C_O_FLAG_HI="$C_O_FLAG_NORM" + C_O_FLAG_NORM="$C_O_FLAG_NORM" + CXX_O_FLAG_HI="$CXX_O_FLAG_NORM" + CXX_O_FLAG_NORM="$CXX_O_FLAG_NORM" + JAVAC_FLAGS="$JAVAC_FLAGS -g" + ;; + slowdebug ) + CFLAGS_JDK="$CFLAGS_JDK $CFLAGS_DEBUG_SYMBOLS" + CXXFLAGS_JDK="$CXXFLAGS_JDK $CXXFLAGS_DEBUG_SYMBOLS" + C_O_FLAG_HI="$C_O_FLAG_NONE" + C_O_FLAG_NORM="$C_O_FLAG_NONE" + CXX_O_FLAG_HI="$CXX_O_FLAG_NONE" + CXX_O_FLAG_NORM="$CXX_O_FLAG_NONE" + JAVAC_FLAGS="$JAVAC_FLAGS -g" + ;; +esac + CCXXFLAGS_JDK="$CCXXFLAGS_JDK $ADD_LP64" # The package path is used only on macosx? @@ -1004,23 +1024,6 @@ fi fi -# Adjust flags according to debug level. -case $DEBUG_LEVEL in - fastdebug ) - CFLAGS="$CFLAGS $D_FLAG" - JAVAC_FLAGS="$JAVAC_FLAGS -g" - ;; - slowdebug ) - CFLAGS="$CFLAGS $D_FLAG" - C_O_FLAG_HI="$C_O_FLAG_NONE" - C_O_FLAG_NORM="$C_O_FLAG_NONE" - CXX_O_FLAG_HI="$CXX_O_FLAG_NONE" - CXX_O_FLAG_NORM="$CXX_O_FLAG_NONE" - JAVAC_FLAGS="$JAVAC_FLAGS -g" - ;; -esac - - AC_SUBST(CFLAGS_JDKLIB) AC_SUBST(CFLAGS_JDKEXE) diff -r 41b9fc8961f6 -r f1a01fb5f958 common/makefiles/NativeCompilation.gmk --- a/common/makefiles/NativeCompilation.gmk Thu Jun 13 09:49:19 2013 -0700 +++ b/common/makefiles/NativeCompilation.gmk Wed Jul 05 18:59:39 2017 +0200 @@ -108,7 +108,11 @@ # setting -showIncludes, all included files are printed. These are filtered out and # parsed into make dependences. ifeq ($(COMPILER_TYPE),CL) - $$($1_$2_COMP) $$($1_$2_FLAGS) -showIncludes $$($1_$2_DEBUG_OUT_FLAGS) $(CC_OUT_OPTION)$$($1_$2_OBJ) $2 | $(TEE) $$($1_$2_DEP).raw | $(GREP) -v "^Note: including file:" + ($$($1_$2_COMP) $$($1_$2_FLAGS) -showIncludes $$($1_$2_DEBUG_OUT_FLAGS) \ + $(CC_OUT_OPTION)$$($1_$2_OBJ) $2 ; echo $$$$? > $$($1_$2_DEP).exitvalue) \ + | $(TEE) $$($1_$2_DEP).raw | $(GREP) -v "^Note: including file:" \ + && exit `cat $$($1_$2_DEP).exitvalue` + $(RM) $$($1_$2_DEP).exitvalue ($(ECHO) $$@: \\ \ && $(SED) -e '/^Note: including file:/!d' \ -e 's|Note: including file: *||' \ diff -r 41b9fc8961f6 -r f1a01fb5f958 common/makefiles/devkit/Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/common/makefiles/devkit/Makefile Wed Jul 05 18:59:39 2017 +0200 @@ -0,0 +1,123 @@ +# +# 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. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# + +########################################################################################## +# +# This Makefile, together with Tools.gmk, can be used to compile a set of +# gcc based cross compilation, portable, self contained packages, capable +# of building OpenJDK. +# +# In addition to the makefiles, access to Oracle Linux installation +# media is required. This has been tested against Oracle Enterprise Linux +# 5.5. Set variables RPM_DIR_x86_64 and RPM_DIR_i686 respectively to point +# to directory containing the RPMs. +# +# By default this Makefile will build crosstools for: +# * i686-unknown-linux-gnu +# * x86_64-unknown-linux-gnu +# The x86_64 version of the compilers will work in multi arch mode and will +# be able to compile 32bit binaries with the -m32 flag. This makes the +# explicit cross compiler for i686 somewhat redundant and is a known issue. +# +# To build the full set of crosstools, use a command line looking like this: +# +# make tars RPM_DIR_x86_64=/tmp/oel55-x86_64/Server/ RPM_DIR_i686=/tmp/oel55-i686/Server/ +# +# To create a x86_64 package without the redundant i686 cross compiler, do +# like this: +# +# make tars platforms=x86_64-unknown-linux-gnu RPM_DIR_x86_64=/tmp/oel55-x86_64/Server/ RPM_DIR_i686=/tmp/oel55-i686/Server/ + +# +# Main makefile which iterates over all host and target platforms. +# + +os := $(shell uname -o) +cpu := x86_64 +#$(shell uname -p) + +# +# This wrapper script can handle exactly these platforms +# +platforms := $(foreach p,x86_64 i686,$(p)-unknown-linux-gnu) +#platforms := $(foreach p,x86_64,$(p)-unknown-linux-gnu) + +# Figure out what platform this is building on. +me := $(cpu)-$(if $(findstring Linux,$(os)),unknown-linux-gnu) + +$(info Building on platform $(me)) + +all compile : $(platforms) + +ifeq (,$(SKIP_ME)) +$(foreach p,$(filter-out $(me),$(platforms)),$(eval $(p) : $$(me))) +endif + +OUTPUT_ROOT = $(abspath ../../../build/devkit) +RESULT = $(OUTPUT_ROOT)/result + +submakevars = HOST=$@ BUILD=$(me) \ + RESULT=$(RESULT) PREFIX=$(RESULT)/$@ \ + OUTPUT_ROOT=$(OUTPUT_ROOT) +$(platforms) : + @echo 'Building compilers for $@' + @echo 'Targets: $(platforms)' + for p in $@ $(filter-out $@,$(platforms)); do \ + $(MAKE) -f Tools.gmk all $(submakevars) \ + TARGET=$$p || exit 1 ; \ + done + @echo 'Building ccache program for $@' + $(MAKE) -f Tools.gmk ccache $(submakevars) TARGET=$@ + @echo 'All done"' + +$(foreach a,i686 x86_64,$(eval $(a) : $(filter $(a)%,$(platforms)))) + +ia32 : i686 +today := $(shell date +%Y%m%d) + + +define Mktar +$(1)_tar = $$(RESULT)/sdk-$(1)-$$(today).tar.gz +$$($(1)_tar) : PLATFORM = $(1) +TARFILES += $$($(1)_tar) +$$($(1)_tar) : $(1) $$(shell find $$(RESULT)/$(1)) +endef + +$(foreach p,$(platforms),$(eval $(call Mktar,$(p)))) + +tars : all $(TARFILES) +onlytars : $(TARFILES) +%.tar.gz : + @echo 'Creating compiler package $@' + cd $(RESULT)/$(PLATFORM) && tar -czf $@ * + touch $@ + +clean : + rm -rf build result + +FORCE : +.PHONY : $(configs) $(platforms) + + diff -r 41b9fc8961f6 -r f1a01fb5f958 common/makefiles/devkit/Tools.gmk --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/common/makefiles/devkit/Tools.gmk Wed Jul 05 18:59:39 2017 +0200 @@ -0,0 +1,473 @@ +# +# 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. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# + +########################################################################################## +# +# Workhorse makefile for creating ONE cross compiler +# Needs either to be from BUILD -> BUILD OR have +# BUILD -> HOST prebuilt +# +# NOTE: There is a bug here. We don't limit the +# PATH when building BUILD -> BUILD, which means that +# if you configure after you've once build the BUILD->BUILD +# compiler THAT one will be picked up as the compiler for itself. +# This is not so great, especially if you did a partial delete +# of the target tree. +# +# Fix this... +# + +$(info TARGET=$(TARGET)) +$(info HOST=$(HOST)) +$(info BUILD=$(BUILD)) + +ARCH := $(word 1,$(subst -, ,$(TARGET))) + +########################################################################################## +# Define external dependencies + +# Latest that could be made to work. +gcc_ver := gcc-4.7.3 +binutils_ver := binutils-2.22 +ccache_ver := ccache-3.1.9 +mpfr_ver := mpfr-3.0.1 +gmp_ver := gmp-4.3.2 +mpc_ver := mpc-1.0.1 + +GCC := http://ftp.gnu.org/pub/gnu/gcc/$(gcc_ver)/$(gcc_ver).tar.bz2 +BINUTILS := http://ftp.gnu.org/pub/gnu/binutils/$(binutils_ver).tar.bz2 +CCACHE := http://samba.org/ftp/ccache/$(ccache_ver).tar.gz +MPFR := http://www.mpfr.org/${mpfr_ver}/${mpfr_ver}.tar.bz2 +GMP := http://ftp.gnu.org/pub/gnu/gmp/${gmp_ver}.tar.bz2 +MPC := http://www.multiprecision.org/mpc/download/${mpc_ver}.tar.gz + +# RPMs in OEL5.5 +RPM_LIST := \ + kernel-headers \ + glibc-2 glibc-headers glibc-devel \ + cups-libs cups-devel \ + libX11 libX11-devel \ + xorg-x11-proto-devel \ + alsa-lib alsa-lib-devel \ + libXext libXext-devel \ + libXtst libXtst-devel \ + libXrender libXrender-devel \ + freetype freetype-devel \ + libXt libXt-devel \ + libSM libSM-devel \ + libICE libICE-devel \ + libXi libXi-devel \ + libXdmcp libXdmcp-devel \ + libXau libXau-devel \ + libgcc + + +ifeq ($(ARCH),x86_64) + RPM_DIR ?= $(RPM_DIR_x86_64) + RPM_ARCHS := x86_64 + ifeq ($(BUILD),$(HOST)) + ifeq ($(TARGET),$(HOST)) + # When building the native compiler for x86_64, enable mixed mode. + RPM_ARCHS += i386 i686 + endif + endif +else + RPM_DIR ?= $(RPM_DIR_i686) + RPM_ARCHS := i386 i686 +endif + +# Sort to remove duplicates +RPM_FILE_LIST := $(sort $(foreach a,$(RPM_ARCHS),$(wildcard $(patsubst %,$(RPM_DIR)/%*$a.rpm,$(RPM_LIST))))) + +ifeq ($(RPM_FILE_LIST),) + $(error Found no RPMs, RPM_DIR must point to list of directories to search for RPMs) +endif + +########################################################################################## +# Define common directories and files + +# Ensure we have 32-bit libs also for x64. We enable mixed-mode. +ifeq (x86_64,$(ARCH)) + LIBDIRS := lib64 lib + CFLAGS_lib := -m32 +else + LIBDIRS := lib +endif + +# Define directories +RESULT := $(OUTPUT_ROOT)/result +BUILDDIR := $(OUTPUT_ROOT)/$(HOST)/$(TARGET) +PREFIX := $(RESULT)/$(HOST) +TARGETDIR := $(PREFIX)/$(TARGET) +SYSROOT := $(TARGETDIR)/sys-root +DOWNLOAD := $(OUTPUT_ROOT)/download +SRCDIR := $(OUTPUT_ROOT)/src + +# Marker file for unpacking rpms +rpms := $(SYSROOT)/rpms_unpacked + +# Need to patch libs that are linker scripts to use non-absolute paths +libs := $(SYSROOT)/libs_patched + +########################################################################################## +# Unpack source packages + +# Generate downloading + unpacking of sources. +define Download +$(1)_DIR = $(abspath $(SRCDIR)/$(basename $(basename $(notdir $($(1)))))) +$(1)_CFG = $$($(1)_DIR)/configure +$(1)_FILE = $(DOWNLOAD)/$(notdir $($(1))) + +$$($(1)_CFG) : $$($(1)_FILE) + mkdir -p $$(SRCDIR) + tar -C $$(SRCDIR) -x$$(if $$(findstring .gz, $$<),z,j)f $$< + $$(foreach p,$$(abspath $$(wildcard $$(notdir $$($(1)_DIR)).patch)), \ + echo PATCHING $$(p) ; \ + patch -d $$($(1)_DIR) -p1 -i $$(p) ; \ + ) + touch $$@ + +$$($(1)_FILE) : + wget -P $(DOWNLOAD) $$($(1)) +endef + +# Download and unpack all source packages +$(foreach p,GCC BINUTILS CCACHE MPFR GMP MPC,$(eval $(call Download,$(p)))) + +########################################################################################## +# Unpack RPMS + +# Note. For building linux you should install rpm2cpio. +define unrpm +$(SYSROOT)/$(notdir $(1)).unpacked \ + : $(1) +$$(rpms) : $(SYSROOT)/$(notdir $(1)).unpacked +endef + +%.unpacked : + $(info Unpacking target rpms and libraries from $<) + @(mkdir -p $(@D); \ + cd $(@D); \ + rpm2cpio $< | \ + cpio --extract --make-directories \ + -f \ + "./usr/share/doc/*" \ + "./usr/share/man/*" \ + "./usr/X11R6/man/*" \ + "*/X11/locale/*" \ + || die ; ) + touch $@ + +$(foreach p,$(RPM_FILE_LIST),$(eval $(call unrpm,$(p)))) + +########################################################################################## + +# Note: MUST create a /usr/lib even if not really needed. +# gcc will use a path relative to it to resolve lib64. (x86_64). +# we're creating multi-lib compiler with 32bit libc as well, so we should +# have it anyway, but just to make sure... +# Patch libc.so and libpthread.so to force linking against libraries in sysroot +# and not the ones installed on the build machine. +$(libs) : $(rpms) + @echo Patching libc and pthreads + @(for f in `find $(SYSROOT) -name libc.so -o -name libpthread.so`; do \ + (cat $$f | sed -e 's|/usr/lib64/||g' \ + -e 's|/usr/lib/||g' \ + -e 's|/lib64/||g' \ + -e 's|/lib/||g' ) > $$f.tmp ; \ + mv $$f.tmp $$f ; \ + done) + @mkdir -p $(SYSROOT)/usr/lib + @touch $@ + +########################################################################################## + +# Define marker files for each source package to be compiled +$(foreach t,binutils mpfr gmp mpc gcc ccache,$(eval $(t) = $(TARGETDIR)/$($(t)_ver).done)) + +########################################################################################## + +# Default base config +CONFIG = --target=$(TARGET) \ + --host=$(HOST) --build=$(BUILD) \ + --prefix=$(PREFIX) + +PATHEXT = $(RESULT)/$(BUILD)/bin: + +PATHPRE = PATH=$(PATHEXT)$(PATH) +BUILDPAR = -j16 + +# Default commands to when making +MAKECMD = +INSTALLCMD = install + + +declare_tools = CC$(1)=$(2)gcc LD$(1)=$(2)ld AR$(1)=$(2)ar AS$(1)=$(2)as RANLIB$(1)=$(2)ranlib CXX$(1)=$(2)g++ OBJDUMP$(1)=$(2)objdump + +ifeq ($(HOST),$(BUILD)) +ifeq ($(HOST),$(TARGET)) +TOOLS = $(call declare_tools,_FOR_TARGET,) +endif +endif + +TOOLS ?= $(call declare_tools,_FOR_TARGET,$(TARGET)-) + +########################################################################################## + +# Create a TARGET bfd + libiberty only. +# Configure one or two times depending on mulitlib arch. +# If multilib, the second should be 32-bit, and we resolve +# CFLAG_ to most likely -m32. +define mk_bfd +$$(info Libs for $(1)) +$$(BUILDDIR)/$$(binutils_ver)-$(subst /,-,$(1))/Makefile \ + : CFLAGS += $$(CFLAGS_$(1)) +$$(BUILDDIR)/$$(binutils_ver)-$(subst /,-,$(1))/Makefile \ + : LIBDIRS = --libdir=$(TARGETDIR)/$(1) + +bfdlib += $$(TARGETDIR)/$$(binutils_ver)-$(subst /,-,$(1)).done +bfdmakes += $$(BUILDDIR)/$$(binutils_ver)-$(subst /,-,$(1))/Makefile +endef + +# Create one set of bfds etc for each multilib arch +$(foreach l,$(LIBDIRS),$(eval $(call mk_bfd,$(l)))) + +# Only build these two libs. +$(bfdlib) : MAKECMD = all-libiberty all-bfd +$(bfdlib) : INSTALLCMD = install-libiberty install-bfd + +# Building targets libbfd + libiberty. HOST==TARGET, i.e not +# for a cross env. +$(bfdmakes) : CONFIG = --target=$(TARGET) \ + --host=$(TARGET) --build=$(BUILD) \ + --prefix=$(TARGETDIR) \ + --with-sysroot=$(SYSROOT) \ + $(LIBDIRS) + +$(bfdmakes) : TOOLS = $(call declare_tools,_FOR_TARGET,$(TARGET)-) $(call declare_tools,,$(TARGET)-) + +########################################################################################## + +$(gcc) \ +$(binutils) \ +$(gmp) \ +$(mpfr) \ +$(mpc) \ +$(bfdmakes) \ +$(ccache) : ENVS += $(TOOLS) + +# libdir to work around hateful bfd stuff installing into wrong dirs... +# ensure we have 64 bit bfd support in the HOST library. I.e our +# compiler on i686 will know 64 bit symbols, BUT later +# we build just the libs again for TARGET, then with whatever the arch +# wants. +$(BUILDDIR)/$(binutils_ver)/Makefile : CONFIG += --enable-64-bit-bfd --libdir=$(PREFIX)/$(word 1,$(LIBDIRS)) + +# Makefile creation. Simply run configure in build dir. +$(bfdmakes) \ +$(BUILDDIR)/$(binutils_ver)/Makefile \ + : $(BINUTILS_CFG) + $(info Configuring $@. Log in $(@D)/log.config) + @mkdir -p $(@D) + ( \ + cd $(@D) ; \ + $(PATHPRE) $(ENVS) CFLAGS="$(CFLAGS)" \ + $(BINUTILS_CFG) \ + $(CONFIG) \ + --with-sysroot=$(SYSROOT) \ + --disable-nls \ + --program-prefix=$(TARGET)- \ + --enable-multilib \ + ) > $(@D)/log.config 2>&1 + @echo 'done' + +$(BUILDDIR)/$(mpfr_ver)/Makefile \ + : $(MPFR_CFG) + $(info Configuring $@. Log in $(@D)/log.config) + @mkdir -p $(@D) + ( \ + cd $(@D) ; \ + $(PATHPRE) $(ENVS) CFLAGS="$(CFLAGS)" \ + $(MPFR_CFG) \ + $(CONFIG) \ + --program-prefix=$(TARGET)- \ + --enable-shared=no \ + --with-gmp=$(PREFIX) \ + ) > $(@D)/log.config 2>&1 + @echo 'done' + +$(BUILDDIR)/$(gmp_ver)/Makefile \ + : $(GMP_CFG) + $(info Configuring $@. Log in $(@D)/log.config) + @mkdir -p $(@D) + ( \ + cd $(@D) ; \ + $(PATHPRE) $(ENVS) CFLAGS="$(CFLAGS)" \ + $(GMP_CFG) \ + --host=$(HOST) --build=$(BUILD) \ + --prefix=$(PREFIX) \ + --disable-nls \ + --program-prefix=$(TARGET)- \ + --enable-shared=no \ + --with-mpfr=$(PREFIX) \ + ) > $(@D)/log.config 2>&1 + @echo 'done' + +$(BUILDDIR)/$(mpc_ver)/Makefile \ + : $(MPC_CFG) + $(info Configuring $@. Log in $(@D)/log.config) + @mkdir -p $(@D) + ( \ + cd $(@D) ; \ + $(PATHPRE) $(ENVS) CFLAGS="$(CFLAGS)" \ + $(MPC_CFG) \ + $(CONFIG) \ + --program-prefix=$(TARGET)- \ + --enable-shared=no \ + --with-mpfr=$(PREFIX) \ + --with-gmp=$(PREFIX) \ + ) > $(@D)/log.config 2>&1 + @echo 'done' + +# Only valid if glibc target -> linux +# proper destructor handling for c++ +ifneq (,$(findstring linux,$(TARGET))) +$(BUILDDIR)/$(gcc_ver)/Makefile : CONFIG += --enable-__cxa_atexit +endif + +# Want: +# c,c++ +# shared libs +# multilib (-m32/-m64 on x64) +# skip native language. +# and link and assemble with the binutils we created +# earlier, so --with-gnu* +$(BUILDDIR)/$(gcc_ver)/Makefile \ + : $(GCC_CFG) + $(info Configuring $@. Log in $(@D)/log.config) + mkdir -p $(@D) + ( \ + cd $(@D) ; \ + $(PATHPRE) $(ENVS) $(GCC_CFG) $(EXTRA_CFLAGS) \ + $(CONFIG) \ + --with-sysroot=$(SYSROOT) \ + --enable-languages=c,c++ \ + --enable-shared \ + --enable-multilib \ + --disable-nls \ + --with-gnu-as \ + --with-gnu-ld \ + --with-mpfr=$(PREFIX) \ + --with-gmp=$(PREFIX) \ + --with-mpc=$(PREFIX) \ + ) > $(@D)/log.config 2>&1 + @echo 'done' + +# need binutils for gcc +$(gcc) : $(binutils) + +# as of 4.3 or so need these for doing config +$(BUILDDIR)/$(gcc_ver)/Makefile : $(gmp) $(mpfr) $(mpc) +$(mpfr) : $(gmp) +$(mpc) : $(gmp) $(mpfr) + +########################################################################################## +# very straightforward. just build a ccache. it is only for host. +$(BUILDDIR)/$(ccache_ver)/Makefile \ + : $(CCACHE_CFG) + $(info Configuring $@. Log in $(@D)/log.config) + @mkdir -p $(@D) + @( \ + cd $(@D) ; \ + $(PATHPRE) $(ENVS) $(CCACHE_CFG) \ + $(CONFIG) \ + ) > $(@D)/log.config 2>&1 + @echo 'done' + +gccpatch = $(TARGETDIR)/gcc-patched + +########################################################################################## +# For some reason cpp is not created as a target-compiler +ifeq ($(HOST),$(TARGET)) +$(gccpatch) : $(gcc) link_libs + @echo -n 'Creating compiler symlinks...' + @for f in cpp; do \ + if [ ! -e $(PREFIX)/bin/$(TARGET)-$$f ];\ + then \ + cd $(PREFIX)/bin && \ + ln -s $$f $(TARGET)-$$f ; \ + fi \ + done + @touch $@ + @echo 'done' + +########################################################################################## +# Ugly at best. Seems that when we compile host->host compiler, that are NOT +# the BUILD compiler, the result will not try searching for libs in package root. +# "Solve" this by create links from the target libdirs to where they are. +link_libs: + @echo -n 'Creating library symlinks...' + @$(foreach l,$(LIBDIRS), \ + for f in `cd $(PREFIX)/$(l) && ls`; do \ + if [ ! -e $(TARGETDIR)/$(l)/$$f ]; then \ + mkdir -p $(TARGETDIR)/$(l) && \ + cd $(TARGETDIR)/$(l)/ && \ + ln -s $(if $(findstring /,$(l)),../,)../../$(l)/$$f $$f; \ + fi \ + done;) + @echo 'done' +else +$(gccpatch) : + @echo 'done' +endif + +########################################################################################## +# Build in two steps. +# make +# make install. +# Use path to our build hosts cross tools +# Always need to build cross tools for build host self. +$(TARGETDIR)/%.done : $(BUILDDIR)/%/Makefile + $(info Building $(basename $@). Log in $( $(&1 + @echo -n 'installing...' + $(PATHPRE) $(MAKE) $(INSTALLPAR) -f $< -C $( $(&1 + @touch $@ + @echo 'done' + +########################################################################################## + +bfdlib : $(bfdlib) +binutils : $(binutils) +rpms : $(rpms) +libs : $(libs) +sysroot : rpms libs +gcc : sysroot $(gcc) $(gccpatch) +all : binutils gcc bfdlib + +# this is only built for host. so separate. +ccache : $(ccache) + +.PHONY : gcc all binutils bfdlib link_libs rpms libs sysroot diff -r 41b9fc8961f6 -r f1a01fb5f958 corba/.hgtags --- a/corba/.hgtags Thu Jun 13 09:49:19 2013 -0700 +++ b/corba/.hgtags Wed Jul 05 18:59:39 2017 +0200 @@ -215,3 +215,4 @@ 8f7ffb296385f85a4a6d53f9f2d4a7b13a8fa1ff jdk8-b91 717aa26f8e0a1c0e768aebb3a763aca56db0c83e jdk8-b92 8dc9d7ccbb2d77fd89bc321bb02e67c152aca257 jdk8-b93 +22f5d7f261d9d61a953d2d9a53f2e9ce0ca361d1 jdk8-b94 diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/.hgtags --- a/hotspot/.hgtags Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/.hgtags Wed Jul 05 18:59:39 2017 +0200 @@ -349,3 +349,5 @@ 573d86d412cd9d3df7912194c1a540be50e9544e jdk8-b93 b786c04b7be15194febe88dc1f0c9443e737a84b hs25-b35 3c78a14da19d26d6937af5f98b97e2a21c653b04 hs25-b36 +1beed1f6f9edefe47ba8ed1355fbd3e7606b8288 jdk8-b94 +69689078dff8b21e6df30870464f5d736eebdf72 hs25-b37 diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/make/Makefile --- a/hotspot/make/Makefile Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/make/Makefile Wed Jul 05 18:59:39 2017 +0200 @@ -486,7 +486,7 @@ JFR_EXISTS=$(shell if [ -d $(HS_ALT_SRC) ]; then echo 1; else echo 0; fi) # export jfr.h ifeq ($JFR_EXISTS,1) -$(EXPORT_INCLUDE_DIR)/%: $(HS_ALT_SRC)/share/vm/jfr/agent/% +$(EXPORT_INCLUDE_DIR)/%: $(HS_ALT_SRC)/share/vm/jfr/% $(install-file) else $(EXPORT_INCLUDE_DIR)/jfr.h: diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/make/bsd/makefiles/buildtree.make --- a/hotspot/make/bsd/makefiles/buildtree.make Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/make/bsd/makefiles/buildtree.make Wed Jul 05 18:59:39 2017 +0200 @@ -47,6 +47,7 @@ # flags.make - with macro settings # vm.make - to support making "$(MAKE) -v vm.make" in makefiles # adlc.make - +# trace.make - generate tracing event and type definitions # jvmti.make - generate JVMTI bindings from the spec (JSR-163) # sa.make - generate SA jar file and natives # @@ -119,6 +120,7 @@ $(PLATFORM_DIR)/generated/dependencies \ $(PLATFORM_DIR)/generated/adfiles \ $(PLATFORM_DIR)/generated/jvmtifiles \ + $(PLATFORM_DIR)/generated/tracefiles \ $(PLATFORM_DIR)/generated/dtracefiles TARGETS = debug fastdebug optimized product @@ -128,7 +130,7 @@ BUILDTREE_MAKE = $(GAMMADIR)/make/$(OS_FAMILY)/makefiles/buildtree.make # dtrace.make is used on BSD versions that implement Dtrace (like MacOS X) -BUILDTREE_TARGETS = Makefile flags.make flags_vm.make vm.make adlc.make jvmti.make sa.make dtrace.make +BUILDTREE_TARGETS = Makefile flags.make flags_vm.make vm.make adlc.make jvmti.make trace.make sa.make dtrace.make BUILDTREE_VARS = GAMMADIR=$(GAMMADIR) OS_FAMILY=$(OS_FAMILY) \ SRCARCH=$(SRCARCH) BUILDARCH=$(BUILDARCH) LIBARCH=$(LIBARCH) VARIANT=$(VARIANT) @@ -331,6 +333,16 @@ echo "include \$$(GAMMADIR)/make/$(OS_FAMILY)/makefiles/$(@F)"; \ ) > $@ +trace.make: $(BUILDTREE_MAKE) + @echo Creating $@ ... + $(QUIETLY) ( \ + $(BUILDTREE_COMMENT); \ + echo; \ + echo include flags.make; \ + echo; \ + echo "include \$$(GAMMADIR)/make/$(OS_FAMILY)/makefiles/$(@F)"; \ + ) > $@ + sa.make: $(BUILDTREE_MAKE) @echo Creating $@ ... $(QUIETLY) ( \ diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/make/bsd/makefiles/minimal1.make --- a/hotspot/make/bsd/makefiles/minimal1.make Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/make/bsd/makefiles/minimal1.make Wed Jul 05 18:59:39 2017 +0200 @@ -19,7 +19,7 @@ # 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. -# +# # TYPE=MINIMAL1 @@ -32,6 +32,7 @@ INCLUDE_MANAGEMENT ?= false INCLUDE_ALL_GCS ?= false INCLUDE_NMT ?= false +INCLUDE_TRACE ?= false INCLUDE_CDS ?= false CXXFLAGS += -DMINIMAL_JVM -DCOMPILER1 -DVMTYPE=\"Minimal\" diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/make/bsd/makefiles/top.make --- a/hotspot/make/bsd/makefiles/top.make Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/make/bsd/makefiles/top.make Wed Jul 05 18:59:39 2017 +0200 @@ -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 @@ -80,7 +80,7 @@ @echo All done. # This is an explicit dependency for the sake of parallel makes. -vm_build_preliminaries: checks $(Cached_plat) $(AD_Files_If_Required) jvmti_stuff sa_stuff dtrace_stuff +vm_build_preliminaries: checks $(Cached_plat) $(AD_Files_If_Required) jvmti_stuff trace_stuff sa_stuff dtrace_stuff @# We need a null action here, so implicit rules don't get consulted. $(Cached_plat): $(Plat_File) @@ -94,6 +94,10 @@ jvmti_stuff: $(Cached_plat) $(adjust-mflags) @$(MAKE) -f jvmti.make $(MFLAGS-adjusted) +# generate trace files +trace_stuff: jvmti_stuff $(Cached_plat) $(adjust-mflags) + @$(MAKE) -f trace.make $(MFLAGS-adjusted) + ifeq ($(OS_VENDOR), Darwin) # generate dtrace header files dtrace_stuff: $(Cached_plat) $(adjust-mflags) diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/make/bsd/makefiles/trace.make --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/make/bsd/makefiles/trace.make Wed Jul 05 18:59:39 2017 +0200 @@ -0,0 +1,121 @@ +# +# 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 +# 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. +# +# + +# This makefile (trace.make) is included from the trace.make in the +# build directories. +# +# It knows how to build and run the tools to generate trace files. + +include $(GAMMADIR)/make/bsd/makefiles/rules.make +include $(GAMMADIR)/make/altsrc.make + +# ######################################################################### + +HAS_ALT_SRC:=$(shell if [ -d $(HS_ALT_SRC)/share/vm/trace ]; then \ + echo "true"; else echo "false";\ + fi) + +TOPDIR = $(shell echo `pwd`) +GENERATED = $(TOPDIR)/../generated +JvmtiOutDir = $(GENERATED)/jvmtifiles +TraceOutDir = $(GENERATED)/tracefiles + +TraceAltSrcDir = $(HS_ALT_SRC)/share/vm/trace +TraceSrcDir = $(HS_COMMON_SRC)/share/vm/trace + +# set VPATH so make knows where to look for source files +Src_Dirs_V += $(TraceSrcDir) $(TraceAltSrcDir) +VPATH += $(Src_Dirs_V:%=%:) + +TraceGeneratedNames = \ + traceEventClasses.hpp \ + traceEventIds.hpp \ + traceTypes.hpp + +ifeq ($(HAS_ALT_SRC), true) +TraceGeneratedNames += \ + traceRequestables.hpp \ + traceEventControl.hpp + +ifneq ($(INCLUDE_TRACE), false) +TraceGeneratedNames += traceProducer.cpp +endif + +endif + + +TraceGeneratedFiles = $(TraceGeneratedNames:%=$(TraceOutDir)/%) + +XSLT = $(REMOTE) $(RUN.JAVA) -classpath $(JvmtiOutDir) jvmtiGen + +XML_DEPS = $(TraceSrcDir)/trace.xml $(TraceSrcDir)/tracetypes.xml \ + $(TraceSrcDir)/trace.dtd $(TraceSrcDir)/xinclude.mod +ifeq ($(HAS_ALT_SRC), true) + XML_DEPS += $(TraceAltSrcDir)/traceevents.xml +endif + +.PHONY: all clean cleanall + +# ######################################################################### + +all: $(TraceGeneratedFiles) + +GENERATE_CODE= \ + $(QUIETLY) echo Generating $@; \ + $(XSLT) -IN $(word 1,$^) -XSL $(word 2,$^) -OUT $@; \ + test -f $@ + +$(TraceOutDir)/traceEventIds.hpp: $(TraceSrcDir)/trace.xml $(TraceSrcDir)/traceEventIds.xsl $(XML_DEPS) + $(GENERATE_CODE) + +$(TraceOutDir)/traceTypes.hpp: $(TraceSrcDir)/trace.xml $(TraceSrcDir)/traceTypes.xsl $(XML_DEPS) + $(GENERATE_CODE) + +ifeq ($(HAS_ALT_SRC), false) + +$(TraceOutDir)/traceEventClasses.hpp: $(TraceSrcDir)/trace.xml $(TraceSrcDir)/traceEventClasses.xsl $(XML_DEPS) + $(GENERATE_CODE) + +else + +$(TraceOutDir)/traceEventClasses.hpp: $(TraceSrcDir)/trace.xml $(TraceAltSrcDir)/traceEventClasses.xsl $(XML_DEPS) + $(GENERATE_CODE) + +$(TraceOutDir)/traceProducer.cpp: $(TraceSrcDir)/trace.xml $(TraceAltSrcDir)/traceProducer.xsl $(XML_DEPS) + $(GENERATE_CODE) + +$(TraceOutDir)/traceRequestables.hpp: $(TraceSrcDir)/trace.xml $(TraceAltSrcDir)/traceRequestables.xsl $(XML_DEPS) + $(GENERATE_CODE) + +$(TraceOutDir)/traceEventControl.hpp: $(TraceSrcDir)/trace.xml $(TraceAltSrcDir)/traceEventControl.xsl $(XML_DEPS) + $(GENERATE_CODE) + +endif + +# ######################################################################### + + +clean cleanall: + rm $(TraceGeneratedFiles) + diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/make/bsd/makefiles/vm.make --- a/hotspot/make/bsd/makefiles/vm.make Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/make/bsd/makefiles/vm.make Wed Jul 05 18:59:39 2017 +0200 @@ -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 @@ -19,7 +19,7 @@ # 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. -# +# # # Rules to build JVM and related libraries, included from vm.make in the build @@ -52,7 +52,7 @@ # Src_Dirs_V is everything in src/share/vm/*, plus the right os/*/vm and cpu/*/vm # The adfiles directory contains ad_.[ch]pp. # The jvmtifiles directory contains jvmti*.[ch]pp -Src_Dirs_V += $(GENERATED)/adfiles $(GENERATED)/jvmtifiles +Src_Dirs_V += $(GENERATED)/adfiles $(GENERATED)/jvmtifiles $(GENERATED)/tracefiles VPATH += $(Src_Dirs_V:%=%:) # set INCLUDES for C preprocessor. @@ -66,7 +66,7 @@ SYMFLAG = endif -# HOTSPOT_RELEASE_VERSION and HOTSPOT_BUILD_VERSION are defined +# HOTSPOT_RELEASE_VERSION and HOTSPOT_BUILD_VERSION are defined # in $(GAMMADIR)/make/defs.make ifeq ($(HOTSPOT_BUILD_VERSION),) BUILD_VERSION = -DHOTSPOT_RELEASE_VERSION="\"$(HOTSPOT_RELEASE_VERSION)\"" @@ -93,7 +93,7 @@ # This is VERY important! The version define must only be supplied to vm_version.o # If not, ccache will not re-use the cache at all, since the version string might contain -# a time and date. +# a time and date. CXXFLAGS/vm_version.o += ${JRE_VERSION} CXXFLAGS/BYFILE = $(CXXFLAGS/$@) @@ -105,10 +105,6 @@ CXXFLAGS += -DDEFAULT_LIBPATH="\"$(DEFAULT_LIBPATH)\"" endif -ifndef JAVASE_EMBEDDED -CFLAGS += -DINCLUDE_TRACE -endif - # CFLAGS_WARN holds compiler options to suppress/enable warnings. CFLAGS += $(CFLAGS_WARN/BYFILE) @@ -165,15 +161,15 @@ SOURCE_PATHS+=$(HS_COMMON_SRC)/cpu/$(Platform_arch)/vm SOURCE_PATHS+=$(HS_COMMON_SRC)/os_cpu/$(Platform_os_arch)/vm -ifndef JAVASE_EMBEDDED -SOURCE_PATHS+=$(shell if [ -d $(HS_ALT_SRC)/share/vm/jfr ]; then \ +CORE_PATHS=$(foreach path,$(SOURCE_PATHS),$(call altsrc,$(path)) $(path)) +CORE_PATHS+=$(GENERATED)/jvmtifiles $(GENERATED)/tracefiles + +ifneq ($(INCLUDE_TRACE), false) +CORE_PATHS+=$(shell if [ -d $(HS_ALT_SRC)/share/vm/jfr ]; then \ find $(HS_ALT_SRC)/share/vm/jfr -type d; \ fi) endif -CORE_PATHS=$(foreach path,$(SOURCE_PATHS),$(call altsrc,$(path)) $(path)) -CORE_PATHS+=$(GENERATED)/jvmtifiles - COMPILER1_PATHS := $(call altsrc,$(HS_COMMON_SRC)/share/vm/c1) COMPILER1_PATHS += $(HS_COMMON_SRC)/share/vm/c1 diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/make/defs.make --- a/hotspot/make/defs.make Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/make/defs.make Wed Jul 05 18:59:39 2017 +0200 @@ -1,5 +1,5 @@ # -# Copyright (c) 2006, 2012, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2006, 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 @@ -19,7 +19,7 @@ # 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. -# +# # # The common definitions for hotspot builds. @@ -236,7 +236,7 @@ JDK_IMAGE_DIR=$(ALT_JDK_IMAGE_DIR) endif -# The platform dependent defs.make defines platform specific variable such +# The platform dependent defs.make defines platform specific variable such # as ARCH, EXPORT_LIST etc. We must place the include here after BOOTDIR is defined. include $(GAMMADIR)/make/$(OSNAME)/makefiles/defs.make @@ -258,7 +258,7 @@ # LIBARCH - directory name in JDK/JRE # Use uname output for SRCARCH, but deal with platform differences. If ARCH - # is not explicitly listed below, it is treated as x86. + # is not explicitly listed below, it is treated as x86. SRCARCH = $(ARCH/$(filter sparc sparc64 ia64 amd64 x86_64 arm ppc zero,$(ARCH))) ARCH/ = x86 ARCH/sparc = sparc @@ -337,8 +337,5 @@ EXPORT_LIST += $(EXPORT_INCLUDE_DIR)/$(JDK_INCLUDE_SUBDIR)/jni_md.h EXPORT_LIST += $(EXPORT_INCLUDE_DIR)/jmm.h -ifndef JAVASE_EMBEDDED -EXPORT_LIST += $(EXPORT_INCLUDE_DIR)/jfr.h -endif +.PHONY: $(HS_ALT_MAKE)/defs.make -.PHONY: $(HS_ALT_MAKE)/defs.make diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/make/excludeSrc.make --- a/hotspot/make/excludeSrc.make Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/make/excludeSrc.make Wed Jul 05 18:59:39 2017 +0200 @@ -19,7 +19,7 @@ # 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. -# +# # ifeq ($(INCLUDE_JVMTI), false) CXXFLAGS += -DINCLUDE_JVMTI=0 @@ -100,7 +100,7 @@ parCardTableModRefBS.cpp parGCAllocBuffer.cpp parNewGeneration.cpp mutableSpace.cpp \ gSpaceCounters.cpp allocationStats.cpp spaceCounters.cpp gcAdaptivePolicyCounters.cpp \ mutableNUMASpace.cpp immutableSpace.cpp yieldingWorkGroup.cpp -endif +endif ifeq ($(INCLUDE_NMT), false) CXXFLAGS += -DINCLUDE_NMT=0 @@ -110,3 +110,5 @@ memBaseline.cpp memPtr.cpp memRecorder.cpp memReporter.cpp memSnapshot.cpp memTrackWorker.cpp \ memTracker.cpp nmtDCmd.cpp endif + +-include $(HS_ALT_MAKE)/excludeSrc.make diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/make/hotspot_version --- a/hotspot/make/hotspot_version Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/make/hotspot_version Wed Jul 05 18:59:39 2017 +0200 @@ -35,7 +35,7 @@ HS_MAJOR_VER=25 HS_MINOR_VER=0 -HS_BUILD_NUMBER=36 +HS_BUILD_NUMBER=37 JDK_MAJOR_VER=1 JDK_MINOR_VER=8 diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/make/linux/makefiles/buildtree.make --- a/hotspot/make/linux/makefiles/buildtree.make Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/make/linux/makefiles/buildtree.make Wed Jul 05 18:59:39 2017 +0200 @@ -47,6 +47,7 @@ # flags.make - with macro settings # vm.make - to support making "$(MAKE) -v vm.make" in makefiles # adlc.make - +# trace.make - generate tracing event and type definitions # jvmti.make - generate JVMTI bindings from the spec (JSR-163) # sa.make - generate SA jar file and natives # @@ -114,7 +115,8 @@ SIMPLE_DIRS = \ $(PLATFORM_DIR)/generated/dependencies \ $(PLATFORM_DIR)/generated/adfiles \ - $(PLATFORM_DIR)/generated/jvmtifiles + $(PLATFORM_DIR)/generated/jvmtifiles \ + $(PLATFORM_DIR)/generated/tracefiles TARGETS = debug fastdebug optimized product SUBMAKE_DIRS = $(addprefix $(PLATFORM_DIR)/,$(TARGETS)) @@ -122,7 +124,7 @@ # For dependencies and recursive makes. BUILDTREE_MAKE = $(GAMMADIR)/make/$(OS_FAMILY)/makefiles/buildtree.make -BUILDTREE_TARGETS = Makefile flags.make flags_vm.make vm.make adlc.make jvmti.make sa.make +BUILDTREE_TARGETS = Makefile flags.make flags_vm.make vm.make adlc.make jvmti.make trace.make sa.make BUILDTREE_VARS = GAMMADIR=$(GAMMADIR) OS_FAMILY=$(OS_FAMILY) \ SRCARCH=$(SRCARCH) BUILDARCH=$(BUILDARCH) LIBARCH=$(LIBARCH) VARIANT=$(VARIANT) @@ -269,6 +271,8 @@ echo && \ echo "HOTSPOT_EXTRA_SYSDEFS\$$(HOTSPOT_EXTRA_SYSDEFS) = $(HOTSPOT_EXTRA_SYSDEFS)" && \ echo "SYSDEFS += \$$(HOTSPOT_EXTRA_SYSDEFS)"; \ + [ -n "$(INCLUDE_TRACE)" ] && \ + echo && echo "INCLUDE_TRACE = $(INCLUDE_TRACE)"; \ echo; \ [ -n "$(SPEC)" ] && \ echo "include $(SPEC)"; \ @@ -337,6 +341,16 @@ echo "include \$$(GAMMADIR)/make/$(OS_FAMILY)/makefiles/$(@F)"; \ ) > $@ +trace.make: $(BUILDTREE_MAKE) + @echo Creating $@ ... + $(QUIETLY) ( \ + $(BUILDTREE_COMMENT); \ + echo; \ + echo include flags.make; \ + echo; \ + echo "include \$$(GAMMADIR)/make/$(OS_FAMILY)/makefiles/$(@F)"; \ + ) > $@ + sa.make: $(BUILDTREE_MAKE) @echo Creating $@ ... $(QUIETLY) ( \ diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/make/linux/makefiles/minimal1.make --- a/hotspot/make/linux/makefiles/minimal1.make Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/make/linux/makefiles/minimal1.make Wed Jul 05 18:59:39 2017 +0200 @@ -19,7 +19,7 @@ # 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. -# +# # TYPE=MINIMAL1 @@ -32,6 +32,7 @@ INCLUDE_MANAGEMENT ?= false INCLUDE_ALL_GCS ?= false INCLUDE_NMT ?= false +INCLUDE_TRACE ?= false INCLUDE_CDS ?= false CXXFLAGS += -DMINIMAL_JVM -DCOMPILER1 -DVMTYPE=\"Minimal\" diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/make/linux/makefiles/top.make --- a/hotspot/make/linux/makefiles/top.make Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/make/linux/makefiles/top.make Wed Jul 05 18:59:39 2017 +0200 @@ -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 @@ -80,7 +80,7 @@ @echo All done. # This is an explicit dependency for the sake of parallel makes. -vm_build_preliminaries: checks $(Cached_plat) $(AD_Files_If_Required) jvmti_stuff sa_stuff +vm_build_preliminaries: checks $(Cached_plat) $(AD_Files_If_Required) trace_stuff jvmti_stuff sa_stuff @# We need a null action here, so implicit rules don't get consulted. $(Cached_plat): $(Plat_File) @@ -94,6 +94,10 @@ jvmti_stuff: $(Cached_plat) $(adjust-mflags) @$(MAKE) -f jvmti.make $(MFLAGS-adjusted) +# generate trace files +trace_stuff: jvmti_stuff $(Cached_plat) $(adjust-mflags) + @$(MAKE) -f trace.make $(MFLAGS-adjusted) + # generate SA jar files and native header sa_stuff: @$(MAKE) -f sa.make $(MFLAGS-adjusted) diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/make/linux/makefiles/trace.make --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/make/linux/makefiles/trace.make Wed Jul 05 18:59:39 2017 +0200 @@ -0,0 +1,120 @@ +# +# 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 +# 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. +# +# + +# This makefile (trace.make) is included from the trace.make in the +# build directories. +# +# It knows how to build and run the tools to generate trace files. + +include $(GAMMADIR)/make/linux/makefiles/rules.make +include $(GAMMADIR)/make/altsrc.make + +# ######################################################################### + +HAS_ALT_SRC:=$(shell if [ -d $(HS_ALT_SRC)/share/vm/trace ]; then \ + echo "true"; else echo "false";\ + fi) + +TOPDIR = $(shell echo `pwd`) +GENERATED = $(TOPDIR)/../generated +JvmtiOutDir = $(GENERATED)/jvmtifiles +TraceOutDir = $(GENERATED)/tracefiles + +TraceAltSrcDir = $(HS_ALT_SRC)/share/vm/trace +TraceSrcDir = $(HS_COMMON_SRC)/share/vm/trace + +# set VPATH so make knows where to look for source files +Src_Dirs_V += $(TraceSrcDir) $(TraceAltSrcDir) +VPATH += $(Src_Dirs_V:%=%:) + +TraceGeneratedNames = \ + traceEventClasses.hpp \ + traceEventIds.hpp \ + traceTypes.hpp + +ifeq ($(HAS_ALT_SRC), true) +TraceGeneratedNames += \ + traceRequestables.hpp \ + traceEventControl.hpp + +ifneq ($(INCLUDE_TRACE), false) +TraceGeneratedNames += traceProducer.cpp +endif + +endif + +TraceGeneratedFiles = $(TraceGeneratedNames:%=$(TraceOutDir)/%) + +XSLT = $(REMOTE) $(RUN.JAVA) -classpath $(JvmtiOutDir) jvmtiGen + +XML_DEPS = $(TraceSrcDir)/trace.xml $(TraceSrcDir)/tracetypes.xml \ + $(TraceSrcDir)/trace.dtd $(TraceSrcDir)/xinclude.mod +ifeq ($(HAS_ALT_SRC), true) + XML_DEPS += $(TraceAltSrcDir)/traceevents.xml +endif + +.PHONY: all clean cleanall + +# ######################################################################### + +all: $(TraceGeneratedFiles) + +GENERATE_CODE= \ + $(QUIETLY) echo Generating $@; \ + $(XSLT) -IN $(word 1,$^) -XSL $(word 2,$^) -OUT $@; \ + test -f $@ + +$(TraceOutDir)/traceEventIds.hpp: $(TraceSrcDir)/trace.xml $(TraceSrcDir)/traceEventIds.xsl $(XML_DEPS) + $(GENERATE_CODE) + +$(TraceOutDir)/traceTypes.hpp: $(TraceSrcDir)/trace.xml $(TraceSrcDir)/traceTypes.xsl $(XML_DEPS) + $(GENERATE_CODE) + +ifeq ($(HAS_ALT_SRC), false) + +$(TraceOutDir)/traceEventClasses.hpp: $(TraceSrcDir)/trace.xml $(TraceSrcDir)/traceEventClasses.xsl $(XML_DEPS) + $(GENERATE_CODE) + +else + +$(TraceOutDir)/traceEventClasses.hpp: $(TraceSrcDir)/trace.xml $(TraceAltSrcDir)/traceEventClasses.xsl $(XML_DEPS) + $(GENERATE_CODE) + +$(TraceOutDir)/traceProducer.cpp: $(TraceSrcDir)/trace.xml $(TraceAltSrcDir)/traceProducer.xsl $(XML_DEPS) + $(GENERATE_CODE) + +$(TraceOutDir)/traceRequestables.hpp: $(TraceSrcDir)/trace.xml $(TraceAltSrcDir)/traceRequestables.xsl $(XML_DEPS) + $(GENERATE_CODE) + +$(TraceOutDir)/traceEventControl.hpp: $(TraceSrcDir)/trace.xml $(TraceAltSrcDir)/traceEventControl.xsl $(XML_DEPS) + $(GENERATE_CODE) + +endif + +# ######################################################################### + +clean cleanall: + rm $(TraceGeneratedFiles) + + diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/make/linux/makefiles/vm.make --- a/hotspot/make/linux/makefiles/vm.make Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/make/linux/makefiles/vm.make Wed Jul 05 18:59:39 2017 +0200 @@ -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 @@ -19,7 +19,7 @@ # 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. -# +# # # Rules to build JVM and related libraries, included from vm.make in the build @@ -52,7 +52,7 @@ # Src_Dirs_V is everything in src/share/vm/*, plus the right os/*/vm and cpu/*/vm # The adfiles directory contains ad_.[ch]pp. # The jvmtifiles directory contains jvmti*.[ch]pp -Src_Dirs_V += $(GENERATED)/adfiles $(GENERATED)/jvmtifiles +Src_Dirs_V += $(GENERATED)/adfiles $(GENERATED)/jvmtifiles $(GENERATED)/tracefiles VPATH += $(Src_Dirs_V:%=%:) # set INCLUDES for C preprocessor. @@ -72,7 +72,7 @@ endif endif -# HOTSPOT_RELEASE_VERSION and HOTSPOT_BUILD_VERSION are defined +# HOTSPOT_RELEASE_VERSION and HOTSPOT_BUILD_VERSION are defined # in $(GAMMADIR)/make/defs.make ifeq ($(HOTSPOT_BUILD_VERSION),) BUILD_VERSION = -DHOTSPOT_RELEASE_VERSION="\"$(HOTSPOT_RELEASE_VERSION)\"" @@ -99,7 +99,7 @@ # This is VERY important! The version define must only be supplied to vm_version.o # If not, ccache will not re-use the cache at all, since the version string might contain -# a time and date. +# a time and date. CXXFLAGS/vm_version.o += ${JRE_VERSION} CXXFLAGS/BYFILE = $(CXXFLAGS/$@) @@ -108,12 +108,6 @@ CXXFLAGS += $(CXXFLAGS/BYFILE) -ifndef JAVASE_EMBEDDED -ifneq (${ARCH},arm) -CFLAGS += -DINCLUDE_TRACE -endif -endif - # CFLAGS_WARN holds compiler options to suppress/enable warnings. CFLAGS += $(CFLAGS_WARN/BYFILE) @@ -158,16 +152,14 @@ SOURCE_PATHS+=$(HS_COMMON_SRC)/cpu/$(Platform_arch)/vm SOURCE_PATHS+=$(HS_COMMON_SRC)/os_cpu/$(Platform_os_arch)/vm -ifndef JAVASE_EMBEDDED -ifneq (${ARCH},arm) -SOURCE_PATHS+=$(shell if [ -d $(HS_ALT_SRC)/share/vm/jfr ]; then \ +CORE_PATHS=$(foreach path,$(SOURCE_PATHS),$(call altsrc,$(path)) $(path)) +CORE_PATHS+=$(GENERATED)/jvmtifiles $(GENERATED)/tracefiles + +ifneq ($(INCLUDE_TRACE), false) +CORE_PATHS+=$(shell if [ -d $(HS_ALT_SRC)/share/vm/jfr ]; then \ find $(HS_ALT_SRC)/share/vm/jfr -type d; \ fi) endif -endif - -CORE_PATHS=$(foreach path,$(SOURCE_PATHS),$(call altsrc,$(path)) $(path)) -CORE_PATHS+=$(GENERATED)/jvmtifiles COMPILER1_PATHS := $(call altsrc,$(HS_COMMON_SRC)/share/vm/c1) COMPILER1_PATHS += $(HS_COMMON_SRC)/share/vm/c1 @@ -316,7 +308,7 @@ # With more recent Redhat releases (or the cutting edge version Fedora), if # SELinux is configured to be enabled, the runtime linker will fail to apply # the text relocation to libjvm.so considering that it is built as a non-PIC -# DSO. To workaround that, we run chcon to libjvm.so after it is built. See +# DSO. To workaround that, we run chcon to libjvm.so after it is built. See # details in bug 6538311. $(LIBJVM): $(LIBJVM.o) $(LIBJVM_MAPFILE) $(LD_SCRIPT) $(QUIETLY) { \ diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/make/solaris/makefiles/buildtree.make --- a/hotspot/make/solaris/makefiles/buildtree.make Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/make/solaris/makefiles/buildtree.make Wed Jul 05 18:59:39 2017 +0200 @@ -47,6 +47,7 @@ # flags.make - with macro settings # vm.make - to support making "$(MAKE) -v vm.make" in makefiles # adlc.make - +# trace.make - generate tracing event and type definitions # jvmti.make - generate JVMTI bindings from the spec (JSR-163) # sa.make - generate SA jar file and natives # @@ -107,7 +108,8 @@ SIMPLE_DIRS = \ $(PLATFORM_DIR)/generated/dependencies \ $(PLATFORM_DIR)/generated/adfiles \ - $(PLATFORM_DIR)/generated/jvmtifiles + $(PLATFORM_DIR)/generated/jvmtifiles \ + $(PLATFORM_DIR)/generated/tracefiles TARGETS = debug fastdebug optimized product SUBMAKE_DIRS = $(addprefix $(PLATFORM_DIR)/,$(TARGETS)) @@ -115,7 +117,7 @@ # For dependencies and recursive makes. BUILDTREE_MAKE = $(GAMMADIR)/make/$(OS_FAMILY)/makefiles/buildtree.make -BUILDTREE_TARGETS = Makefile flags.make flags_vm.make vm.make adlc.make jvmti.make sa.make +BUILDTREE_TARGETS = Makefile flags.make flags_vm.make vm.make adlc.make jvmti.make trace.make sa.make BUILDTREE_VARS = GAMMADIR=$(GAMMADIR) OS_FAMILY=$(OS_FAMILY) \ ARCH=$(ARCH) BUILDARCH=$(BUILDARCH) LIBARCH=$(LIBARCH) VARIANT=$(VARIANT) @@ -327,6 +329,16 @@ echo "include \$$(GAMMADIR)/make/$(OS_FAMILY)/makefiles/$(@F)"; \ ) > $@ +trace.make: $(BUILDTREE_MAKE) + @echo Creating $@ ... + $(QUIETLY) ( \ + $(BUILDTREE_COMMENT); \ + echo; \ + echo include flags.make; \ + echo; \ + echo "include \$$(GAMMADIR)/make/$(OS_FAMILY)/makefiles/$(@F)"; \ + ) > $@ + sa.make: $(BUILDTREE_MAKE) @echo Creating $@ ... $(QUIETLY) ( \ diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/make/solaris/makefiles/top.make --- a/hotspot/make/solaris/makefiles/top.make Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/make/solaris/makefiles/top.make Wed Jul 05 18:59:39 2017 +0200 @@ -1,5 +1,5 @@ # -# Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 1998, 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 @@ -73,7 +73,7 @@ @echo All done. # This is an explicit dependency for the sake of parallel makes. -vm_build_preliminaries: checks $(Cached_plat) $(AD_Files_If_Required) jvmti_stuff sa_stuff +vm_build_preliminaries: checks $(Cached_plat) $(AD_Files_If_Required) jvmti_stuff trace_stuff sa_stuff @# We need a null action here, so implicit rules don't get consulted. $(Cached_plat): $(Plat_File) @@ -87,6 +87,10 @@ jvmti_stuff: $(Cached_plat) $(adjust-mflags) @$(MAKE) -f jvmti.make $(MFLAGS-adjusted) +# generate trace files +trace_stuff: jvmti_stuff $(Cached_plat) $(adjust-mflags) + @$(MAKE) -f trace.make $(MFLAGS-adjusted) + # generate SA jar files and native header sa_stuff: @$(MAKE) -f sa.make $(MFLAGS-adjusted) @@ -127,5 +131,5 @@ rm -fr $(GENERATED) .PHONY: default vm_build_preliminaries -.PHONY: lists ad_stuff jvmti_stuff sa_stuff the_vm clean realclean +.PHONY: lists ad_stuff jvmti_stuff trace_stuff sa_stuff the_vm clean realclean .PHONY: checks check_os_version install diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/make/solaris/makefiles/trace.make --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/make/solaris/makefiles/trace.make Wed Jul 05 18:59:39 2017 +0200 @@ -0,0 +1,116 @@ +# +# 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 +# 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. +# +# + +# This makefile (trace.make) is included from the trace.make in the +# build directories. +# +# It knows how to build and run the tools to generate trace files. + +include $(GAMMADIR)/make/solaris/makefiles/rules.make +include $(GAMMADIR)/make/altsrc.make + +# ######################################################################### + +HAS_ALT_SRC:=$(shell if [ -d $(HS_ALT_SRC)/share/vm/trace ]; then \ + echo "true"; else echo "false";\ + fi) + +TOPDIR = $(shell echo `pwd`) +GENERATED = $(TOPDIR)/../generated +JvmtiOutDir = $(GENERATED)/jvmtifiles +TraceOutDir = $(GENERATED)/tracefiles + +TraceAltSrcDir = $(HS_ALT_SRC)/share/vm/trace +TraceSrcDir = $(HS_COMMON_SRC)/share/vm/trace + +# set VPATH so make knows where to look for source files +Src_Dirs_V += $(TraceSrcDir) $(TraceAltSrcDir) +VPATH += $(Src_Dirs_V:%=%:) + +TraceGeneratedNames = \ + traceEventClasses.hpp \ + traceEventIds.hpp \ + traceTypes.hpp + +ifeq ($(HAS_ALT_SRC), true) +TraceGeneratedNames += \ + traceRequestables.hpp \ + traceEventControl.hpp \ + traceProducer.cpp +endif + +TraceGeneratedFiles = $(TraceGeneratedNames:%=$(TraceOutDir)/%) + +XSLT = $(REMOTE) $(RUN.JAVA) -classpath $(JvmtiOutDir) jvmtiGen + +XML_DEPS = $(TraceSrcDir)/trace.xml $(TraceSrcDir)/tracetypes.xml \ + $(TraceSrcDir)/trace.dtd $(TraceSrcDir)/xinclude.mod +ifeq ($(HAS_ALT_SRC), true) + XML_DEPS += $(TraceAltSrcDir)/traceevents.xml +endif + +.PHONY: all clean cleanall + +# ######################################################################### + +all: $(TraceGeneratedFiles) + +GENERATE_CODE= \ + $(QUIETLY) echo Generating $@; \ + $(XSLT) -IN $(word 1,$^) -XSL $(word 2,$^) -OUT $@; \ + test -f $@ + +$(TraceOutDir)/traceEventIds.hpp: $(TraceSrcDir)/trace.xml $(TraceSrcDir)/traceEventIds.xsl $(XML_DEPS) + $(GENERATE_CODE) + +$(TraceOutDir)/traceTypes.hpp: $(TraceSrcDir)/trace.xml $(TraceSrcDir)/traceTypes.xsl $(XML_DEPS) + $(GENERATE_CODE) + +ifeq ($(HAS_ALT_SRC), false) + +$(TraceOutDir)/traceEventClasses.hpp: $(TraceSrcDir)/trace.xml $(TraceSrcDir)/traceEventClasses.xsl $(XML_DEPS) + $(GENERATE_CODE) + +else + +$(TraceOutDir)/traceEventClasses.hpp: $(TraceSrcDir)/trace.xml $(TraceAltSrcDir)/traceEventClasses.xsl $(XML_DEPS) + $(GENERATE_CODE) + +$(TraceOutDir)/traceProducer.cpp: $(TraceSrcDir)/trace.xml $(TraceAltSrcDir)/traceProducer.xsl $(XML_DEPS) + $(GENERATE_CODE) + +$(TraceOutDir)/traceRequestables.hpp: $(TraceSrcDir)/trace.xml $(TraceAltSrcDir)/traceRequestables.xsl $(XML_DEPS) + $(GENERATE_CODE) + +$(TraceOutDir)/traceEventControl.hpp: $(TraceSrcDir)/trace.xml $(TraceAltSrcDir)/traceEventControl.xsl $(XML_DEPS) + $(GENERATE_CODE) + +endif + +# ######################################################################### + +clean cleanall: + rm $(TraceGeneratedFiles) + + diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/make/solaris/makefiles/vm.make --- a/hotspot/make/solaris/makefiles/vm.make Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/make/solaris/makefiles/vm.make Wed Jul 05 18:59:39 2017 +0200 @@ -1,5 +1,5 @@ # -# Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 1998, 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 @@ -19,7 +19,7 @@ # 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. -# +# # # Rules to build JVM and related libraries, included from vm.make in the build @@ -48,7 +48,7 @@ # Src_Dirs_V is everything in src/share/vm/*, plus the right os/*/vm and cpu/*/vm # The adfiles directory contains ad_.[ch]pp. # The jvmtifiles directory contains jvmti*.[ch]pp -Src_Dirs_V += $(GENERATED)/adfiles $(GENERATED)/jvmtifiles +Src_Dirs_V += $(GENERATED)/adfiles $(GENERATED)/jvmtifiles $(GENERATED)/tracefiles VPATH += $(Src_Dirs_V:%=%:) # set INCLUDES for C preprocessor @@ -87,7 +87,7 @@ # This is VERY important! The version define must only be supplied to vm_version.o # If not, ccache will not re-use the cache at all, since the version string might contain -# a time and date. +# a time and date. CXXFLAGS/vm_version.o += ${JRE_VERSION} CXXFLAGS/BYFILE = $(CXXFLAGS/$@) @@ -103,7 +103,7 @@ CFLAGS += $(CFLAGS/NOEX) # Extra flags from gnumake's invocation or environment -CFLAGS += $(EXTRA_CFLAGS) -DINCLUDE_TRACE +CFLAGS += $(EXTRA_CFLAGS) # Math Library (libm.so), do not use -lm. # There might be two versions of libm.so on the build system: @@ -137,9 +137,7 @@ LIBS += -lsocket -lsched -ldl $(LIBM) -lthread -lc -ldemangle endif # sparcWorks -ifeq ("${Platform_arch}", "sparc") LIBS += -lkstat -endif # By default, link the *.o into the library, not the executable. LINK_INTO$(LINK_INTO) = LIBJVM @@ -177,12 +175,14 @@ SOURCE_PATHS+=$(HS_COMMON_SRC)/cpu/$(Platform_arch)/vm SOURCE_PATHS+=$(HS_COMMON_SRC)/os_cpu/$(Platform_os_arch)/vm -SOURCE_PATHS+=$(shell if [ -d $(HS_ALT_SRC)/share/vm/jfr ]; then \ +CORE_PATHS=$(foreach path,$(SOURCE_PATHS),$(call altsrc,$(path)) $(path)) +CORE_PATHS+=$(GENERATED)/jvmtifiles $(GENERATED)/tracefiles + +ifneq ($(INCLUDE_TRACE), false) +CORE_PATHS+=$(shell if [ -d $(HS_ALT_SRC)/share/vm/jfr ]; then \ find $(HS_ALT_SRC)/share/vm/jfr -type d; \ fi) - -CORE_PATHS=$(foreach path,$(SOURCE_PATHS),$(call altsrc,$(path)) $(path)) -CORE_PATHS+=$(GENERATED)/jvmtifiles +endif COMPILER1_PATHS := $(call altsrc,$(HS_COMMON_SRC)/share/vm/c1) COMPILER1_PATHS += $(HS_COMMON_SRC)/share/vm/c1 @@ -287,7 +287,7 @@ LINK_VM = $(LINK_LIB.CXX) endif # making the library: -$(LIBJVM): $(ADD_GNU_DEBUGLINK) $(FIX_EMPTY_SEC_HDR_FLAGS) $(LIBJVM.o) $(LIBJVM_MAPFILE) +$(LIBJVM): $(ADD_GNU_DEBUGLINK) $(FIX_EMPTY_SEC_HDR_FLAGS) $(LIBJVM.o) $(LIBJVM_MAPFILE) ifeq ($(filter -sbfast -xsbfast, $(CFLAGS_BROWSE)),) @echo Linking vm... $(QUIETLY) $(LINK_LIB.CXX/PRE_HOOK) diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/make/windows/build.make --- a/hotspot/make/windows/build.make Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/make/windows/build.make Wed Jul 05 18:59:39 2017 +0200 @@ -196,6 +196,12 @@ # End VERSIONINFO parameters +# if hotspot-only build and/or OPENJDK isn't passed down, need to set OPENJDK +!ifndef OPENJDK +!if !exists($(WorkSpace)\src\closed) +OPENJDK=true +!endif +!endif # We don't support SA on ia64, and we can't # build it if we are using a version of Vis Studio @@ -273,6 +279,7 @@ @ echo HS_COMPANY=$(COMPANY_NAME) >> $@ @ echo HS_FILEDESC=$(HS_FILEDESC) >> $@ @ echo HOTSPOT_VM_DISTRO=$(HOTSPOT_VM_DISTRO) >> $@ + @ if "$(OPENJDK)" NEQ "" echo OPENJDK=$(OPENJDK) >> $@ @ echo HS_COPYRIGHT=$(HOTSPOT_VM_COPYRIGHT) >> $@ @ echo HS_NAME=$(PRODUCT_NAME) $(JDK_MKTG_VERSION) >> $@ @ echo HS_BUILD_VER=$(HS_BUILD_VER) >> $@ diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/make/windows/create_obj_files.sh --- a/hotspot/make/windows/create_obj_files.sh Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/make/windows/create_obj_files.sh Wed Jul 05 18:59:39 2017 +0200 @@ -71,13 +71,11 @@ BASE_PATHS="${BASE_PATHS} ${COMMONSRC}/${sd}" done -BASE_PATHS="${BASE_PATHS} ${GENERATED}/jvmtifiles" +BASE_PATHS="${BASE_PATHS} ${GENERATED}/jvmtifiles ${GENERATED}/tracefiles" if [ -d "${ALTSRC}/share/vm/jfr" ]; then - BASE_PATHS="${BASE_PATHS} ${ALTSRC}/share/vm/jfr/agent" - BASE_PATHS="${BASE_PATHS} ${ALTSRC}/share/vm/jfr/agent/isolated_deps/util" - BASE_PATHS="${BASE_PATHS} ${ALTSRC}/share/vm/jfr/jvm" - BASE_PATHS="${BASE_PATHS} ${ALTSRC}/share/vm/jfr" + BASE_PATHS="${BASE_PATHS} ${ALTSRC}/share/vm/jfr" + BASE_PATHS="${BASE_PATHS} ${ALTSRC}/share/vm/jfr/buffers" fi BASE_PATHS="${BASE_PATHS} ${COMMONSRC}/share/vm/prims/wbtestmethods" diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/make/windows/makefiles/generated.make --- a/hotspot/make/windows/makefiles/generated.make Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/make/windows/makefiles/generated.make Wed Jul 05 18:59:39 2017 +0200 @@ -1,5 +1,5 @@ # -# Copyright (c) 2005, 2010, 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 @@ -30,15 +30,19 @@ JvmtiOutDir=jvmtifiles !include $(WorkSpace)/make/windows/makefiles/jvmti.make +# Pick up rules for building trace +TraceOutDir=tracefiles +!include $(WorkSpace)/make/windows/makefiles/trace.make + # Pick up rules for building SA !include $(WorkSpace)/make/windows/makefiles/sa.make AdlcOutDir=adfiles !if ("$(Variant)" == "compiler2") || ("$(Variant)" == "tiered") -default:: $(AdlcOutDir)/ad_$(Platform_arch_model).cpp $(AdlcOutDir)/dfa_$(Platform_arch_model).cpp $(JvmtiGeneratedFiles) buildobjfiles +default:: $(AdlcOutDir)/ad_$(Platform_arch_model).cpp $(AdlcOutDir)/dfa_$(Platform_arch_model).cpp $(JvmtiGeneratedFiles) $(TraceGeneratedFiles) buildobjfiles !else -default:: $(JvmtiGeneratedFiles) buildobjfiles +default:: $(JvmtiGeneratedFiles) $(TraceGeneratedFiles) buildobjfiles !endif buildobjfiles: diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/make/windows/makefiles/projectcreator.make --- a/hotspot/make/windows/makefiles/projectcreator.make Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/make/windows/makefiles/projectcreator.make Wed Jul 05 18:59:39 2017 +0200 @@ -19,7 +19,7 @@ # Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA # or visit www.oracle.com if you need additional information or have any # questions. -# +# # !include $(WorkSpace)/make/windows/makefiles/rules.make @@ -72,7 +72,7 @@ -ignorePath ppc \ -ignorePath zero \ -hidePath .hg - + # This is referenced externally by both the IDE and batch builds ProjectCreatorOptions= @@ -89,7 +89,7 @@ -disablePch bytecodeInterpreter.cpp \ -disablePch bytecodeInterpreterWithChecks.cpp \ -disablePch getThread_windows_$(Platform_arch).cpp \ - -disablePch_compiler2 opcodes.cpp + -disablePch_compiler2 opcodes.cpp # Common options for the IDE builds for core, c1, and c2 ProjectCreatorIDEOptions=\ @@ -115,7 +115,7 @@ -define TARGET_OS_ARCH_windows_x86 \ -define TARGET_OS_FAMILY_windows \ -define TARGET_COMPILER_visCPP \ - -define INCLUDE_TRACE \ + -define INCLUDE_TRACE=1 \ $(ProjectCreatorIncludesPRIVATE) # Add in build-specific options @@ -203,4 +203,12 @@ -additionalFile jvmtiEnter.cpp \ -additionalFile jvmtiEnterTrace.cpp \ -additionalFile jvmti.h \ - -additionalFile bytecodeInterpreterWithChecks.cpp + -additionalFile bytecodeInterpreterWithChecks.cpp \ + -additionalFile traceEventClasses.hpp \ + -additionalFile traceEventIds.hpp \ +!if "$(OPENJDK)" != "true" + -additionalFile traceRequestables.hpp \ + -additionalFile traceEventControl.hpp \ + -additionalFile traceProducer.cpp \ +!endif + -additionalFile traceTypes.hpp diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/make/windows/makefiles/trace.make --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/make/windows/makefiles/trace.make Wed Jul 05 18:59:39 2017 +0200 @@ -0,0 +1,121 @@ +# +# 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 +# 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. +# +# + +# This makefile (trace.make) is included from the trace.make in the +# build directories. +# +# It knows how to build and run the tools to generate trace files. + +!include $(WorkSpace)/make/windows/makefiles/rules.make + +# ######################################################################### + + +TraceAltSrcDir = $(WorkSpace)/src/closed/share/vm/trace +TraceSrcDir = $(WorkSpace)/src/share/vm/trace + +TraceGeneratedNames = \ + traceEventClasses.hpp \ + traceEventIds.hpp \ + traceTypes.hpp + + +!if "$(OPENJDK)" != "true" +TraceGeneratedNames = $(TraceGeneratedNames) \ + traceRequestables.hpp \ + traceEventControl.hpp \ + traceProducer.cpp +!endif + + +#Note: TraceGeneratedFiles must be kept in sync with TraceGeneratedNames by hand. +#Should be equivalent to "TraceGeneratedFiles = $(TraceGeneratedNames:%=$(TraceOutDir)/%)" +TraceGeneratedFiles = \ + $(TraceOutDir)/traceEventClasses.hpp \ + $(TraceOutDir)/traceEventIds.hpp \ + $(TraceOutDir)/traceTypes.hpp + +!if "$(OPENJDK)" != "true" +TraceGeneratedFiles = $(TraceGeneratedFiles) \ + $(TraceOutDir)/traceRequestables.hpp \ + $(TraceOutDir)/traceEventControl.hpp \ + $(TraceOutDir)/traceProducer.cpp +!endif + +XSLT = $(QUIETLY) $(REMOTE) $(RUN_JAVA) -classpath $(JvmtiOutDir) jvmtiGen + +XML_DEPS = $(TraceSrcDir)/trace.xml $(TraceSrcDir)/tracetypes.xml \ + $(TraceSrcDir)/trace.dtd $(TraceSrcDir)/xinclude.mod + +!if "$(OPENJDK)" != "true" +XML_DEPS = $(XML_DEPS) $(TraceAltSrcDir)/traceevents.xml +!endif + +.PHONY: all clean cleanall + +# ######################################################################### + +default:: + @if not exist $(TraceOutDir) mkdir $(TraceOutDir) + +$(TraceOutDir)/traceEventIds.hpp: $(TraceSrcDir)/trace.xml $(TraceSrcDir)/traceEventIds.xsl $(XML_DEPS) + @echo Generating $@ + @$(XSLT) -IN $(TraceSrcDir)/trace.xml -XSL $(TraceSrcDir)/traceEventIds.xsl -OUT $(TraceOutDir)/traceEventIds.hpp + +$(TraceOutDir)/traceTypes.hpp: $(TraceSrcDir)/trace.xml $(TraceSrcDir)/traceTypes.xsl $(XML_DEPS) + @echo Generating $@ + @$(XSLT) -IN $(TraceSrcDir)/trace.xml -XSL $(TraceSrcDir)/traceTypes.xsl -OUT $(TraceOutDir)/traceTypes.hpp + +!if "$(OPENJDK)" == "true" + +$(TraceOutDir)/traceEventClasses.hpp: $(TraceSrcDir)/trace.xml $(TraceSrcDir)/traceEventClasses.xsl $(XML_DEPS) + @echo Generating $@ + @$(XSLT) -IN $(TraceSrcDir)/trace.xml -XSL $(TraceSrcDir)/traceEventClasses.xsl -OUT $(TraceOutDir)/traceEventClasses.hpp + +!else + +$(TraceOutDir)/traceEventClasses.hpp: $(TraceSrcDir)/trace.xml $(TraceAltSrcDir)/traceEventClasses.xsl $(XML_DEPS) + @echo Generating $@ + @$(XSLT) -IN $(TraceSrcDir)/trace.xml -XSL $(TraceAltSrcDir)/traceEventClasses.xsl -OUT $(TraceOutDir)/traceEventClasses.hpp + +$(TraceOutDir)/traceProducer.cpp: $(TraceSrcDir)/trace.xml $(TraceAltSrcDir)/traceProducer.xsl $(XML_DEPS) + @echo Generating $@ + @$(XSLT) -IN $(TraceSrcDir)/trace.xml -XSL $(TraceAltSrcDir)/traceProducer.xsl -OUT $(TraceOutDir)/traceProducer.cpp + +$(TraceOutDir)/traceRequestables.hpp: $(TraceSrcDir)/trace.xml $(TraceAltSrcDir)/traceRequestables.xsl $(XML_DEPS) + @echo Generating $@ + @$(XSLT) -IN $(TraceSrcDir)/trace.xml -XSL $(TraceAltSrcDir)/traceRequestables.xsl -OUT $(TraceOutDir)/traceRequestables.hpp + +$(TraceOutDir)/traceEventControl.hpp: $(TraceSrcDir)/trace.xml $(TraceAltSrcDir)/traceEventControl.xsl $(XML_DEPS) + @echo Generating $@ + @$(XSLT) -IN $(TraceSrcDir)/trace.xml -XSL $(TraceAltSrcDir)/traceEventControl.xsl -OUT $(TraceOutDir)/traceEventControl.hpp + +!endif + +# ######################################################################### + +cleanall : + rm $(TraceGeneratedFiles) + + diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/make/windows/makefiles/vm.make --- a/hotspot/make/windows/makefiles/vm.make Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/make/windows/makefiles/vm.make Wed Jul 05 18:59:39 2017 +0200 @@ -66,10 +66,6 @@ CXX_FLAGS=$(CXX_FLAGS) /D "HOTSPOT_BUILD_USER=\"$(BuildUser)\"" CXX_FLAGS=$(CXX_FLAGS) /D "HOTSPOT_VM_DISTRO=\"$(HOTSPOT_VM_DISTRO)\"" -!ifndef JAVASE_EMBEDDED -CXX_FLAGS=$(CXX_FLAGS) /D "INCLUDE_TRACE" -!endif - CXX_FLAGS=$(CXX_FLAGS) $(CXX_INCLUDE_DIRS) # Define that so jni.h is on correct side @@ -144,6 +140,7 @@ VM_PATH=../generated VM_PATH=$(VM_PATH);../generated/adfiles VM_PATH=$(VM_PATH);../generated/jvmtifiles +VM_PATH=$(VM_PATH);../generated/tracefiles VM_PATH=$(VM_PATH);$(WorkSpace)/src/share/vm/c1 VM_PATH=$(VM_PATH);$(WorkSpace)/src/share/vm/compiler VM_PATH=$(VM_PATH);$(WorkSpace)/src/share/vm/code @@ -172,10 +169,8 @@ VM_PATH=$(VM_PATH);$(WorkSpace)/src/share/vm/opto !if exists($(ALTSRC)\share\vm\jfr) -VM_PATH=$(VM_PATH);$(ALTSRC)/share/vm/jfr/agent -VM_PATH=$(VM_PATH);$(ALTSRC)/share/vm/jfr/agent/isolated_deps/util -VM_PATH=$(VM_PATH);$(ALTSRC)/share/vm/jfr/jvm VM_PATH=$(VM_PATH);$(ALTSRC)/share/vm/jfr +VM_PATH=$(VM_PATH);$(ALTSRC)/share/vm/jfr/buffers !endif VM_PATH={$(VM_PATH)} @@ -384,16 +379,13 @@ {..\generated\jvmtifiles}.cpp.obj:: $(CXX) $(CXX_FLAGS) $(CXX_USE_PCH) /c $< +{..\generated\tracefiles}.cpp.obj:: + $(CXX) $(CXX_FLAGS) $(CXX_USE_PCH) /c $< + {$(ALTSRC)\share\vm\jfr}.cpp.obj:: $(CXX) $(CXX_FLAGS) $(CXX_USE_PCH) /c $< -{$(ALTSRC)\share\vm\jfr\agent}.cpp.obj:: - $(CXX) $(CXX_FLAGS) $(CXX_USE_PCH) /c $< - -{$(ALTSRC)\share\vm\jfr\agent\isolated_deps\util}.cpp.obj:: - $(CXX) $(CXX_FLAGS) $(CXX_USE_PCH) /c $< - -{$(ALTSRC)\share\vm\jfr\jvm}.cpp.obj:: +{$(ALTSRC)\share\vm\jfr\buffers}.cpp.obj:: $(CXX) $(CXX_FLAGS) $(CXX_USE_PCH) /c $< default:: diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/make/windows/projectfiles/common/Makefile --- a/hotspot/make/windows/projectfiles/common/Makefile Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/make/windows/projectfiles/common/Makefile Wed Jul 05 18:59:39 2017 +0200 @@ -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 @@ -45,6 +45,12 @@ !endif !endif +# if hotspot-only build and/or OPENJDK isn't passed down, need to set OPENJDK +!ifndef OPENJDK +!if !exists($(WorkSpace)\src\closed) +OPENJDK=true +!endif +!endif !include $(HOTSPOTWORKSPACE)/make/windows/makefiles/projectcreator.make @@ -54,6 +60,10 @@ JvmtiOutDir=$(HOTSPOTBUILDSPACE)\$(Variant)\generated\jvmtifiles !include $(HOTSPOTWORKSPACE)/make/windows/makefiles/jvmti.make +# Pick up rules for building trace +TraceOutDir=$(HOTSPOTBUILDSPACE)\$(Variant)\generated\tracefiles +!include $(HOTSPOTWORKSPACE)/make/windows/makefiles/trace.make + !if "$(Variant)" == "compiler2" # Pick up rules for building adlc !include $(HOTSPOTWORKSPACE)/make/windows/makefiles/adlc.make @@ -66,7 +76,7 @@ HS_INTERNAL_NAME=jvm -default:: $(AdditionalTargets) $(JvmtiGeneratedFiles) +default:: $(AdditionalTargets) $(JvmtiGeneratedFiles) $(TraceGeneratedFiles) !include $(HOTSPOTWORKSPACE)/make/hotspot_version diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/cpu/sparc/vm/frame_sparc.cpp --- a/hotspot/src/cpu/sparc/vm/frame_sparc.cpp Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/src/cpu/sparc/vm/frame_sparc.cpp Wed Jul 05 18:59:39 2017 +0200 @@ -252,6 +252,16 @@ return false; } + // Could be a zombie method + if (sender_blob->is_zombie() || sender_blob->is_unloaded()) { + return false; + } + + // Could be a zombie method + if (sender_blob->is_zombie() || sender_blob->is_unloaded()) { + return false; + } + // It should be safe to construct the sender though it might not be valid frame sender(_SENDER_SP, younger_sp, adjusted_stack); @@ -294,10 +304,10 @@ return jcw_safe; } - // If the frame size is 0 something is bad because every nmethod has a non-zero frame size + // If the frame size is 0 something (or less) is bad because every nmethod has a non-zero frame size // because you must allocate window space - if (sender_blob->frame_size() == 0) { + if (sender_blob->frame_size() <= 0) { assert(!sender_blob->is_nmethod(), "should count return address at least"); return false; } diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/cpu/x86/vm/frame_x86.cpp --- a/hotspot/src/cpu/x86/vm/frame_x86.cpp Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/src/cpu/x86/vm/frame_x86.cpp Wed Jul 05 18:59:39 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -33,6 +33,7 @@ #include "runtime/handles.inline.hpp" #include "runtime/javaCalls.hpp" #include "runtime/monitorChunk.hpp" +#include "runtime/os.hpp" #include "runtime/signature.hpp" #include "runtime/stubCodeGenerator.hpp" #include "runtime/stubRoutines.hpp" @@ -54,16 +55,22 @@ address sp = (address)_sp; address fp = (address)_fp; address unextended_sp = (address)_unextended_sp; - // sp must be within the stack - bool sp_safe = (sp <= thread->stack_base()) && - (sp >= thread->stack_base() - thread->stack_size()); + + // consider stack guards when trying to determine "safe" stack pointers + static size_t stack_guard_size = os::uses_stack_guard_pages() ? (StackYellowPages + StackRedPages) * os::vm_page_size() : 0; + size_t usable_stack_size = thread->stack_size() - stack_guard_size; + + // sp must be within the usable part of the stack (not in guards) + bool sp_safe = (sp < thread->stack_base()) && + (sp >= thread->stack_base() - usable_stack_size); + if (!sp_safe) { return false; } // unextended sp must be within the stack and above or equal sp - bool unextended_sp_safe = (unextended_sp <= thread->stack_base()) && + bool unextended_sp_safe = (unextended_sp < thread->stack_base()) && (unextended_sp >= sp); if (!unextended_sp_safe) { @@ -71,7 +78,8 @@ } // an fp must be within the stack and above (but not equal) sp - bool fp_safe = (fp <= thread->stack_base()) && (fp > sp); + // second evaluation on fp+ is added to handle situation where fp is -1 + bool fp_safe = (fp < thread->stack_base() && (fp > sp) && (((fp + (return_addr_offset * sizeof(void*))) < thread->stack_base()))); // We know sp/unextended_sp are safe only fp is questionable here @@ -86,6 +94,13 @@ // other generic buffer blobs are more problematic so we just assume they are // ok. adapter blobs never have a frame complete and are never ok. + // check for a valid frame_size, otherwise we are unlikely to get a valid sender_pc + + if (!Interpreter::contains(_pc) && _cb->frame_size() <= 0) { + //assert(0, "Invalid frame_size"); + return false; + } + if (!_cb->is_frame_complete_at(_pc)) { if (_cb->is_nmethod() || _cb->is_adapter_blob() || _cb->is_runtime_stub()) { return false; @@ -107,7 +122,7 @@ address jcw = (address)entry_frame_call_wrapper(); - bool jcw_safe = (jcw <= thread->stack_base()) && ( jcw > fp); + bool jcw_safe = (jcw < thread->stack_base()) && ( jcw > fp); return jcw_safe; @@ -134,12 +149,6 @@ sender_pc = (address) *(sender_sp-1); } - // We must always be able to find a recognizable pc - CodeBlob* sender_blob = CodeCache::find_blob_unsafe(sender_pc); - if (sender_pc == NULL || sender_blob == NULL) { - return false; - } - // If the potential sender is the interpreter then we can do some more checking if (Interpreter::contains(sender_pc)) { @@ -149,7 +158,7 @@ // is really a frame pointer. intptr_t *saved_fp = (intptr_t*)*(sender_sp - frame::sender_sp_offset); - bool saved_fp_safe = ((address)saved_fp <= thread->stack_base()) && (saved_fp > sender_sp); + bool saved_fp_safe = ((address)saved_fp < thread->stack_base()) && (saved_fp > sender_sp); if (!saved_fp_safe) { return false; @@ -163,6 +172,17 @@ } + // We must always be able to find a recognizable pc + CodeBlob* sender_blob = CodeCache::find_blob_unsafe(sender_pc); + if (sender_pc == NULL || sender_blob == NULL) { + return false; + } + + // Could be a zombie method + if (sender_blob->is_zombie() || sender_blob->is_unloaded()) { + return false; + } + // Could just be some random pointer within the codeBlob if (!sender_blob->code_contains(sender_pc)) { return false; @@ -174,10 +194,9 @@ } // Could be the call_stub - if (StubRoutines::returns_to_call_stub(sender_pc)) { intptr_t *saved_fp = (intptr_t*)*(sender_sp - frame::sender_sp_offset); - bool saved_fp_safe = ((address)saved_fp <= thread->stack_base()) && (saved_fp > sender_sp); + bool saved_fp_safe = ((address)saved_fp < thread->stack_base()) && (saved_fp > sender_sp); if (!saved_fp_safe) { return false; @@ -190,15 +209,24 @@ // Validate the JavaCallWrapper an entry frame must have address jcw = (address)sender.entry_frame_call_wrapper(); - bool jcw_safe = (jcw <= thread->stack_base()) && ( jcw > (address)sender.fp()); + bool jcw_safe = (jcw < thread->stack_base()) && ( jcw > (address)sender.fp()); return jcw_safe; } - // If the frame size is 0 something is bad because every nmethod has a non-zero frame size + if (sender_blob->is_nmethod()) { + nmethod* nm = sender_blob->as_nmethod_or_null(); + if (nm != NULL) { + if (nm->is_deopt_mh_entry(sender_pc) || nm->is_deopt_entry(sender_pc)) { + return false; + } + } + } + + // If the frame size is 0 something (or less) is bad because every nmethod has a non-zero frame size // because the return address counts against the callee's frame. - if (sender_blob->frame_size() == 0) { + if (sender_blob->frame_size() <= 0) { assert(!sender_blob->is_nmethod(), "should count return address at least"); return false; } @@ -208,7 +236,9 @@ // should not be anything but the call stub (already covered), the interpreter (already covered) // or an nmethod. - assert(sender_blob->is_nmethod(), "Impossible call chain"); + if (!sender_blob->is_nmethod()) { + return false; + } // Could put some more validation for the potential non-interpreted sender // frame we'd create by calling sender if I could think of any. Wait for next crash in forte... diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/os/bsd/vm/osThread_bsd.hpp --- a/hotspot/src/os/bsd/vm/osThread_bsd.hpp Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/src/os/bsd/vm/osThread_bsd.hpp Wed Jul 05 18:59:39 2017 +0200 @@ -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 @@ -94,7 +94,7 @@ // flags that support signal based suspend/resume on Bsd are in a // separate class to avoid confusion with many flags in OSThread that // are used by VM level suspend/resume. - os::Bsd::SuspendResume sr; + os::SuspendResume sr; // _ucontext and _siginfo are used by SR_handler() to save thread context, // and they will later be used to walk the stack or reposition thread PC. diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/os/bsd/vm/os_bsd.cpp --- a/hotspot/src/os/bsd/vm/os_bsd.cpp Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/src/os/bsd/vm/os_bsd.cpp Wed Jul 05 18:59:39 2017 +0200 @@ -1852,17 +1852,118 @@ // Bsd(POSIX) specific hand shaking semaphore. #ifdef __APPLE__ -static semaphore_t sig_sem; +typedef semaphore_t os_semaphore_t; #define SEM_INIT(sem, value) semaphore_create(mach_task_self(), &sem, SYNC_POLICY_FIFO, value) -#define SEM_WAIT(sem) semaphore_wait(sem); -#define SEM_POST(sem) semaphore_signal(sem); +#define SEM_WAIT(sem) semaphore_wait(sem) +#define SEM_POST(sem) semaphore_signal(sem) +#define SEM_DESTROY(sem) semaphore_destroy(mach_task_self(), sem) #else -static sem_t sig_sem; +typedef sem_t os_semaphore_t; #define SEM_INIT(sem, value) sem_init(&sem, 0, value) -#define SEM_WAIT(sem) sem_wait(&sem); -#define SEM_POST(sem) sem_post(&sem); +#define SEM_WAIT(sem) sem_wait(&sem) +#define SEM_POST(sem) sem_post(&sem) +#define SEM_DESTROY(sem) sem_destroy(&sem) #endif +class Semaphore : public StackObj { + public: + Semaphore(); + ~Semaphore(); + void signal(); + void wait(); + bool trywait(); + bool timedwait(unsigned int sec, int nsec); + private: + jlong currenttime() const; + semaphore_t _semaphore; +}; + +Semaphore::Semaphore() : _semaphore(0) { + SEM_INIT(_semaphore, 0); +} + +Semaphore::~Semaphore() { + SEM_DESTROY(_semaphore); +} + +void Semaphore::signal() { + SEM_POST(_semaphore); +} + +void Semaphore::wait() { + SEM_WAIT(_semaphore); +} + +jlong Semaphore::currenttime() const { + struct timeval tv; + gettimeofday(&tv, NULL); + return (tv.tv_sec * NANOSECS_PER_SEC) + (tv.tv_usec * 1000); +} + +#ifdef __APPLE__ +bool Semaphore::trywait() { + return timedwait(0, 0); +} + +bool Semaphore::timedwait(unsigned int sec, int nsec) { + kern_return_t kr = KERN_ABORTED; + mach_timespec_t waitspec; + waitspec.tv_sec = sec; + waitspec.tv_nsec = nsec; + + jlong starttime = currenttime(); + + kr = semaphore_timedwait(_semaphore, waitspec); + while (kr == KERN_ABORTED) { + jlong totalwait = (sec * NANOSECS_PER_SEC) + nsec; + + jlong current = currenttime(); + jlong passedtime = current - starttime; + + if (passedtime >= totalwait) { + waitspec.tv_sec = 0; + waitspec.tv_nsec = 0; + } else { + jlong waittime = totalwait - (current - starttime); + waitspec.tv_sec = waittime / NANOSECS_PER_SEC; + waitspec.tv_nsec = waittime % NANOSECS_PER_SEC; + } + + kr = semaphore_timedwait(_semaphore, waitspec); + } + + return kr == KERN_SUCCESS; +} + +#else + +bool Semaphore::trywait() { + return sem_trywait(&_semaphore) == 0; +} + +bool Semaphore::timedwait(unsigned int sec, int nsec) { + struct timespec ts; + jlong endtime = unpackTime(&ts, false, (sec * NANOSECS_PER_SEC) + nsec); + + while (1) { + int result = sem_timedwait(&_semaphore, &ts); + if (result == 0) { + return true; + } else if (errno == EINTR) { + continue; + } else if (errno == ETIMEDOUT) { + return false; + } else { + return false; + } + } +} + +#endif // __APPLE__ + +static os_semaphore_t sig_sem; +static Semaphore sr_semaphore; + void os::signal_init_pd() { // Initialize signal structures ::memset((void*)pending_signals, 0, sizeof(pending_signals)); @@ -2616,9 +2717,6 @@ static void resume_clear_context(OSThread *osthread) { osthread->set_ucontext(NULL); osthread->set_siginfo(NULL); - - // notify the suspend action is completed, we have now resumed - osthread->sr.clear_suspended(); } static void suspend_save_context(OSThread *osthread, siginfo_t* siginfo, ucontext_t* context) { @@ -2638,7 +2736,7 @@ // its signal handlers run and prevents sigwait()'s use with the // mutex granting granting signal. // -// Currently only ever called on the VMThread +// Currently only ever called on the VMThread or JavaThread // static void SR_handler(int sig, siginfo_t* siginfo, ucontext_t* context) { // Save and restore errno to avoid confusing native code with EINTR @@ -2647,38 +2745,48 @@ Thread* thread = Thread::current(); OSThread* osthread = thread->osthread(); - assert(thread->is_VM_thread(), "Must be VMThread"); - // read current suspend action - int action = osthread->sr.suspend_action(); - if (action == os::Bsd::SuspendResume::SR_SUSPEND) { + assert(thread->is_VM_thread() || thread->is_Java_thread(), "Must be VMThread or JavaThread"); + + os::SuspendResume::State current = osthread->sr.state(); + if (current == os::SuspendResume::SR_SUSPEND_REQUEST) { suspend_save_context(osthread, siginfo, context); - // Notify the suspend action is about to be completed. do_suspend() - // waits until SR_SUSPENDED is set and then returns. We will wait - // here for a resume signal and that completes the suspend-other - // action. do_suspend/do_resume is always called as a pair from - // the same thread - so there are no races - - // notify the caller - osthread->sr.set_suspended(); - - sigset_t suspend_set; // signals for sigsuspend() - - // get current set of blocked signals and unblock resume signal - pthread_sigmask(SIG_BLOCK, NULL, &suspend_set); - sigdelset(&suspend_set, SR_signum); - - // wait here until we are resumed - do { - sigsuspend(&suspend_set); - // ignore all returns until we get a resume signal - } while (osthread->sr.suspend_action() != os::Bsd::SuspendResume::SR_CONTINUE); + // attempt to switch the state, we assume we had a SUSPEND_REQUEST + os::SuspendResume::State state = osthread->sr.suspended(); + if (state == os::SuspendResume::SR_SUSPENDED) { + sigset_t suspend_set; // signals for sigsuspend() + + // get current set of blocked signals and unblock resume signal + pthread_sigmask(SIG_BLOCK, NULL, &suspend_set); + sigdelset(&suspend_set, SR_signum); + + sr_semaphore.signal(); + // wait here until we are resumed + while (1) { + sigsuspend(&suspend_set); + + os::SuspendResume::State result = osthread->sr.running(); + if (result == os::SuspendResume::SR_RUNNING) { + sr_semaphore.signal(); + break; + } else if (result != os::SuspendResume::SR_SUSPENDED) { + ShouldNotReachHere(); + } + } + + } else if (state == os::SuspendResume::SR_RUNNING) { + // request was cancelled, continue + } else { + ShouldNotReachHere(); + } resume_clear_context(osthread); - + } else if (current == os::SuspendResume::SR_RUNNING) { + // request was cancelled, continue + } else if (current == os::SuspendResume::SR_WAKEUP_REQUEST) { + // ignore } else { - assert(action == os::Bsd::SuspendResume::SR_CONTINUE, "unexpected sr action"); - // nothing special to do - just leave the handler + // ignore } errno = old_errno; @@ -2722,42 +2830,82 @@ return 0; } +static int sr_notify(OSThread* osthread) { + int status = pthread_kill(osthread->pthread_id(), SR_signum); + assert_status(status == 0, status, "pthread_kill"); + return status; +} + +// "Randomly" selected value for how long we want to spin +// before bailing out on suspending a thread, also how often +// we send a signal to a thread we want to resume +static const int RANDOMLY_LARGE_INTEGER = 1000000; +static const int RANDOMLY_LARGE_INTEGER2 = 100; // returns true on success and false on error - really an error is fatal // but this seems the normal response to library errors static bool do_suspend(OSThread* osthread) { + assert(osthread->sr.is_running(), "thread should be running"); + assert(!sr_semaphore.trywait(), "semaphore has invalid state"); + // mark as suspended and send signal - osthread->sr.set_suspend_action(os::Bsd::SuspendResume::SR_SUSPEND); - int status = pthread_kill(osthread->pthread_id(), SR_signum); - assert_status(status == 0, status, "pthread_kill"); - - // check status and wait until notified of suspension - if (status == 0) { - for (int i = 0; !osthread->sr.is_suspended(); i++) { - os::yield_all(i); - } - osthread->sr.set_suspend_action(os::Bsd::SuspendResume::SR_NONE); - return true; - } - else { - osthread->sr.set_suspend_action(os::Bsd::SuspendResume::SR_NONE); + if (osthread->sr.request_suspend() != os::SuspendResume::SR_SUSPEND_REQUEST) { + // failed to switch, state wasn't running? + ShouldNotReachHere(); return false; } + + if (sr_notify(osthread) != 0) { + ShouldNotReachHere(); + } + + // managed to send the signal and switch to SUSPEND_REQUEST, now wait for SUSPENDED + while (true) { + if (sr_semaphore.timedwait(0, 2 * NANOSECS_PER_MILLISEC)) { + break; + } else { + // timeout + os::SuspendResume::State cancelled = osthread->sr.cancel_suspend(); + if (cancelled == os::SuspendResume::SR_RUNNING) { + return false; + } else if (cancelled == os::SuspendResume::SR_SUSPENDED) { + // make sure that we consume the signal on the semaphore as well + sr_semaphore.wait(); + break; + } else { + ShouldNotReachHere(); + return false; + } + } + } + + guarantee(osthread->sr.is_suspended(), "Must be suspended"); + return true; } static void do_resume(OSThread* osthread) { assert(osthread->sr.is_suspended(), "thread should be suspended"); - osthread->sr.set_suspend_action(os::Bsd::SuspendResume::SR_CONTINUE); - - int status = pthread_kill(osthread->pthread_id(), SR_signum); - assert_status(status == 0, status, "pthread_kill"); - // check status and wait unit notified of resumption - if (status == 0) { - for (int i = 0; osthread->sr.is_suspended(); i++) { - os::yield_all(i); + assert(!sr_semaphore.trywait(), "invalid semaphore state"); + + if (osthread->sr.request_wakeup() != os::SuspendResume::SR_WAKEUP_REQUEST) { + // failed to switch to WAKEUP_REQUEST + ShouldNotReachHere(); + return; + } + + while (true) { + if (sr_notify(osthread) == 0) { + if (sr_semaphore.timedwait(0, 2 * NANOSECS_PER_MILLISEC)) { + if (osthread->sr.is_running()) { + return; + } + } + } else { + ShouldNotReachHere(); } } - osthread->sr.set_suspend_action(os::Bsd::SuspendResume::SR_NONE); + + guarantee(osthread->sr.is_running(), "Must be running!"); } //////////////////////////////////////////////////////////////////////////////// @@ -3508,7 +3656,40 @@ return false; } +void os::SuspendedThreadTask::internal_do_task() { + if (do_suspend(_thread->osthread())) { + SuspendedThreadTaskContext context(_thread, _thread->osthread()->ucontext()); + do_task(context); + do_resume(_thread->osthread()); + } +} + /// +class PcFetcher : public os::SuspendedThreadTask { +public: + PcFetcher(Thread* thread) : os::SuspendedThreadTask(thread) {} + ExtendedPC result(); +protected: + void do_task(const os::SuspendedThreadTaskContext& context); +private: + ExtendedPC _epc; +}; + +ExtendedPC PcFetcher::result() { + guarantee(is_done(), "task is not done yet."); + return _epc; +} + +void PcFetcher::do_task(const os::SuspendedThreadTaskContext& context) { + Thread* thread = context.thread(); + OSThread* osthread = thread->osthread(); + if (osthread->ucontext() != NULL) { + _epc = os::Bsd::ucontext_get_pc((ucontext_t *) context.ucontext()); + } else { + // NULL context is unexpected, double-check this is the VMThread + guarantee(thread->is_VM_thread(), "can only be called for VMThread"); + } +} // Suspends the target using the signal mechanism and then grabs the PC before // resuming the target. Used by the flat-profiler only @@ -3517,22 +3698,9 @@ assert(Thread::current()->is_Watcher_thread(), "Must be watcher"); assert(thread->is_VM_thread(), "Can only be called for VMThread"); - ExtendedPC epc; - - OSThread* osthread = thread->osthread(); - if (do_suspend(osthread)) { - if (osthread->ucontext() != NULL) { - epc = os::Bsd::ucontext_get_pc(osthread->ucontext()); - } else { - // NULL context is unexpected, double-check this is the VMThread - guarantee(thread->is_VM_thread(), "can only be called for VMThread"); - } - do_resume(osthread); - } - // failure means pthread_kill failed for some reason - arguably this is - // a fatal problem, but such problems are ignored elsewhere - - return epc; + PcFetcher fetcher(thread); + fetcher.run(); + return fetcher.result(); } int os::Bsd::safe_cond_timedwait(pthread_cond_t *_cond, pthread_mutex_t *_mutex, const struct timespec *_abstime) @@ -4517,3 +4685,4 @@ return n; } + diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/os/bsd/vm/os_bsd.hpp --- a/hotspot/src/os/bsd/vm/os_bsd.hpp Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/src/os/bsd/vm/os_bsd.hpp Wed Jul 05 18:59:39 2017 +0200 @@ -145,36 +145,6 @@ // BsdThreads work-around for 6292965 static int safe_cond_timedwait(pthread_cond_t *_cond, pthread_mutex_t *_mutex, const struct timespec *_abstime); - - // Bsd suspend/resume support - this helper is a shadow of its former - // self now that low-level suspension is barely used, and old workarounds - // for BsdThreads are no longer needed. - class SuspendResume { - private: - volatile int _suspend_action; - volatile jint _state; - public: - // values for suspend_action: - enum { - SR_NONE = 0x00, - SR_SUSPEND = 0x01, // suspend request - SR_CONTINUE = 0x02, // resume request - SR_SUSPENDED = 0x20 // values for _state: + SR_NONE - }; - - SuspendResume() { _suspend_action = SR_NONE; _state = SR_NONE; } - - int suspend_action() const { return _suspend_action; } - void set_suspend_action(int x) { _suspend_action = x; } - - // atomic updates for _state - inline void set_suspended(); - inline void clear_suspended(); - bool is_suspended() { return _state & SR_SUSPENDED; } - - #undef SR_SUSPENDED - }; - private: typedef int (*sched_getcpu_func_t)(void); typedef int (*numa_node_to_cpus_func_t)(int node, unsigned long *buffer, int bufferlen); @@ -250,7 +220,7 @@ int TryPark () ; int park (jlong millis) ; void SetAssociation (Thread * a) { _Assoc = a ; } -} ; +}; class PlatformParker : public CHeapObj { protected: @@ -268,6 +238,6 @@ status = pthread_mutex_init (_mutex, NULL); assert_status(status == 0, status, "mutex_init"); } -} ; +}; #endif // OS_BSD_VM_OS_BSD_HPP diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/os/bsd/vm/os_bsd.inline.hpp --- a/hotspot/src/os/bsd/vm/os_bsd.inline.hpp Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/src/os/bsd/vm/os_bsd.inline.hpp Wed Jul 05 18:59:39 2017 +0200 @@ -286,20 +286,4 @@ return ::setsockopt(fd, level, optname, optval, optlen); } -inline void os::Bsd::SuspendResume::set_suspended() { - jint temp, temp2; - do { - temp = _state; - temp2 = Atomic::cmpxchg(temp | SR_SUSPENDED, &_state, temp); - } while (temp2 != temp); -} - -inline void os::Bsd::SuspendResume::clear_suspended() { - jint temp, temp2; - do { - temp = _state; - temp2 = Atomic::cmpxchg(temp & ~SR_SUSPENDED, &_state, temp); - } while (temp2 != temp); -} - #endif // OS_BSD_VM_OS_BSD_INLINE_HPP diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/os/linux/vm/osThread_linux.hpp --- a/hotspot/src/os/linux/vm/osThread_linux.hpp Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/src/os/linux/vm/osThread_linux.hpp Wed Jul 05 18:59:39 2017 +0200 @@ -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 @@ -77,7 +77,7 @@ // flags that support signal based suspend/resume on Linux are in a // separate class to avoid confusion with many flags in OSThread that // are used by VM level suspend/resume. - os::Linux::SuspendResume sr; + os::SuspendResume sr; // _ucontext and _siginfo are used by SR_handler() to save thread context, // and they will later be used to walk the stack or reposition thread PC. diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/os/linux/vm/os_linux.cpp --- a/hotspot/src/os/linux/vm/os_linux.cpp Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/src/os/linux/vm/os_linux.cpp Wed Jul 05 18:59:39 2017 +0200 @@ -151,6 +151,9 @@ /* Used to protect dlsym() calls */ static pthread_mutex_t dl_mutex; +// Declarations +static void unpackTime(timespec* absTime, bool isAbsolute, jlong time); + #ifdef JAVASE_EMBEDDED class MemNotifyThread: public Thread { friend class VMStructs; @@ -2407,6 +2410,57 @@ return CAST_FROM_FN_PTR(void*, UserHandler); } +class Semaphore : public StackObj { + public: + Semaphore(); + ~Semaphore(); + void signal(); + void wait(); + bool trywait(); + bool timedwait(unsigned int sec, int nsec); + private: + sem_t _semaphore; +}; + + +Semaphore::Semaphore() { + sem_init(&_semaphore, 0, 0); +} + +Semaphore::~Semaphore() { + sem_destroy(&_semaphore); +} + +void Semaphore::signal() { + sem_post(&_semaphore); +} + +void Semaphore::wait() { + sem_wait(&_semaphore); +} + +bool Semaphore::trywait() { + return sem_trywait(&_semaphore) == 0; +} + +bool Semaphore::timedwait(unsigned int sec, int nsec) { + struct timespec ts; + unpackTime(&ts, false, (sec * NANOSECS_PER_SEC) + nsec); + + while (1) { + int result = sem_timedwait(&_semaphore, &ts); + if (result == 0) { + return true; + } else if (errno == EINTR) { + continue; + } else if (errno == ETIMEDOUT) { + return false; + } else { + return false; + } + } +} + extern "C" { typedef void (*sa_handler_t)(int); typedef void (*sa_sigaction_t)(int, siginfo_t *, void *); @@ -2446,6 +2500,7 @@ // Linux(POSIX) specific hand shaking semaphore. static sem_t sig_sem; +static Semaphore sr_semaphore; void os::signal_init_pd() { // Initialize signal structures @@ -3559,9 +3614,6 @@ static void resume_clear_context(OSThread *osthread) { osthread->set_ucontext(NULL); osthread->set_siginfo(NULL); - - // notify the suspend action is completed, we have now resumed - osthread->sr.clear_suspended(); } static void suspend_save_context(OSThread *osthread, siginfo_t* siginfo, ucontext_t* context) { @@ -3581,7 +3633,7 @@ // its signal handlers run and prevents sigwait()'s use with the // mutex granting granting signal. // -// Currently only ever called on the VMThread +// Currently only ever called on the VMThread and JavaThreads (PC sampling) // static void SR_handler(int sig, siginfo_t* siginfo, ucontext_t* context) { // Save and restore errno to avoid confusing native code with EINTR @@ -3590,38 +3642,46 @@ Thread* thread = Thread::current(); OSThread* osthread = thread->osthread(); - assert(thread->is_VM_thread(), "Must be VMThread"); - // read current suspend action - int action = osthread->sr.suspend_action(); - if (action == os::Linux::SuspendResume::SR_SUSPEND) { + assert(thread->is_VM_thread() || thread->is_Java_thread(), "Must be VMThread or JavaThread"); + + os::SuspendResume::State current = osthread->sr.state(); + if (current == os::SuspendResume::SR_SUSPEND_REQUEST) { suspend_save_context(osthread, siginfo, context); - // Notify the suspend action is about to be completed. do_suspend() - // waits until SR_SUSPENDED is set and then returns. We will wait - // here for a resume signal and that completes the suspend-other - // action. do_suspend/do_resume is always called as a pair from - // the same thread - so there are no races - - // notify the caller - osthread->sr.set_suspended(); - - sigset_t suspend_set; // signals for sigsuspend() - - // get current set of blocked signals and unblock resume signal - pthread_sigmask(SIG_BLOCK, NULL, &suspend_set); - sigdelset(&suspend_set, SR_signum); - - // wait here until we are resumed - do { - sigsuspend(&suspend_set); - // ignore all returns until we get a resume signal - } while (osthread->sr.suspend_action() != os::Linux::SuspendResume::SR_CONTINUE); + // attempt to switch the state, we assume we had a SUSPEND_REQUEST + os::SuspendResume::State state = osthread->sr.suspended(); + if (state == os::SuspendResume::SR_SUSPENDED) { + sigset_t suspend_set; // signals for sigsuspend() + + // get current set of blocked signals and unblock resume signal + pthread_sigmask(SIG_BLOCK, NULL, &suspend_set); + sigdelset(&suspend_set, SR_signum); + + sr_semaphore.signal(); + // wait here until we are resumed + while (1) { + sigsuspend(&suspend_set); + + os::SuspendResume::State result = osthread->sr.running(); + if (result == os::SuspendResume::SR_RUNNING) { + sr_semaphore.signal(); + break; + } + } + + } else if (state == os::SuspendResume::SR_RUNNING) { + // request was cancelled, continue + } else { + ShouldNotReachHere(); + } resume_clear_context(osthread); - + } else if (current == os::SuspendResume::SR_RUNNING) { + // request was cancelled, continue + } else if (current == os::SuspendResume::SR_WAKEUP_REQUEST) { + // ignore } else { - assert(action == os::Linux::SuspendResume::SR_CONTINUE, "unexpected sr action"); - // nothing special to do - just leave the handler + // ignore } errno = old_errno; @@ -3665,42 +3725,82 @@ return 0; } +static int sr_notify(OSThread* osthread) { + int status = pthread_kill(osthread->pthread_id(), SR_signum); + assert_status(status == 0, status, "pthread_kill"); + return status; +} + +// "Randomly" selected value for how long we want to spin +// before bailing out on suspending a thread, also how often +// we send a signal to a thread we want to resume +static const int RANDOMLY_LARGE_INTEGER = 1000000; +static const int RANDOMLY_LARGE_INTEGER2 = 100; // returns true on success and false on error - really an error is fatal // but this seems the normal response to library errors static bool do_suspend(OSThread* osthread) { + assert(osthread->sr.is_running(), "thread should be running"); + assert(!sr_semaphore.trywait(), "semaphore has invalid state"); + // mark as suspended and send signal - osthread->sr.set_suspend_action(os::Linux::SuspendResume::SR_SUSPEND); - int status = pthread_kill(osthread->pthread_id(), SR_signum); - assert_status(status == 0, status, "pthread_kill"); - - // check status and wait until notified of suspension - if (status == 0) { - for (int i = 0; !osthread->sr.is_suspended(); i++) { - os::yield_all(i); + if (osthread->sr.request_suspend() != os::SuspendResume::SR_SUSPEND_REQUEST) { + // failed to switch, state wasn't running? + ShouldNotReachHere(); + return false; + } + + if (sr_notify(osthread) != 0) { + ShouldNotReachHere(); + } + + // managed to send the signal and switch to SUSPEND_REQUEST, now wait for SUSPENDED + while (true) { + if (sr_semaphore.timedwait(0, 2 * NANOSECS_PER_MILLISEC)) { + break; + } else { + // timeout + os::SuspendResume::State cancelled = osthread->sr.cancel_suspend(); + if (cancelled == os::SuspendResume::SR_RUNNING) { + return false; + } else if (cancelled == os::SuspendResume::SR_SUSPENDED) { + // make sure that we consume the signal on the semaphore as well + sr_semaphore.wait(); + break; + } else { + ShouldNotReachHere(); + return false; + } } - osthread->sr.set_suspend_action(os::Linux::SuspendResume::SR_NONE); - return true; - } - else { - osthread->sr.set_suspend_action(os::Linux::SuspendResume::SR_NONE); - return false; - } + } + + guarantee(osthread->sr.is_suspended(), "Must be suspended"); + return true; } static void do_resume(OSThread* osthread) { assert(osthread->sr.is_suspended(), "thread should be suspended"); - osthread->sr.set_suspend_action(os::Linux::SuspendResume::SR_CONTINUE); - - int status = pthread_kill(osthread->pthread_id(), SR_signum); - assert_status(status == 0, status, "pthread_kill"); - // check status and wait unit notified of resumption - if (status == 0) { - for (int i = 0; osthread->sr.is_suspended(); i++) { - os::yield_all(i); + assert(!sr_semaphore.trywait(), "invalid semaphore state"); + + if (osthread->sr.request_wakeup() != os::SuspendResume::SR_WAKEUP_REQUEST) { + // failed to switch to WAKEUP_REQUEST + ShouldNotReachHere(); + return; + } + + while (true) { + if (sr_notify(osthread) == 0) { + if (sr_semaphore.timedwait(0, 2 * NANOSECS_PER_MILLISEC)) { + if (osthread->sr.is_running()) { + return; + } + } + } else { + ShouldNotReachHere(); } } - osthread->sr.set_suspend_action(os::Linux::SuspendResume::SR_NONE); + + guarantee(osthread->sr.is_running(), "Must be running!"); } //////////////////////////////////////////////////////////////////////////////// @@ -4472,6 +4572,40 @@ /// +void os::SuspendedThreadTask::internal_do_task() { + if (do_suspend(_thread->osthread())) { + SuspendedThreadTaskContext context(_thread, _thread->osthread()->ucontext()); + do_task(context); + do_resume(_thread->osthread()); + } +} + +class PcFetcher : public os::SuspendedThreadTask { +public: + PcFetcher(Thread* thread) : os::SuspendedThreadTask(thread) {} + ExtendedPC result(); +protected: + void do_task(const os::SuspendedThreadTaskContext& context); +private: + ExtendedPC _epc; +}; + +ExtendedPC PcFetcher::result() { + guarantee(is_done(), "task is not done yet."); + return _epc; +} + +void PcFetcher::do_task(const os::SuspendedThreadTaskContext& context) { + Thread* thread = context.thread(); + OSThread* osthread = thread->osthread(); + if (osthread->ucontext() != NULL) { + _epc = os::Linux::ucontext_get_pc((ucontext_t *) context.ucontext()); + } else { + // NULL context is unexpected, double-check this is the VMThread + guarantee(thread->is_VM_thread(), "can only be called for VMThread"); + } +} + // Suspends the target using the signal mechanism and then grabs the PC before // resuming the target. Used by the flat-profiler only ExtendedPC os::get_thread_pc(Thread* thread) { @@ -4479,22 +4613,9 @@ assert(Thread::current()->is_Watcher_thread(), "Must be watcher"); assert(thread->is_VM_thread(), "Can only be called for VMThread"); - ExtendedPC epc; - - OSThread* osthread = thread->osthread(); - if (do_suspend(osthread)) { - if (osthread->ucontext() != NULL) { - epc = os::Linux::ucontext_get_pc(osthread->ucontext()); - } else { - // NULL context is unexpected, double-check this is the VMThread - guarantee(thread->is_VM_thread(), "can only be called for VMThread"); - } - do_resume(osthread); - } - // failure means pthread_kill failed for some reason - arguably this is - // a fatal problem, but such problems are ignored elsewhere - - return epc; + PcFetcher fetcher(thread); + fetcher.run(); + return fetcher.result(); } int os::Linux::safe_cond_timedwait(pthread_cond_t *_cond, pthread_mutex_t *_mutex, const struct timespec *_abstime) @@ -5616,4 +5737,5 @@ new MemNotifyThread(fd); } } + #endif // JAVASE_EMBEDDED diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/os/linux/vm/os_linux.hpp --- a/hotspot/src/os/linux/vm/os_linux.hpp Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/src/os/linux/vm/os_linux.hpp Wed Jul 05 18:59:39 2017 +0200 @@ -210,35 +210,6 @@ // LinuxThreads work-around for 6292965 static int safe_cond_timedwait(pthread_cond_t *_cond, pthread_mutex_t *_mutex, const struct timespec *_abstime); - - // Linux suspend/resume support - this helper is a shadow of its former - // self now that low-level suspension is barely used, and old workarounds - // for LinuxThreads are no longer needed. - class SuspendResume { - private: - volatile int _suspend_action; - volatile jint _state; - public: - // values for suspend_action: - enum { - SR_NONE = 0x00, - SR_SUSPEND = 0x01, // suspend request - SR_CONTINUE = 0x02, // resume request - SR_SUSPENDED = 0x20 // values for _state: + SR_NONE - }; - - SuspendResume() { _suspend_action = SR_NONE; _state = SR_NONE; } - - int suspend_action() const { return _suspend_action; } - void set_suspend_action(int x) { _suspend_action = x; } - - // atomic updates for _state - inline void set_suspended(); - inline void clear_suspended(); - bool is_suspended() { return _state & SR_SUSPENDED; } - - }; - private: typedef int (*sched_getcpu_func_t)(void); typedef int (*numa_node_to_cpus_func_t)(int node, unsigned long *buffer, int bufferlen); @@ -333,6 +304,6 @@ status = pthread_mutex_init (_mutex, NULL); assert_status(status == 0, status, "mutex_init"); } -} ; +}; #endif // OS_LINUX_VM_OS_LINUX_HPP diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/os/linux/vm/os_linux.inline.hpp --- a/hotspot/src/os/linux/vm/os_linux.inline.hpp Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/src/os/linux/vm/os_linux.inline.hpp Wed Jul 05 18:59:39 2017 +0200 @@ -288,20 +288,4 @@ return ::setsockopt(fd, level, optname, optval, optlen); } -inline void os::Linux::SuspendResume::set_suspended() { - jint temp, temp2; - do { - temp = _state; - temp2 = Atomic::cmpxchg(temp | SR_SUSPENDED, &_state, temp); - } while (temp2 != temp); -} - -inline void os::Linux::SuspendResume::clear_suspended() { - jint temp, temp2; - do { - temp = _state; - temp2 = Atomic::cmpxchg(temp & ~SR_SUSPENDED, &_state, temp); - } while (temp2 != temp); -} - #endif // OS_LINUX_VM_OS_LINUX_INLINE_HPP diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/os/solaris/vm/osThread_solaris.cpp --- a/hotspot/src/os/solaris/vm/osThread_solaris.cpp Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/src/os/solaris/vm/osThread_solaris.cpp Wed Jul 05 18:59:39 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 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 @@ -41,10 +41,6 @@ _thread_id = 0; sigemptyset(&_caller_sigmask); - _current_callback = NULL; - _current_callback_lock = VM_Version::supports_compare_and_exchange() ? NULL - : new Mutex(Mutex::suspend_resume, "Callback_lock", true); - _saved_interrupt_thread_state = _thread_new; _vm_created_thread = false; } @@ -52,172 +48,6 @@ void OSThread::pd_destroy() { } -// Synchronous interrupt support -// -// _current_callback == NULL no pending callback -// == 1 callback_in_progress -// == other value pointer to the pending callback -// - -// CAS on v8 is implemented by using a global atomic_memory_operation_lock, -// which is shared by other atomic functions. It is OK for normal uses, but -// dangerous if used after some thread is suspended or if used in signal -// handlers. Instead here we use a special per-thread lock to synchronize -// updating _current_callback if we are running on v8. Note in general trying -// to grab locks after a thread is suspended is not safe, but it is safe for -// updating _current_callback, because synchronous interrupt callbacks are -// currently only used in: -// 1. GetThreadPC_Callback - used by WatcherThread to profile VM thread -// There is no overlap between the callbacks, which means we won't try to -// grab a thread's sync lock after the thread has been suspended while holding -// the same lock. - -// used after a thread is suspended -static intptr_t compare_and_exchange_current_callback ( - intptr_t callback, intptr_t *addr, intptr_t compare_value, Mutex *sync) { - if (VM_Version::supports_compare_and_exchange()) { - return Atomic::cmpxchg_ptr(callback, addr, compare_value); - } else { - MutexLockerEx ml(sync, Mutex::_no_safepoint_check_flag); - if (*addr == compare_value) { - *addr = callback; - return compare_value; - } else { - return callback; - } - } -} - -// used in signal handler -static intptr_t exchange_current_callback(intptr_t callback, intptr_t *addr, Mutex *sync) { - if (VM_Version::supports_compare_and_exchange()) { - return Atomic::xchg_ptr(callback, addr); - } else { - MutexLockerEx ml(sync, Mutex::_no_safepoint_check_flag); - intptr_t cb = *addr; - *addr = callback; - return cb; - } -} - -// one interrupt at a time. spin if _current_callback != NULL -int OSThread::set_interrupt_callback(Sync_Interrupt_Callback * cb) { - int count = 0; - while (compare_and_exchange_current_callback( - (intptr_t)cb, (intptr_t *)&_current_callback, (intptr_t)NULL, _current_callback_lock) != NULL) { - while (_current_callback != NULL) { - count++; -#ifdef ASSERT - if ((WarnOnStalledSpinLock > 0) && - (count % WarnOnStalledSpinLock == 0)) { - warning("_current_callback seems to be stalled: %p", _current_callback); - } -#endif - os::yield_all(count); - } - } - return 0; -} - -// reset _current_callback, spin if _current_callback is callback_in_progress -void OSThread::remove_interrupt_callback(Sync_Interrupt_Callback * cb) { - int count = 0; - while (compare_and_exchange_current_callback( - (intptr_t)NULL, (intptr_t *)&_current_callback, (intptr_t)cb, _current_callback_lock) != (intptr_t)cb) { -#ifdef ASSERT - intptr_t p = (intptr_t)_current_callback; - assert(p == (intptr_t)callback_in_progress || - p == (intptr_t)cb, "wrong _current_callback value"); -#endif - while (_current_callback != cb) { - count++; -#ifdef ASSERT - if ((WarnOnStalledSpinLock > 0) && - (count % WarnOnStalledSpinLock == 0)) { - warning("_current_callback seems to be stalled: %p", _current_callback); - } -#endif - os::yield_all(count); - } - } -} - -void OSThread::do_interrupt_callbacks_at_interrupt(InterruptArguments *args) { - Sync_Interrupt_Callback * cb; - cb = (Sync_Interrupt_Callback *)exchange_current_callback( - (intptr_t)callback_in_progress, (intptr_t *)&_current_callback, _current_callback_lock); - - if (cb == NULL) { - // signal is delivered too late (thread is masking interrupt signal??). - // there is nothing we need to do because requesting thread has given up. - } else if ((intptr_t)cb == (intptr_t)callback_in_progress) { - fatal("invalid _current_callback state"); - } else { - assert(cb->target()->osthread() == this, "wrong target"); - cb->execute(args); - cb->leave_callback(); // notify the requester - } - - // restore original _current_callback value - intptr_t p; - p = exchange_current_callback((intptr_t)cb, (intptr_t *)&_current_callback, _current_callback_lock); - assert(p == (intptr_t)callback_in_progress, "just checking"); -} - -// Called by the requesting thread to send a signal to target thread and -// execute "this" callback from the signal handler. -int OSThread::Sync_Interrupt_Callback::interrupt(Thread * target, int timeout) { - // Let signals to the vm_thread go even if the Threads_lock is not acquired - assert(Threads_lock->owned_by_self() || (target == VMThread::vm_thread()), - "must have threads lock to call this"); - - OSThread * osthread = target->osthread(); - - // may block if target thread already has a pending callback - osthread->set_interrupt_callback(this); - - _target = target; - - int rslt = thr_kill(osthread->thread_id(), os::Solaris::SIGasync()); - assert(rslt == 0, "thr_kill != 0"); - - bool status = false; - jlong t1 = os::javaTimeMillis(); - { // don't use safepoint check because we might be the watcher thread. - MutexLockerEx ml(_sync, Mutex::_no_safepoint_check_flag); - while (!is_done()) { - status = _sync->wait(Mutex::_no_safepoint_check_flag, timeout); - - // status == true if timed out - if (status) break; - - // update timeout - jlong t2 = os::javaTimeMillis(); - timeout -= t2 - t1; - t1 = t2; - } - } - - // reset current_callback - osthread->remove_interrupt_callback(this); - - return status; -} - -void OSThread::Sync_Interrupt_Callback::leave_callback() { - if (!_sync->owned_by_self()) { - // notify requesting thread - MutexLockerEx ml(_sync, Mutex::_no_safepoint_check_flag); - _is_done = true; - _sync->notify_all(); - } else { - // Current thread is interrupted while it is holding the _sync lock, trying - // to grab it again will deadlock. The requester will timeout anyway, - // so just return. - _is_done = true; - } -} - // copied from synchronizer.cpp void OSThread::handle_spinlock_contention(int tries) { @@ -229,3 +59,7 @@ os::yield(); // Yield to threads of same or higher priority } } + +void OSThread::SR_handler(Thread* thread, ucontext_t* uc) { + os::Solaris::SR_handler(thread, uc); +} diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/os/solaris/vm/osThread_solaris.hpp --- a/hotspot/src/os/solaris/vm/osThread_solaris.hpp Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/src/os/solaris/vm/osThread_solaris.hpp Wed Jul 05 18:59:39 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -72,61 +72,15 @@ // *************************************************************** public: - - class InterruptArguments : StackObj { - private: - Thread* _thread; // the thread to signal was dispatched to - ucontext_t* _ucontext; // the machine context at the time of the signal - - public: - InterruptArguments(Thread* thread, ucontext_t* ucontext) { - _thread = thread; - _ucontext = ucontext; - } - - Thread* thread() const { return _thread; } - ucontext_t* ucontext() const { return _ucontext; } - }; - - // There are currently no asynchronous callbacks - and we'd better not - // support them in the future either, as they need to be deallocated from - // the interrupt handler, which is not safe; they also require locks to - // protect the callback queue. - - class Sync_Interrupt_Callback : private StackObj { - protected: - volatile bool _is_done; - Monitor* _sync; - Thread* _target; - public: - Sync_Interrupt_Callback(Monitor * sync) { - _is_done = false; _target = NULL; _sync = sync; - } - - bool is_done() const { return _is_done; } - Thread* target() const { return _target; } - - int interrupt(Thread * target, int timeout); - - // override to implement the callback. - virtual void execute(InterruptArguments *args) = 0; - - void leave_callback(); - }; + os::SuspendResume sr; private: - - Sync_Interrupt_Callback * volatile _current_callback; - enum { - callback_in_progress = 1 - }; - Mutex * _current_callback_lock; // only used on v8 + ucontext_t* _ucontext; public: - - int set_interrupt_callback (Sync_Interrupt_Callback * cb); - void remove_interrupt_callback(Sync_Interrupt_Callback * cb); - void do_interrupt_callbacks_at_interrupt(InterruptArguments *args); + ucontext_t* ucontext() const { return _ucontext; } + void set_ucontext(ucontext_t* ptr) { _ucontext = ptr; } + static void SR_handler(Thread* thread, ucontext_t* uc); // *************************************************************** // java.lang.Thread.interrupt state. diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/os/solaris/vm/os_share_solaris.hpp --- a/hotspot/src/os/solaris/vm/os_share_solaris.hpp Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/src/os/solaris/vm/os_share_solaris.hpp Wed Jul 05 18:59:39 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2010, 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,28 +27,6 @@ // Defines the interfaces to Solaris operating systems that vary across platforms - -// This is a simple callback that just fetches a PC for an interrupted thread. -// The thread need not be suspended and the fetched PC is just a hint. -// Returned PC and nPC are not necessarily consecutive. -// This one is currently used for profiling the VMThread ONLY! - -// Must be synchronous -class GetThreadPC_Callback : public OSThread::Sync_Interrupt_Callback { - private: - ExtendedPC _addr; - - public: - - GetThreadPC_Callback(Monitor *sync) : - OSThread::Sync_Interrupt_Callback(sync) { } - ExtendedPC addr() const { return _addr; } - - void set_addr(ExtendedPC addr) { _addr = addr; } - - void execute(OSThread::InterruptArguments *args); -}; - // misc extern "C" { void signalHandler(int, siginfo_t*, void*); diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/os/solaris/vm/os_solaris.cpp --- a/hotspot/src/os/solaris/vm/os_solaris.cpp Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/src/os/solaris/vm/os_solaris.cpp Wed Jul 05 18:59:39 2017 +0200 @@ -240,6 +240,8 @@ static int pthread_cond_default_init(cond_t *cv, int scope, void *arg){ memset(cv, 0, sizeof(cond_t)); return 0; } } +static void unpackTime(timespec* absTime, bool isAbsolute, jlong time); + // Thread Local Storage // This is common to all Solaris platforms so it is defined here, // in this common file. @@ -2580,6 +2582,57 @@ return CAST_FROM_FN_PTR(void*, UserHandler); } +class Semaphore : public StackObj { + public: + Semaphore(); + ~Semaphore(); + void signal(); + void wait(); + bool trywait(); + bool timedwait(unsigned int sec, int nsec); + private: + sema_t _semaphore; +}; + + +Semaphore::Semaphore() { + sema_init(&_semaphore, 0, NULL, NULL); +} + +Semaphore::~Semaphore() { + sema_destroy(&_semaphore); +} + +void Semaphore::signal() { + sema_post(&_semaphore); +} + +void Semaphore::wait() { + sema_wait(&_semaphore); +} + +bool Semaphore::trywait() { + return sema_trywait(&_semaphore) == 0; +} + +bool Semaphore::timedwait(unsigned int sec, int nsec) { + struct timespec ts; + unpackTime(&ts, false, (sec * NANOSECS_PER_SEC) + nsec); + + while (1) { + int result = sema_timedwait(&_semaphore, &ts); + if (result == 0) { + return true; + } else if (errno == EINTR) { + continue; + } else if (errno == ETIME) { + return false; + } else { + return false; + } + } +} + extern "C" { typedef void (*sa_handler_t)(int); typedef void (*sa_sigaction_t)(int, siginfo_t *, void *); @@ -4164,6 +4217,68 @@ schedctl_start(schedctl_init()); } +static void resume_clear_context(OSThread *osthread) { + osthread->set_ucontext(NULL); +} + +static void suspend_save_context(OSThread *osthread, ucontext_t* context) { + osthread->set_ucontext(context); +} + +static Semaphore sr_semaphore; + +void os::Solaris::SR_handler(Thread* thread, ucontext_t* uc) { + // Save and restore errno to avoid confusing native code with EINTR + // after sigsuspend. + int old_errno = errno; + + OSThread* osthread = thread->osthread(); + assert(thread->is_VM_thread() || thread->is_Java_thread(), "Must be VMThread or JavaThread"); + + os::SuspendResume::State current = osthread->sr.state(); + if (current == os::SuspendResume::SR_SUSPEND_REQUEST) { + suspend_save_context(osthread, uc); + + // attempt to switch the state, we assume we had a SUSPEND_REQUEST + os::SuspendResume::State state = osthread->sr.suspended(); + if (state == os::SuspendResume::SR_SUSPENDED) { + sigset_t suspend_set; // signals for sigsuspend() + + // get current set of blocked signals and unblock resume signal + thr_sigsetmask(SIG_BLOCK, NULL, &suspend_set); + sigdelset(&suspend_set, os::Solaris::SIGasync()); + + sr_semaphore.signal(); + // wait here until we are resumed + while (1) { + sigsuspend(&suspend_set); + + os::SuspendResume::State result = osthread->sr.running(); + if (result == os::SuspendResume::SR_RUNNING) { + sr_semaphore.signal(); + break; + } + } + + } else if (state == os::SuspendResume::SR_RUNNING) { + // request was cancelled, continue + } else { + ShouldNotReachHere(); + } + + resume_clear_context(osthread); + } else if (current == os::SuspendResume::SR_RUNNING) { + // request was cancelled, continue + } else if (current == os::SuspendResume::SR_WAKEUP_REQUEST) { + // ignore + } else { + // ignore + } + + errno = old_errno; +} + + void os::interrupt(Thread* thread) { assert(Thread::current() == thread || Threads_lock->owned_by_self(), "possibility of dangling Thread pointer"); @@ -4247,6 +4362,116 @@ return buf[0] == 'y' || buf[0] == 'Y'; } +static int sr_notify(OSThread* osthread) { + int status = thr_kill(osthread->thread_id(), os::Solaris::SIGasync()); + assert_status(status == 0, status, "thr_kill"); + return status; +} + +// "Randomly" selected value for how long we want to spin +// before bailing out on suspending a thread, also how often +// we send a signal to a thread we want to resume +static const int RANDOMLY_LARGE_INTEGER = 1000000; +static const int RANDOMLY_LARGE_INTEGER2 = 100; + +static bool do_suspend(OSThread* osthread) { + assert(osthread->sr.is_running(), "thread should be running"); + assert(!sr_semaphore.trywait(), "semaphore has invalid state"); + + // mark as suspended and send signal + if (osthread->sr.request_suspend() != os::SuspendResume::SR_SUSPEND_REQUEST) { + // failed to switch, state wasn't running? + ShouldNotReachHere(); + return false; + } + + if (sr_notify(osthread) != 0) { + ShouldNotReachHere(); + } + + // managed to send the signal and switch to SUSPEND_REQUEST, now wait for SUSPENDED + while (true) { + if (sr_semaphore.timedwait(0, 2000 * NANOSECS_PER_MILLISEC)) { + break; + } else { + // timeout + os::SuspendResume::State cancelled = osthread->sr.cancel_suspend(); + if (cancelled == os::SuspendResume::SR_RUNNING) { + return false; + } else if (cancelled == os::SuspendResume::SR_SUSPENDED) { + // make sure that we consume the signal on the semaphore as well + sr_semaphore.wait(); + break; + } else { + ShouldNotReachHere(); + return false; + } + } + } + + guarantee(osthread->sr.is_suspended(), "Must be suspended"); + return true; +} + +static void do_resume(OSThread* osthread) { + assert(osthread->sr.is_suspended(), "thread should be suspended"); + assert(!sr_semaphore.trywait(), "invalid semaphore state"); + + if (osthread->sr.request_wakeup() != os::SuspendResume::SR_WAKEUP_REQUEST) { + // failed to switch to WAKEUP_REQUEST + ShouldNotReachHere(); + return; + } + + while (true) { + if (sr_notify(osthread) == 0) { + if (sr_semaphore.timedwait(0, 2 * NANOSECS_PER_MILLISEC)) { + if (osthread->sr.is_running()) { + return; + } + } + } else { + ShouldNotReachHere(); + } + } + + guarantee(osthread->sr.is_running(), "Must be running!"); +} + +void os::SuspendedThreadTask::internal_do_task() { + if (do_suspend(_thread->osthread())) { + SuspendedThreadTaskContext context(_thread, _thread->osthread()->ucontext()); + do_task(context); + do_resume(_thread->osthread()); + } +} + +class PcFetcher : public os::SuspendedThreadTask { +public: + PcFetcher(Thread* thread) : os::SuspendedThreadTask(thread) {} + ExtendedPC result(); +protected: + void do_task(const os::SuspendedThreadTaskContext& context); +private: + ExtendedPC _epc; +}; + +ExtendedPC PcFetcher::result() { + guarantee(is_done(), "task is not done yet."); + return _epc; +} + +void PcFetcher::do_task(const os::SuspendedThreadTaskContext& context) { + Thread* thread = context.thread(); + OSThread* osthread = thread->osthread(); + if (osthread->ucontext() != NULL) { + _epc = os::Solaris::ucontext_get_pc((ucontext_t *) context.ucontext()); + } else { + // NULL context is unexpected, double-check this is the VMThread + guarantee(thread->is_VM_thread(), "can only be called for VMThread"); + } +} + // A lightweight implementation that does not suspend the target thread and // thus returns only a hint. Used for profiling only! ExtendedPC os::get_thread_pc(Thread* thread) { @@ -4254,21 +4479,9 @@ assert(Thread::current()->is_Watcher_thread(), "Must be watcher and own Threads_lock"); // For now, is only used to profile the VM Thread assert(thread->is_VM_thread(), "Can only be called for VMThread"); - ExtendedPC epc; - - GetThreadPC_Callback cb(ProfileVM_lock); - OSThread *osthread = thread->osthread(); - const int time_to_wait = 400; // 400ms wait for initial response - int status = cb.interrupt(thread, time_to_wait); - - if (cb.is_done() ) { - epc = cb.addr(); - } else { - DEBUG_ONLY(tty->print_cr("Failed to get pc for thread: %d got %d status", - osthread->thread_id(), status);); - // epc is already NULL - } - return epc; + PcFetcher fetcher(thread); + fetcher.run(); + return fetcher.result(); } diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/os/solaris/vm/os_solaris.hpp --- a/hotspot/src/os/solaris/vm/os_solaris.hpp Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/src/os/solaris/vm/os_solaris.hpp Wed Jul 05 18:59:39 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -127,7 +127,6 @@ static void set_SIGinterrupt(int newsig) { _SIGinterrupt = newsig; } static void set_SIGasync(int newsig) { _SIGasync = newsig; } - public: // Large Page Support--ISM. static bool largepage_range(char* addr, size_t size); @@ -145,6 +144,7 @@ static intptr_t* ucontext_get_sp(ucontext_t* uc); // ucontext_get_fp() is only used by Solaris X86 (see note below) static intptr_t* ucontext_get_fp(ucontext_t* uc); + static address ucontext_get_pc(ucontext_t* uc); // For Analyzer Forte AsyncGetCallTrace profiling support: // Parameter ret_fp is only used by Solaris X86. @@ -157,6 +157,8 @@ static void hotspot_sigmask(Thread* thread); + // SR_handler + static void SR_handler(Thread* thread, ucontext_t* uc); protected: // Solaris-specific interface goes here static julong available_memory(); diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/os/windows/vm/os_windows.cpp --- a/hotspot/src/os/windows/vm/os_windows.cpp Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/src/os/windows/vm/os_windows.cpp Wed Jul 05 18:59:39 2017 +0200 @@ -5048,6 +5048,71 @@ return ::setsockopt(fd, level, optname, optval, optlen); } +// WINDOWS CONTEXT Flags for THREAD_SAMPLING +#if defined(IA32) +# define sampling_context_flags (CONTEXT_FULL | CONTEXT_FLOATING_POINT | CONTEXT_EXTENDED_REGISTERS) +#elif defined (AMD64) +# define sampling_context_flags (CONTEXT_FULL | CONTEXT_FLOATING_POINT) +#endif + +// returns true if thread could be suspended, +// false otherwise +static bool do_suspend(HANDLE* h) { + if (h != NULL) { + if (SuspendThread(*h) != ~0) { + return true; + } + } + return false; +} + +// resume the thread +// calling resume on an active thread is a no-op +static void do_resume(HANDLE* h) { + if (h != NULL) { + ResumeThread(*h); + } +} + +// retrieve a suspend/resume context capable handle +// from the tid. Caller validates handle return value. +void get_thread_handle_for_extended_context(HANDLE* h, OSThread::thread_id_t tid) { + if (h != NULL) { + *h = OpenThread(THREAD_SUSPEND_RESUME | THREAD_GET_CONTEXT | THREAD_QUERY_INFORMATION, FALSE, tid); + } +} + +// +// Thread sampling implementation +// +void os::SuspendedThreadTask::internal_do_task() { + CONTEXT ctxt; + HANDLE h = NULL; + + // get context capable handle for thread + get_thread_handle_for_extended_context(&h, _thread->osthread()->thread_id()); + + // sanity + if (h == NULL || h == INVALID_HANDLE_VALUE) { + return; + } + + // suspend the thread + if (do_suspend(&h)) { + ctxt.ContextFlags = sampling_context_flags; + // get thread context + GetThreadContext(h, &ctxt); + SuspendedThreadTaskContext context(_thread, &ctxt); + // pass context to Thread Sampling impl + do_task(context); + // resume thread + do_resume(&h); + } + + // close handle + CloseHandle(h); +} + // Kernel32 API typedef SIZE_T (WINAPI* GetLargePageMinimum_Fn)(void); diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/os_cpu/bsd_x86/vm/thread_bsd_x86.cpp --- a/hotspot/src/os_cpu/bsd_x86/vm/thread_bsd_x86.cpp Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/src/os_cpu/bsd_x86/vm/thread_bsd_x86.cpp Wed Jul 05 18:59:39 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2010, 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 @@ -30,10 +30,16 @@ // currently interrupted by SIGPROF bool JavaThread::pd_get_top_frame_for_signal_handler(frame* fr_addr, void* ucontext, bool isInJava) { + assert(Thread::current() == this, "caller must be current thread"); + return pd_get_top_frame(fr_addr, ucontext, isInJava); +} - assert(Thread::current() == this, "caller must be current thread"); +bool JavaThread::pd_get_top_frame_for_profiling(frame* fr_addr, void* ucontext, bool isInJava) { + return pd_get_top_frame(fr_addr, ucontext, isInJava); +} + +bool JavaThread::pd_get_top_frame(frame* fr_addr, void* ucontext, bool isInJava) { assert(this->is_Java_thread(), "must be JavaThread"); - JavaThread* jt = (JavaThread *)this; // If we have a last_Java_frame, then we should use it even if diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/os_cpu/bsd_x86/vm/thread_bsd_x86.hpp --- a/hotspot/src/os_cpu/bsd_x86/vm/thread_bsd_x86.hpp Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/src/os_cpu/bsd_x86/vm/thread_bsd_x86.hpp Wed Jul 05 18:59:39 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 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 @@ -61,6 +61,13 @@ bool pd_get_top_frame_for_signal_handler(frame* fr_addr, void* ucontext, bool isInJava); + bool pd_get_top_frame_for_profiling(frame* fr_addr, void* ucontext, + bool isInJava); + +private: + bool pd_get_top_frame(frame* fr_addr, void* ucontext, bool isInJava); +public: + // These routines are only used on cpu architectures that // have separate register stacks (Itanium). static bool register_stack_overflow() { return false; } diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/os_cpu/linux_x86/vm/thread_linux_x86.cpp --- a/hotspot/src/os_cpu/linux_x86/vm/thread_linux_x86.cpp Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/src/os_cpu/linux_x86/vm/thread_linux_x86.cpp Wed Jul 05 18:59:39 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2010, 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 @@ -32,8 +32,15 @@ void* ucontext, bool isInJava) { assert(Thread::current() == this, "caller must be current thread"); + return pd_get_top_frame(fr_addr, ucontext, isInJava); +} + +bool JavaThread::pd_get_top_frame_for_profiling(frame* fr_addr, void* ucontext, bool isInJava) { + return pd_get_top_frame(fr_addr, ucontext, isInJava); +} + +bool JavaThread::pd_get_top_frame(frame* fr_addr, void* ucontext, bool isInJava) { assert(this->is_Java_thread(), "must be JavaThread"); - JavaThread* jt = (JavaThread *)this; // If we have a last_Java_frame, then we should use it even if diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/os_cpu/linux_x86/vm/thread_linux_x86.hpp --- a/hotspot/src/os_cpu/linux_x86/vm/thread_linux_x86.hpp Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/src/os_cpu/linux_x86/vm/thread_linux_x86.hpp Wed Jul 05 18:59:39 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 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 @@ -61,6 +61,11 @@ bool pd_get_top_frame_for_signal_handler(frame* fr_addr, void* ucontext, bool isInJava); + bool pd_get_top_frame_for_profiling(frame* fr_addr, void* ucontext, bool isInJava); +private: + bool pd_get_top_frame(frame* fr_addr, void* ucontext, bool isInJava); +public: + // These routines are only used on cpu architectures that // have separate register stacks (Itanium). static bool register_stack_overflow() { return false; } diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/os_cpu/solaris_sparc/vm/os_solaris_sparc.cpp --- a/hotspot/src/os_cpu/solaris_sparc/vm/os_solaris_sparc.cpp Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/src/os_cpu/solaris_sparc/vm/os_solaris_sparc.cpp Wed Jul 05 18:59:39 2017 +0200 @@ -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 @@ -194,6 +194,11 @@ return NULL; } +address os::Solaris::ucontext_get_pc(ucontext_t *uc) { + return (address) uc->uc_mcontext.gregs[REG_PC]; +} + + // For Forte Analyzer AsyncGetCallTrace profiling support - thread // is currently interrupted by SIGPROF. // @@ -265,22 +270,6 @@ } } - -void GetThreadPC_Callback::execute(OSThread::InterruptArguments *args) { - Thread* thread = args->thread(); - ucontext_t* uc = args->ucontext(); - intptr_t* sp; - - assert(ProfileVM && thread->is_VM_thread(), "just checking"); - - // Skip the mcontext corruption verification. If if occasionally - // things get corrupt, it is ok for profiling - we will just get an unresolved - // function name - ExtendedPC new_addr((address)uc->uc_mcontext.gregs[REG_PC]); - _addr = new_addr; -} - - static int threadgetstate(thread_t tid, int *flags, lwpid_t *lwp, stack_t *ss, gregset_t rs, lwpstatus_t *lwpstatus) { char lwpstatusfile[PROCFILE_LENGTH]; int lwpfd, err; @@ -358,13 +347,8 @@ guarantee(sig != os::Solaris::SIGinterrupt(), "Can not chain VM interrupt signal, try -XX:+UseAltSigs"); if (sig == os::Solaris::SIGasync()) { - if (thread) { - OSThread::InterruptArguments args(thread, uc); - thread->osthread()->do_interrupt_callbacks_at_interrupt(&args); - return true; - } else if (vmthread) { - OSThread::InterruptArguments args(vmthread, uc); - vmthread->osthread()->do_interrupt_callbacks_at_interrupt(&args); + if (thread || vmthread) { + OSThread::SR_handler(t, uc); return true; } else if (os::Solaris::chained_handler(sig, info, ucVoid)) { return true; diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/os_cpu/solaris_sparc/vm/thread_solaris_sparc.cpp --- a/hotspot/src/os_cpu/solaris_sparc/vm/thread_solaris_sparc.cpp Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/src/os_cpu/solaris_sparc/vm/thread_solaris_sparc.cpp Wed Jul 05 18:59:39 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2010, 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 @@ -36,11 +36,21 @@ void* ucontext, bool isInJava) { assert(Thread::current() == this, "caller must be current thread"); + return pd_get_top_frame(fr_addr, ucontext, isInJava, true); +} + +bool JavaThread::pd_get_top_frame_for_profiling(frame* fr_addr, void* ucontext, bool isInJava) { + // get ucontext somehow + return pd_get_top_frame(fr_addr, ucontext, isInJava, false); +} + +bool JavaThread::pd_get_top_frame(frame* fr_addr, + void* ucontext, bool isInJava, bool makeWalkable) { assert(this->is_Java_thread(), "must be JavaThread"); JavaThread* jt = (JavaThread *)this; - if (!isInJava) { + if (!isInJava && makeWalkable) { // make_walkable flushes register windows and grabs last_Java_pc // which can not be done if the ucontext sp matches last_Java_sp // stack walking utilities assume last_Java_pc set if marked flushed diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/os_cpu/solaris_sparc/vm/thread_solaris_sparc.hpp --- a/hotspot/src/os_cpu/solaris_sparc/vm/thread_solaris_sparc.hpp Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/src/os_cpu/solaris_sparc/vm/thread_solaris_sparc.hpp Wed Jul 05 18:59:39 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 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 @@ -93,6 +93,11 @@ bool pd_get_top_frame_for_signal_handler(frame* fr_addr, void* ucontext, bool isInJava); + bool pd_get_top_frame_for_profiling(frame* fr_addr, void* ucontext, bool isInJava); +private: + bool pd_get_top_frame(frame* fr_addr, void* ucontext, bool isInJava, bool makeWalkable); +public: + // These routines are only used on cpu architectures that // have separate register stacks (Itanium). static bool register_stack_overflow() { return false; } diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/os_cpu/solaris_x86/vm/os_solaris_x86.cpp --- a/hotspot/src/os_cpu/solaris_x86/vm/os_solaris_x86.cpp Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/src/os_cpu/solaris_x86/vm/os_solaris_x86.cpp Wed Jul 05 18:59:39 2017 +0200 @@ -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 @@ -183,6 +183,10 @@ return (intptr_t*)uc->uc_mcontext.gregs[REG_FP]; } +address os::Solaris::ucontext_get_pc(ucontext_t *uc) { + return (address) uc->uc_mcontext.gregs[REG_PC]; +} + // For Forte Analyzer AsyncGetCallTrace profiling support - thread // is currently interrupted by SIGPROF. // @@ -252,22 +256,6 @@ } } -// This is a simple callback that just fetches a PC for an interrupted thread. -// The thread need not be suspended and the fetched PC is just a hint. -// This one is currently used for profiling the VMThread ONLY! - -// Must be synchronous -void GetThreadPC_Callback::execute(OSThread::InterruptArguments *args) { - Thread* thread = args->thread(); - ucontext_t* uc = args->ucontext(); - intptr_t* sp; - - assert(ProfileVM && thread->is_VM_thread(), "just checking"); - - ExtendedPC new_addr((address)uc->uc_mcontext.gregs[REG_PC]); - _addr = new_addr; -} - static int threadgetstate(thread_t tid, int *flags, lwpid_t *lwp, stack_t *ss, gregset_t rs, lwpstatus_t *lwpstatus) { char lwpstatusfile[PROCFILE_LENGTH]; int lwpfd, err; @@ -419,14 +407,8 @@ guarantee(sig != os::Solaris::SIGinterrupt(), "Can not chain VM interrupt signal, try -XX:+UseAltSigs"); if (sig == os::Solaris::SIGasync()) { - if(thread){ - OSThread::InterruptArguments args(thread, uc); - thread->osthread()->do_interrupt_callbacks_at_interrupt(&args); - return true; - } - else if(vmthread){ - OSThread::InterruptArguments args(vmthread, uc); - vmthread->osthread()->do_interrupt_callbacks_at_interrupt(&args); + if(thread || vmthread){ + OSThread::SR_handler(t, uc); return true; } else if (os::Solaris::chained_handler(sig, info, ucVoid)) { return true; diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/os_cpu/solaris_x86/vm/thread_solaris_x86.cpp --- a/hotspot/src/os_cpu/solaris_x86/vm/thread_solaris_x86.cpp Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/src/os_cpu/solaris_x86/vm/thread_solaris_x86.cpp Wed Jul 05 18:59:39 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2010, 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 @@ -30,8 +30,17 @@ // currently interrupted by SIGPROF bool JavaThread::pd_get_top_frame_for_signal_handler(frame* fr_addr, void* ucontext, bool isInJava) { + assert(Thread::current() == this, "caller must be current thread"); + return pd_get_top_frame(fr_addr, ucontext, isInJava); +} - assert(Thread::current() == this, "caller must be current thread"); +bool JavaThread::pd_get_top_frame_for_profiling(frame* fr_addr, + void* ucontext, bool isInJava) { + return pd_get_top_frame(fr_addr, ucontext, isInJava); +} + +bool JavaThread::pd_get_top_frame(frame* fr_addr, + void* ucontext, bool isInJava) { assert(this->is_Java_thread(), "must be JavaThread"); JavaThread* jt = (JavaThread *)this; diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/os_cpu/solaris_x86/vm/thread_solaris_x86.hpp --- a/hotspot/src/os_cpu/solaris_x86/vm/thread_solaris_x86.hpp Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/src/os_cpu/solaris_x86/vm/thread_solaris_x86.hpp Wed Jul 05 18:59:39 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2010, 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 @@ -54,6 +54,12 @@ bool pd_get_top_frame_for_signal_handler(frame* fr_addr, void* ucontext, bool isInJava); + bool pd_get_top_frame_for_profiling(frame* fr_addr, void* ucontext, + bool isInJava); +private: + bool pd_get_top_frame(frame* fr_addr, void* ucontext, + bool isInJava); +public: // These routines are only used on cpu architectures that // have separate register stacks (Itanium). diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/os_cpu/windows_x86/vm/thread_windows_x86.cpp --- a/hotspot/src/os_cpu/windows_x86/vm/thread_windows_x86.cpp Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/src/os_cpu/windows_x86/vm/thread_windows_x86.cpp Wed Jul 05 18:59:39 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2010, 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 @@ -32,6 +32,15 @@ void* ucontext, bool isInJava) { assert(Thread::current() == this, "caller must be current thread"); + return pd_get_top_frame(fr_addr, ucontext, isInJava); +} + +bool JavaThread::pd_get_top_frame_for_profiling(frame* fr_addr, void* ucontext, bool isInJava) { + return pd_get_top_frame(fr_addr, ucontext, isInJava); +} + +bool JavaThread::pd_get_top_frame(frame* fr_addr, void* ucontext, bool isInJava) { + assert(this->is_Java_thread(), "must be JavaThread"); JavaThread* jt = (JavaThread *)this; @@ -87,4 +96,3 @@ } void JavaThread::cache_global_variables() { } - diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/os_cpu/windows_x86/vm/thread_windows_x86.hpp --- a/hotspot/src/os_cpu/windows_x86/vm/thread_windows_x86.hpp Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/src/os_cpu/windows_x86/vm/thread_windows_x86.hpp Wed Jul 05 18:59:39 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2010, 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 @@ -58,6 +58,12 @@ bool pd_get_top_frame_for_signal_handler(frame* fr_addr, void* ucontext, bool isInJava); + bool pd_get_top_frame_for_profiling(frame* fr_addr, void* ucontext, bool isInJava); + +private: + bool pd_get_top_frame(frame* fr_addr, void* ucontext, bool isInJava); + + public: // These routines are only used on cpu architectures that // have separate register stacks (Itanium). static bool register_stack_overflow() { return false; } diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/share/tools/ProjectCreator/BuildConfig.java --- a/hotspot/src/share/tools/ProjectCreator/BuildConfig.java Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/src/share/tools/ProjectCreator/BuildConfig.java Wed Jul 05 18:59:39 2017 +0200 @@ -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 @@ -152,7 +152,7 @@ sysDefines.add("_WINDOWS"); sysDefines.add("HOTSPOT_BUILD_USER=\\\""+System.getProperty("user.name")+"\\\""); sysDefines.add("HOTSPOT_BUILD_TARGET=\\\""+get("Build")+"\\\""); - sysDefines.add("INCLUDE_TRACE"); + sysDefines.add("INCLUDE_TRACE=1"); sysDefines.add("_JNI_IMPLEMENTATION_"); if (vars.get("PlatformName").equals("Win32")) { sysDefines.add("HOTSPOT_LIB_ARCH=\\\"i386\\\""); diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/share/vm/classfile/classFileParser.cpp --- a/hotspot/src/share/vm/classfile/classFileParser.cpp Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/src/share/vm/classfile/classFileParser.cpp Wed Jul 05 18:59:39 2017 +0200 @@ -39,6 +39,7 @@ #include "memory/gcLocker.hpp" #include "memory/metadataFactory.hpp" #include "memory/oopFactory.hpp" +#include "memory/referenceType.hpp" #include "memory/universe.inline.hpp" #include "oops/constantPool.hpp" #include "oops/fieldStreams.hpp" diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/share/vm/classfile/classLoaderData.cpp --- a/hotspot/src/share/vm/classfile/classLoaderData.cpp Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/src/share/vm/classfile/classLoaderData.cpp Wed Jul 05 18:59:39 2017 +0200 @@ -64,6 +64,11 @@ #include "utilities/growableArray.hpp" #include "utilities/ostream.hpp" +#if INCLUDE_TRACE + #include "trace/tracing.hpp" +#endif + + ClassLoaderData * ClassLoaderData::_the_null_class_loader_data = NULL; ClassLoaderData::ClassLoaderData(Handle h_class_loader, bool is_anonymous, Dependencies dependencies) : @@ -120,6 +125,12 @@ } } +void ClassLoaderData::classes_do(void f(Klass * const)) { + for (Klass* k = _klasses; k != NULL; k = k->next_link()) { + f(k); + } +} + void ClassLoaderData::classes_do(void f(InstanceKlass*)) { for (Klass* k = _klasses; k != NULL; k = k->next_link()) { if (k->oop_is_instance()) { @@ -583,6 +594,19 @@ } } +void ClassLoaderDataGraph::classes_do(void f(Klass* const)) { + for (ClassLoaderData* cld = _head; cld != NULL; cld = cld->next()) { + cld->classes_do(f); + } +} + +void ClassLoaderDataGraph::classes_unloading_do(void f(Klass* const)) { + assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint!"); + for (ClassLoaderData* cld = _unloading; cld != NULL; cld = cld->next()) { + cld->classes_do(f); + } +} + GrowableArray* ClassLoaderDataGraph::new_clds() { assert(_head == NULL || _saved_head != NULL, "remember_new_clds(true) not called?"); @@ -687,6 +711,11 @@ dead->set_next(_unloading); _unloading = dead; } + + if (seen_dead_loader) { + post_class_unload_events(); + } + return seen_dead_loader; } @@ -702,6 +731,20 @@ Metaspace::purge(); } +void ClassLoaderDataGraph::post_class_unload_events(void) { +#if INCLUDE_TRACE + assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint!"); + if (Tracing::enabled()) { + if (Tracing::is_event_enabled(TraceClassUnloadEvent)) { + assert(_unloading != NULL, "need class loader data unload list!"); + _class_unload_time = Tracing::time(); + classes_unloading_do(&class_unload_event); + } + Tracing::on_unloading_classes(); + } +#endif +} + // CDS support // Global metaspaces for writing information to the shared archive. When @@ -769,3 +812,21 @@ class_loader()->print_value_on(out); } } + +#if INCLUDE_TRACE + +TracingTime ClassLoaderDataGraph::_class_unload_time; + +void ClassLoaderDataGraph::class_unload_event(Klass* const k) { + + // post class unload event + EventClassUnload event(UNTIMED); + event.set_endtime(_class_unload_time); + event.set_unloadedClass(k); + oop defining_class_loader = k->class_loader(); + event.set_definingClassLoader(defining_class_loader != NULL ? + defining_class_loader->klass() : (Klass*)NULL); + event.commit(); +} + +#endif /* INCLUDE_TRACE */ diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/share/vm/classfile/classLoaderData.hpp --- a/hotspot/src/share/vm/classfile/classLoaderData.hpp Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/src/share/vm/classfile/classLoaderData.hpp Wed Jul 05 18:59:39 2017 +0200 @@ -32,6 +32,10 @@ #include "runtime/mutex.hpp" #include "utilities/growableArray.hpp" +#if INCLUDE_TRACE +# include "trace/traceTime.hpp" +#endif + // // A class loader represents a linkset. Conceptually, a linkset identifies // the complete transitive closure of resolved links that a dynamic linker can @@ -49,6 +53,7 @@ class JNIMethodBlock; class JNIHandleBlock; class Metadebug; + // GC root for walking class loader data created class ClassLoaderDataGraph : public AllStatic { @@ -63,6 +68,7 @@ static ClassLoaderData* _saved_head; static ClassLoaderData* add(Handle class_loader, bool anonymous, TRAPS); + static void post_class_unload_events(void); public: static ClassLoaderData* find_or_create(Handle class_loader, TRAPS); static void purge(); @@ -71,6 +77,8 @@ static void always_strong_oops_do(OopClosure* blk, KlassClosure* klass_closure, bool must_claim); static void keep_alive_oops_do(OopClosure* blk, KlassClosure* klass_closure, bool must_claim); static void classes_do(KlassClosure* klass_closure); + static void classes_do(void f(Klass* const)); + static void classes_unloading_do(void f(Klass* const)); static bool do_unloading(BoolObjectClosure* is_alive); // CMS support. @@ -86,6 +94,12 @@ static bool contains(address x); static bool contains_loader_data(ClassLoaderData* loader_data); #endif + +#if INCLUDE_TRACE + private: + static TracingTime _class_unload_time; + static void class_unload_event(Klass* const k); +#endif }; // ClassLoaderData class @@ -171,7 +185,7 @@ void unload(); bool keep_alive() const { return _keep_alive; } bool is_alive(BoolObjectClosure* is_alive_closure) const; - + void classes_do(void f(Klass*)); void classes_do(void f(InstanceKlass*)); // Deallocate free list during class unloading. diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/share/vm/classfile/javaClasses.cpp --- a/hotspot/src/share/vm/classfile/javaClasses.cpp Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/src/share/vm/classfile/javaClasses.cpp Wed Jul 05 18:59:39 2017 +0200 @@ -961,7 +961,7 @@ // Read thread status value from threadStatus field in java.lang.Thread java class. java_lang_Thread::ThreadStatus java_lang_Thread::get_thread_status(oop java_thread) { - assert(Thread::current()->is_VM_thread() || + assert(Thread::current()->is_Watcher_thread() || Thread::current()->is_VM_thread() || JavaThread::current()->thread_state() == _thread_in_vm, "Java Thread is not running in vm"); // The threadStatus is only present starting in 1.5 diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/share/vm/classfile/systemDictionary.cpp --- a/hotspot/src/share/vm/classfile/systemDictionary.cpp Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/src/share/vm/classfile/systemDictionary.cpp Wed Jul 05 18:59:39 2017 +0200 @@ -56,6 +56,11 @@ #include "services/classLoadingService.hpp" #include "services/threadService.hpp" +#if INCLUDE_TRACE + #include "trace/tracing.hpp" + #include "trace/traceMacros.hpp" +#endif + Dictionary* SystemDictionary::_dictionary = NULL; PlaceholderTable* SystemDictionary::_placeholders = NULL; @@ -586,10 +591,15 @@ } -Klass* SystemDictionary::resolve_instance_class_or_null(Symbol* name, Handle class_loader, Handle protection_domain, TRAPS) { +Klass* SystemDictionary::resolve_instance_class_or_null(Symbol* name, + Handle class_loader, + Handle protection_domain, + TRAPS) { assert(name != NULL && !FieldType::is_array(name) && !FieldType::is_obj(name), "invalid class name"); + TracingTime class_load_start_time = Tracing::time(); + // UseNewReflection // Fix for 4474172; see evaluation for more details class_loader = Handle(THREAD, java_lang_ClassLoader::non_reflection_class_loader(class_loader())); @@ -804,8 +814,9 @@ // during compilations. MutexLocker mu(Compile_lock, THREAD); update_dictionary(d_index, d_hash, p_index, p_hash, - k, class_loader, THREAD); + k, class_loader, THREAD); } + if (JvmtiExport::should_post_class_load()) { Thread *thread = THREAD; assert(thread->is_Java_thread(), "thread->is_Java_thread()"); @@ -861,8 +872,8 @@ // This brackets the SystemDictionary updates for both defining // and initiating loaders MutexLocker mu(SystemDictionary_lock, THREAD); - placeholders()->find_and_remove(p_index, p_hash, name, loader_data, PlaceholderTable::LOAD_INSTANCE, THREAD); - SystemDictionary_lock->notify_all(); + placeholders()->find_and_remove(p_index, p_hash, name, loader_data, PlaceholderTable::LOAD_INSTANCE, THREAD); + SystemDictionary_lock->notify_all(); } } @@ -870,6 +881,8 @@ return NULL; } + post_class_load_event(class_load_start_time, k, class_loader); + #ifdef ASSERT { ClassLoaderData* loader_data = k->class_loader_data(); @@ -993,6 +1006,8 @@ TRAPS) { TempNewSymbol parsed_name = NULL; + TracingTime class_load_start_time = Tracing::time(); + ClassLoaderData* loader_data; if (host_klass.not_null()) { // Create a new CLD for anonymous class, that uses the same class loader @@ -1048,6 +1063,8 @@ assert(THREAD->is_Java_thread(), "thread->is_Java_thread()"); JvmtiExport::post_class_load((JavaThread *) THREAD, k()); } + + post_class_load_event(class_load_start_time, k, class_loader); } assert(host_klass.not_null() || cp_patches == NULL, "cp_patches only found with host_klass"); @@ -1435,6 +1452,7 @@ JvmtiExport::post_class_load((JavaThread *) THREAD, k()); } + } // Support parallel classloading @@ -1678,6 +1696,7 @@ } return newsize; } + // 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) { @@ -2024,12 +2043,6 @@ } } - // Assign a classid if one has not already been assigned. The - // counter does not need to be atomically incremented since this - // is only done while holding the SystemDictionary_lock. - // All loaded classes get a unique ID. - TRACE_INIT_ID(k); - // Make a new system dictionary entry. Klass* sd_check = find_class(d_index, d_hash, name, loader_data); if (sd_check == NULL) { @@ -2612,6 +2625,27 @@ "Loaded klasses should be in SystemDictionary"); } +// utility function for class load event +void SystemDictionary::post_class_load_event(TracingTime start_time, + instanceKlassHandle k, + Handle initiating_loader) { +#if INCLUDE_TRACE + EventClassLoad event(UNTIMED); + if (event.should_commit()) { + event.set_endtime(Tracing::time()); + event.set_starttime(start_time); + event.set_loadedClass(k()); + oop defining_class_loader = k->class_loader(); + event.set_definingClassLoader(defining_class_loader != NULL ? + defining_class_loader->klass() : (Klass*)NULL); + oop class_loader = initiating_loader.is_null() ? (oop)NULL : initiating_loader(); + event.set_initiatingClassLoader(class_loader != NULL ? + class_loader->klass() : (Klass*)NULL); + event.commit(); + } +#endif /* INCLUDE_TRACE */ +} + #ifndef PRODUCT // statistics code diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/share/vm/classfile/systemDictionary.hpp --- a/hotspot/src/share/vm/classfile/systemDictionary.hpp Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/src/share/vm/classfile/systemDictionary.hpp Wed Jul 05 18:59:39 2017 +0200 @@ -31,9 +31,11 @@ #include "oops/symbol.hpp" #include "runtime/java.hpp" #include "runtime/reflectionUtils.hpp" +#include "trace/traceTime.hpp" #include "utilities/hashtable.hpp" #include "utilities/hashtable.inline.hpp" + // The system dictionary stores all loaded classes and maps: // // [class name,class loader] -> class i.e. [Symbol*,oop] -> Klass* @@ -636,6 +638,9 @@ // Setup link to hierarchy static void add_to_hierarchy(instanceKlassHandle k, TRAPS); + // event based tracing + static void post_class_load_event(TracingTime start_time, instanceKlassHandle k, + Handle initiating_loader); // We pass in the hashtable index so we can calculate it outside of // the SystemDictionary_lock. diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/share/vm/code/codeCache.cpp --- a/hotspot/src/share/vm/code/codeCache.cpp Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/src/share/vm/code/codeCache.cpp Wed Jul 05 18:59:39 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -45,6 +45,7 @@ #include "runtime/java.hpp" #include "runtime/mutexLocker.hpp" #include "services/memoryService.hpp" +#include "trace/tracing.hpp" #include "utilities/xmlstream.hpp" // Helper class for printing in CodeCache @@ -114,7 +115,6 @@ } }; - // CodeCache implementation CodeHeap * CodeCache::_heap = new CodeHeap(); @@ -126,6 +126,7 @@ nmethod* CodeCache::_scavenge_root_nmethods = NULL; nmethod* CodeCache::_saved_nmethods = NULL; +int CodeCache::_codemem_full_count = 0; CodeBlob* CodeCache::first() { assert_locked_or_safepoint(CodeCache_lock); @@ -829,6 +830,22 @@ } } +void CodeCache::report_codemem_full() { + _codemem_full_count++; + EventCodeCacheFull event; + if (event.should_commit()) { + event.set_startAddress((u8)low_bound()); + event.set_commitedTopAddress((u8)high()); + event.set_reservedTopAddress((u8)high_bound()); + event.set_entryCount(nof_blobs()); + event.set_methodCount(nof_nmethods()); + event.set_adaptorCount(nof_adapters()); + event.set_unallocatedCapacity(unallocated_capacity()/K); + event.set_fullCount(_codemem_full_count); + event.commit(); + } +} + //------------------------------------------------------------------------------------------------ // Non-product version diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/share/vm/code/codeCache.hpp --- a/hotspot/src/share/vm/code/codeCache.hpp Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/src/share/vm/code/codeCache.hpp Wed Jul 05 18:59:39 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -64,11 +64,15 @@ static void mark_scavenge_root_nmethods() PRODUCT_RETURN; static void verify_perm_nmethods(CodeBlobClosure* f_or_null) PRODUCT_RETURN; + static int _codemem_full_count; + public: // Initialization static void initialize(); + static void report_codemem_full(); + // Allocation/administration static CodeBlob* allocate(int size, bool is_critical = false); // allocates a new CodeBlob static void commit(CodeBlob* cb); // called when the allocated CodeBlob has been filled @@ -155,6 +159,7 @@ // The full limits of the codeCache static address low_bound() { return (address) _heap->low_boundary(); } static address high_bound() { return (address) _heap->high_boundary(); } + static address high() { return (address) _heap->high(); } // Profiling static address first_address(); // first address used for CodeBlobs @@ -186,6 +191,8 @@ // tells how many nmethods have dependencies static int number_of_nmethods_with_dependencies(); + + static int get_codemem_full_count() { return _codemem_full_count; } }; #endif // SHARE_VM_CODE_CODECACHE_HPP diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/share/vm/compiler/compileBroker.cpp --- a/hotspot/src/share/vm/compiler/compileBroker.cpp Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/src/share/vm/compiler/compileBroker.cpp Wed Jul 05 18:59:39 2017 +0200 @@ -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 @@ -43,6 +43,7 @@ #include "runtime/os.hpp" #include "runtime/sharedRuntime.hpp" #include "runtime/sweeper.hpp" +#include "trace/tracing.hpp" #include "utilities/dtrace.hpp" #include "utilities/events.hpp" #ifdef COMPILER1 @@ -179,9 +180,11 @@ int CompileBroker::_sum_nmethod_size = 0; int CompileBroker::_sum_nmethod_code_size = 0; -CompileQueue* CompileBroker::_c2_method_queue = NULL; -CompileQueue* CompileBroker::_c1_method_queue = NULL; -CompileTask* CompileBroker::_task_free_list = NULL; +long CompileBroker::_peak_compilation_time = 0; + +CompileQueue* CompileBroker::_c2_method_queue = NULL; +CompileQueue* CompileBroker::_c1_method_queue = NULL; +CompileTask* CompileBroker::_task_free_list = NULL; GrowableArray* CompileBroker::_method_threads = NULL; @@ -1795,6 +1798,7 @@ ciMethod* target = ci_env.get_method_from_handle(target_handle); TraceTime t1("compilation", &time); + EventCompilation event; AbstractCompiler *comp = compiler(task_level); if (comp == NULL) { @@ -1836,6 +1840,16 @@ } // simulate crash during compilation assert(task->compile_id() != CICrashAt, "just as planned"); + if (event.should_commit()) { + event.set_method(target->get_Method()); + event.set_compileID(compile_id); + event.set_compileLevel(task->comp_level()); + event.set_succeded(task->is_success()); + event.set_isOsr(is_osr); + event.set_codeSize((task->code() == NULL) ? 0 : task->code()->total_size()); + event.set_inlinedBytes(task->num_inlined_bytecodes()); + event.commit(); + } } pop_jni_handle_block(); @@ -1916,6 +1930,10 @@ } warning("CodeCache is full. Compiler has been disabled."); warning("Try increasing the code cache size using -XX:ReservedCodeCacheSize="); + + CodeCache::report_codemem_full(); + + #ifndef PRODUCT if (CompileTheWorld || ExitOnFullCodeCache) { codecache_print(/* detailed= */ true); @@ -2073,8 +2091,10 @@ // java.lang.management.CompilationMBean _perf_total_compilation->inc(time.ticks()); + _t_total_compilation.add(time); + _peak_compilation_time = time.milliseconds() > _peak_compilation_time ? time.milliseconds() : _peak_compilation_time; + if (CITime) { - _t_total_compilation.add(time); if (is_osr) { _t_osr_compilation.add(time); _sum_osr_bytes_compiled += method->code_size() + task->num_inlined_bytecodes(); @@ -2172,7 +2192,6 @@ tty->print_cr(" nmethod total size : %6d bytes", CompileBroker::_sum_nmethod_size); } - // Debugging output for failure void CompileBroker::print_last_compile() { if ( _last_compile_level != CompLevel_none && diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/share/vm/compiler/compileBroker.hpp --- a/hotspot/src/share/vm/compiler/compileBroker.hpp Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/src/share/vm/compiler/compileBroker.hpp Wed Jul 05 18:59:39 2017 +0200 @@ -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 @@ -299,17 +299,17 @@ static elapsedTimer _t_osr_compilation; static elapsedTimer _t_standard_compilation; + static int _total_compile_count; static int _total_bailout_count; static int _total_invalidated_count; - static int _total_compile_count; static int _total_native_compile_count; static int _total_osr_compile_count; static int _total_standard_compile_count; - static int _sum_osr_bytes_compiled; static int _sum_standard_bytes_compiled; static int _sum_nmethod_size; static int _sum_nmethod_code_size; + static long _peak_compilation_time; static CompilerThread* make_compiler_thread(const char* name, CompileQueue* queue, CompilerCounters* counters, TRAPS); static void init_compiler_threads(int c1_compiler_count, int c2_compiler_count); @@ -421,6 +421,19 @@ // compiler name for debugging static const char* compiler_name(int comp_level); + + static int get_total_compile_count() { return _total_compile_count; } + static int get_total_bailout_count() { return _total_bailout_count; } + static int get_total_invalidated_count() { return _total_invalidated_count; } + static int get_total_native_compile_count() { return _total_native_compile_count; } + static int get_total_osr_compile_count() { return _total_osr_compile_count; } + static int get_total_standard_compile_count() { return _total_standard_compile_count; } + static int get_sum_osr_bytes_compiled() { return _sum_osr_bytes_compiled; } + static int get_sum_standard_bytes_compiled() { return _sum_standard_bytes_compiled; } + static int get_sum_nmethod_size() { return _sum_nmethod_size;} + static int get_sum_nmethod_code_size() { return _sum_nmethod_code_size; } + static long get_peak_compilation_time() { return _peak_compilation_time; } + static long get_total_compilation_time() { return _t_total_compilation.milliseconds(); } }; #endif // SHARE_VM_COMPILER_COMPILEBROKER_HPP diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp --- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp Wed Jul 05 18:59:39 2017 +0200 @@ -37,8 +37,12 @@ #include "gc_implementation/concurrentMarkSweep/vmCMSOperations.hpp" #include "gc_implementation/parNew/parNewGeneration.hpp" #include "gc_implementation/shared/collectorCounters.hpp" +#include "gc_implementation/shared/gcTimer.hpp" +#include "gc_implementation/shared/gcTrace.hpp" +#include "gc_implementation/shared/gcTraceTime.hpp" #include "gc_implementation/shared/isGCActiveMark.hpp" #include "gc_interface/collectedHeap.inline.hpp" +#include "memory/allocation.hpp" #include "memory/cardTableRS.hpp" #include "memory/collectorPolicy.hpp" #include "memory/gcLocker.inline.hpp" @@ -60,7 +64,8 @@ // statics CMSCollector* ConcurrentMarkSweepGeneration::_collector = NULL; -bool CMSCollector::_full_gc_requested = false; +bool CMSCollector::_full_gc_requested = false; +GCCause::Cause CMSCollector::_full_gc_cause = GCCause::_no_gc; ////////////////////////////////////////////////////////////////// // In support of CMS/VM thread synchronization @@ -591,7 +596,10 @@ _concurrent_cycles_since_last_unload(0), _roots_scanning_options(0), _inter_sweep_estimate(CMS_SweepWeight, CMS_SweepPadding), - _intra_sweep_estimate(CMS_SweepWeight, CMS_SweepPadding) + _intra_sweep_estimate(CMS_SweepWeight, CMS_SweepPadding), + _gc_tracer_cm(new (ResourceObj::C_HEAP, mtGC) CMSTracer()), + _gc_timer_cm(new (ResourceObj::C_HEAP, mtGC) ConcurrentGCTimer()), + _cms_start_registered(false) { if (ExplicitGCInvokesConcurrentAndUnloadsClasses) { ExplicitGCInvokesConcurrent = true; @@ -1676,18 +1684,38 @@ _full_gcs_since_conc_gc++; } -void CMSCollector::request_full_gc(unsigned int full_gc_count) { +void CMSCollector::request_full_gc(unsigned int full_gc_count, GCCause::Cause cause) { GenCollectedHeap* gch = GenCollectedHeap::heap(); unsigned int gc_count = gch->total_full_collections(); if (gc_count == full_gc_count) { MutexLockerEx y(CGC_lock, Mutex::_no_safepoint_check_flag); _full_gc_requested = true; + _full_gc_cause = cause; CGC_lock->notify(); // nudge CMS thread } else { assert(gc_count > full_gc_count, "Error: causal loop"); } } +bool CMSCollector::is_external_interruption() { + GCCause::Cause cause = GenCollectedHeap::heap()->gc_cause(); + return GCCause::is_user_requested_gc(cause) || + GCCause::is_serviceability_requested_gc(cause); +} + +void CMSCollector::report_concurrent_mode_interruption() { + if (is_external_interruption()) { + if (PrintGCDetails) { + gclog_or_tty->print(" (concurrent mode interrupted)"); + } + } else { + if (PrintGCDetails) { + gclog_or_tty->print(" (concurrent mode failure)"); + } + _gc_tracer_cm->report_concurrent_mode_failure(); + } +} + // The foreground and background collectors need to coordinate in order // to make sure that they do not mutually interfere with CMS collections. @@ -1845,14 +1873,8 @@ } ) - if (PrintGCDetails && first_state > Idling) { - GCCause::Cause cause = GenCollectedHeap::heap()->gc_cause(); - if (GCCause::is_user_requested_gc(cause) || - GCCause::is_serviceability_requested_gc(cause)) { - gclog_or_tty->print(" (concurrent mode interrupted)"); - } else { - gclog_or_tty->print(" (concurrent mode failure)"); - } + if (first_state > Idling) { + report_concurrent_mode_interruption(); } set_did_compact(should_compact); @@ -1868,6 +1890,10 @@ // Reference objects are active. ref_processor()->clean_up_discovered_references(); + if (first_state > Idling) { + save_heap_summary(); + } + do_compaction_work(clear_all_soft_refs); // Has the GC time limit been exceeded? @@ -1971,7 +1997,14 @@ // a mark-sweep-compact. void CMSCollector::do_compaction_work(bool clear_all_soft_refs) { GenCollectedHeap* gch = GenCollectedHeap::heap(); - TraceTime t("CMS:MSC ", PrintGCDetails && Verbose, true, gclog_or_tty); + + STWGCTimer* gc_timer = GenMarkSweep::gc_timer(); + gc_timer->register_gc_start(os::elapsed_counter()); + + SerialOldTracer* gc_tracer = GenMarkSweep::gc_tracer(); + gc_tracer->report_gc_start(gch->gc_cause(), gc_timer->gc_start()); + + GCTraceTime t("CMS:MSC ", PrintGCDetails && Verbose, true, NULL); if (PrintGC && Verbose && !(GCCause::is_user_requested_gc(gch->gc_cause()))) { gclog_or_tty->print_cr("Compact ConcurrentMarkSweepGeneration after %d " "collections passed to foreground collector", _full_gcs_since_conc_gc); @@ -2062,6 +2095,10 @@ size_policy()->msc_collection_end(gch->gc_cause()); } + gc_timer->register_gc_end(os::elapsed_counter()); + + gc_tracer->report_gc_end(gc_timer->gc_end(), gc_timer->time_partitions()); + // For a mark-sweep-compact, compute_new_size() will be called // in the heap's do_collection() method. } @@ -2093,7 +2130,7 @@ // required. _collectorState = FinalMarking; } - collect_in_foreground(clear_all_soft_refs); + collect_in_foreground(clear_all_soft_refs, GenCollectedHeap::heap()->gc_cause()); // For a mark-sweep, compute_new_size() will be called // in the heap's do_collection() method. @@ -2153,7 +2190,7 @@ // one "collect" method between the background collector and the foreground // collector but the if-then-else required made it cleaner to have // separate methods. -void CMSCollector::collect_in_background(bool clear_all_soft_refs) { +void CMSCollector::collect_in_background(bool clear_all_soft_refs, GCCause::Cause cause) { assert(Thread::current()->is_ConcurrentGC_thread(), "A CMS asynchronous collection is only allowed on a CMS thread."); @@ -2172,6 +2209,7 @@ } else { assert(_collectorState == Idling, "Should be idling before start."); _collectorState = InitialMarking; + register_gc_start(cause); // Reset the expansion cause, now that we are about to begin // a new cycle. clear_expansion_cause(); @@ -2184,6 +2222,7 @@ // ensuing concurrent GC cycle. update_should_unload_classes(); _full_gc_requested = false; // acks all outstanding full gc requests + _full_gc_cause = GCCause::_no_gc; // Signal that we are about to start a collection gch->increment_total_full_collections(); // ... starting a collection cycle _collection_count_start = gch->total_full_collections(); @@ -2263,7 +2302,6 @@ { ReleaseForegroundGC x(this); stats().record_cms_begin(); - VM_CMS_Initial_Mark initial_mark_op(this); VMThread::execute(&initial_mark_op); } @@ -2343,6 +2381,7 @@ CMSTokenSync z(true); // not strictly needed. if (_collectorState == Resizing) { compute_new_size(); + save_heap_summary(); _collectorState = Resetting; } else { assert(_collectorState == Idling, "The state should only change" @@ -2401,7 +2440,39 @@ } } -void CMSCollector::collect_in_foreground(bool clear_all_soft_refs) { +void CMSCollector::register_foreground_gc_start(GCCause::Cause cause) { + if (!_cms_start_registered) { + register_gc_start(cause); + } +} + +void CMSCollector::register_gc_start(GCCause::Cause cause) { + _cms_start_registered = true; + _gc_timer_cm->register_gc_start(os::elapsed_counter()); + _gc_tracer_cm->report_gc_start(cause, _gc_timer_cm->gc_start()); +} + +void CMSCollector::register_gc_end() { + if (_cms_start_registered) { + report_heap_summary(GCWhen::AfterGC); + + _gc_timer_cm->register_gc_end(os::elapsed_counter()); + _gc_tracer_cm->report_gc_end(_gc_timer_cm->gc_end(), _gc_timer_cm->time_partitions()); + _cms_start_registered = false; + } +} + +void CMSCollector::save_heap_summary() { + GenCollectedHeap* gch = GenCollectedHeap::heap(); + _last_heap_summary = gch->create_heap_summary(); + _last_metaspace_summary = gch->create_metaspace_summary(); +} + +void CMSCollector::report_heap_summary(GCWhen::Type when) { + _gc_tracer_cm->report_gc_heap_summary(when, _last_heap_summary, _last_metaspace_summary); +} + +void CMSCollector::collect_in_foreground(bool clear_all_soft_refs, GCCause::Cause cause) { assert(_foregroundGCIsActive && !_foregroundGCShouldWait, "Foreground collector should be waiting, not executing"); assert(Thread::current()->is_VM_thread(), "A foreground collection" @@ -2409,8 +2480,8 @@ assert(ConcurrentMarkSweepThread::vm_thread_has_cms_token(), "VM thread should have CMS token"); - NOT_PRODUCT(TraceTime t("CMS:MS (foreground) ", PrintGCDetails && Verbose, - true, gclog_or_tty);) + NOT_PRODUCT(GCTraceTime t("CMS:MS (foreground) ", PrintGCDetails && Verbose, + true, NULL);) if (UseAdaptiveSizePolicy) { size_policy()->ms_collection_begin(); } @@ -2434,6 +2505,7 @@ } switch (_collectorState) { case InitialMarking: + register_foreground_gc_start(cause); init_mark_was_synchronous = true; // fact to be exploited in re-mark checkpointRootsInitial(false); assert(_collectorState == Marking, "Collector state should have changed" @@ -2482,6 +2554,7 @@ GenCollectedHeap::heap()->total_collections() >= VerifyGCStartAt) { Universe::verify("Verify before reset: "); } + save_heap_summary(); reset(false); assert(_collectorState == Idling, "Collector state should " "have changed"); @@ -3504,6 +3577,9 @@ check_correct_thread_executing(); TraceCMSMemoryManagerStats tms(_collectorState,GenCollectedHeap::heap()->gc_cause()); + save_heap_summary(); + report_heap_summary(GCWhen::BeforeGC); + ReferenceProcessor* rp = ref_processor(); SpecializationStats::clear(); assert(_restart_addr == NULL, "Control point invariant"); @@ -3549,8 +3625,8 @@ // CMS collection cycle. setup_cms_unloading_and_verification_state(); - NOT_PRODUCT(TraceTime t("\ncheckpointRootsInitialWork", - PrintGCDetails && Verbose, true, gclog_or_tty);) + NOT_PRODUCT(GCTraceTime t("\ncheckpointRootsInitialWork", + PrintGCDetails && Verbose, true, _gc_timer_cm);) if (UseAdaptiveSizePolicy) { size_policy()->checkpoint_roots_initial_begin(); } @@ -4542,8 +4618,10 @@ // The code in this method may need further // tweaking for better performance and some restructuring // for cleaner interfaces. + GCTimer *gc_timer = NULL; // Currently not tracing concurrent phases rp->preclean_discovered_references( - rp->is_alive_non_header(), &keep_alive, &complete_trace, &yield_cl); + rp->is_alive_non_header(), &keep_alive, &complete_trace, &yield_cl, + gc_timer); } if (clean_survivor) { // preclean the active survivor space(s) @@ -4885,8 +4963,8 @@ // Temporarily set flag to false, GCH->do_collection will // expect it to be false and set to true FlagSetting fl(gch->_is_gc_active, false); - NOT_PRODUCT(TraceTime t("Scavenge-Before-Remark", - PrintGCDetails && Verbose, true, gclog_or_tty);) + NOT_PRODUCT(GCTraceTime t("Scavenge-Before-Remark", + PrintGCDetails && Verbose, true, _gc_timer_cm);) int level = _cmsGen->level() - 1; if (level >= 0) { gch->do_collection(true, // full (i.e. force, see below) @@ -4915,7 +4993,7 @@ void CMSCollector::checkpointRootsFinalWork(bool asynch, bool clear_all_soft_refs, bool init_mark_was_synchronous) { - NOT_PRODUCT(TraceTime tr("checkpointRootsFinalWork", PrintGCDetails, false, gclog_or_tty);) + NOT_PRODUCT(GCTraceTime tr("checkpointRootsFinalWork", PrintGCDetails, false, _gc_timer_cm);) assert(haveFreelistLocks(), "must have free list locks"); assert_lock_strong(bitMapLock()); @@ -4966,11 +5044,11 @@ // the most recent young generation GC, minus those cleaned up by the // concurrent precleaning. if (CMSParallelRemarkEnabled && CollectedHeap::use_parallel_gc_threads()) { - TraceTime t("Rescan (parallel) ", PrintGCDetails, false, gclog_or_tty); + GCTraceTime t("Rescan (parallel) ", PrintGCDetails, false, _gc_timer_cm); do_remark_parallel(); } else { - TraceTime t("Rescan (non-parallel) ", PrintGCDetails, false, - gclog_or_tty); + GCTraceTime t("Rescan (non-parallel) ", PrintGCDetails, false, + _gc_timer_cm); do_remark_non_parallel(); } } @@ -4983,7 +5061,7 @@ verify_overflow_empty(); { - NOT_PRODUCT(TraceTime ts("refProcessingWork", PrintGCDetails, false, gclog_or_tty);) + NOT_PRODUCT(GCTraceTime ts("refProcessingWork", PrintGCDetails, false, _gc_timer_cm);) refProcessingWork(asynch, clear_all_soft_refs); } verify_work_stacks_empty(); @@ -5044,6 +5122,8 @@ verify_after_remark(); } + _gc_tracer_cm->report_object_count_after_gc(&_is_alive_closure); + // Change under the freelistLocks. _collectorState = Sweeping; // Call isAllClear() under bitMapLock @@ -5697,7 +5777,7 @@ NULL, // space is set further below &_markBitMap, &_markStack, &mrias_cl); { - TraceTime t("grey object rescan", PrintGCDetails, false, gclog_or_tty); + GCTraceTime t("grey object rescan", PrintGCDetails, false, _gc_timer_cm); // Iterate over the dirty cards, setting the corresponding bits in the // mod union table. { @@ -5734,7 +5814,7 @@ Universe::verify(); } { - TraceTime t("root rescan", PrintGCDetails, false, gclog_or_tty); + GCTraceTime t("root rescan", PrintGCDetails, false, _gc_timer_cm); verify_work_stacks_empty(); @@ -5756,7 +5836,7 @@ } { - TraceTime t("visit unhandled CLDs", PrintGCDetails, false, gclog_or_tty); + GCTraceTime t("visit unhandled CLDs", PrintGCDetails, false, _gc_timer_cm); verify_work_stacks_empty(); @@ -5775,7 +5855,7 @@ } { - TraceTime t("dirty klass scan", PrintGCDetails, false, gclog_or_tty); + GCTraceTime t("dirty klass scan", PrintGCDetails, false, _gc_timer_cm); verify_work_stacks_empty(); @@ -5977,7 +6057,9 @@ _span, &_markBitMap, &_markStack, &cmsKeepAliveClosure, false /* !preclean */); { - TraceTime t("weak refs processing", PrintGCDetails, false, gclog_or_tty); + GCTraceTime t("weak refs processing", PrintGCDetails, false, _gc_timer_cm); + + ReferenceProcessorStats stats; if (rp->processing_is_mt()) { // Set the degree of MT here. If the discovery is done MT, there // may have been a different number of threads doing the discovery @@ -5996,16 +6078,20 @@ } rp->set_active_mt_degree(active_workers); CMSRefProcTaskExecutor task_executor(*this); - rp->process_discovered_references(&_is_alive_closure, + stats = rp->process_discovered_references(&_is_alive_closure, &cmsKeepAliveClosure, &cmsDrainMarkingStackClosure, - &task_executor); + &task_executor, + _gc_timer_cm); } else { - rp->process_discovered_references(&_is_alive_closure, + stats = rp->process_discovered_references(&_is_alive_closure, &cmsKeepAliveClosure, &cmsDrainMarkingStackClosure, - NULL); - } + NULL, + _gc_timer_cm); + } + _gc_tracer_cm->report_gc_reference_stats(stats); + } // This is the point where the entire marking should have completed. @@ -6013,7 +6099,7 @@ if (should_unload_classes()) { { - TraceTime t("class unloading", PrintGCDetails, false, gclog_or_tty); + GCTraceTime t("class unloading", PrintGCDetails, false, _gc_timer_cm); // Unload classes and purge the SystemDictionary. bool purged_class = SystemDictionary::do_unloading(&_is_alive_closure); @@ -6026,7 +6112,7 @@ } { - TraceTime t("scrub symbol table", PrintGCDetails, false, gclog_or_tty); + GCTraceTime t("scrub symbol table", PrintGCDetails, false, _gc_timer_cm); // Clean up unreferenced symbols in symbol table. SymbolTable::unlink(); } @@ -6035,7 +6121,7 @@ // CMS doesn't use the StringTable as hard roots when class unloading is turned off. // Need to check if we really scanned the StringTable. if ((roots_scanning_options() & SharedHeap::SO_Strings) == 0) { - TraceTime t("scrub string table", PrintGCDetails, false, gclog_or_tty); + GCTraceTime t("scrub string table", PrintGCDetails, false, _gc_timer_cm); // Delete entries for dead interned strings. StringTable::unlink(&_is_alive_closure); } @@ -6380,12 +6466,14 @@ _cmsGen->rotate_debug_collection_type(); } ) + + register_gc_end(); } void CMSCollector::do_CMS_operation(CMS_op_type op, GCCause::Cause gc_cause) { gclog_or_tty->date_stamp(PrintGC && PrintGCDateStamps); TraceCPUTime tcpu(PrintGCDetails, true, gclog_or_tty); - TraceTime t(GCCauseString("GC", gc_cause), PrintGC, !PrintGCDetails, gclog_or_tty); + GCTraceTime t(GCCauseString("GC", gc_cause), PrintGC, !PrintGCDetails, NULL); TraceCollectorStats tcs(counters()); switch (op) { diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp --- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp Wed Jul 05 18:59:39 2017 +0200 @@ -25,8 +25,10 @@ #ifndef SHARE_VM_GC_IMPLEMENTATION_CONCURRENTMARKSWEEP_CONCURRENTMARKSWEEPGENERATION_HPP #define SHARE_VM_GC_IMPLEMENTATION_CONCURRENTMARKSWEEP_CONCURRENTMARKSWEEPGENERATION_HPP +#include "gc_implementation/shared/gcHeapSummary.hpp" #include "gc_implementation/shared/gSpaceCounters.hpp" #include "gc_implementation/shared/gcStats.hpp" +#include "gc_implementation/shared/gcWhen.hpp" #include "gc_implementation/shared/generationCounters.hpp" #include "memory/freeBlockDictionary.hpp" #include "memory/generation.hpp" @@ -53,6 +55,8 @@ class CMSAdaptiveSizePolicy; class CMSConcMarkingTask; class CMSGCAdaptivePolicyCounters; +class CMSTracer; +class ConcurrentGCTimer; class ConcurrentMarkSweepGeneration; class ConcurrentMarkSweepPolicy; class ConcurrentMarkSweepThread; @@ -61,6 +65,7 @@ class PromotionInfo; class ScanMarkedObjectsAgainCarefullyClosure; class TenuredGeneration; +class SerialOldTracer; // A generic CMS bit map. It's the basis for both the CMS marking bit map // as well as for the mod union table (in each case only a subset of the @@ -567,8 +572,9 @@ bool _completed_initialization; // In support of ExplicitGCInvokesConcurrent - static bool _full_gc_requested; - unsigned int _collection_count_start; + static bool _full_gc_requested; + static GCCause::Cause _full_gc_cause; + unsigned int _collection_count_start; // Should we unload classes this concurrent cycle? bool _should_unload_classes; @@ -609,6 +615,20 @@ AdaptivePaddedAverage _inter_sweep_estimate; AdaptivePaddedAverage _intra_sweep_estimate; + CMSTracer* _gc_tracer_cm; + ConcurrentGCTimer* _gc_timer_cm; + + bool _cms_start_registered; + + GCHeapSummary _last_heap_summary; + MetaspaceSummary _last_metaspace_summary; + + void register_foreground_gc_start(GCCause::Cause cause); + void register_gc_start(GCCause::Cause cause); + void register_gc_end(); + void save_heap_summary(); + void report_heap_summary(GCWhen::Type when); + protected: ConcurrentMarkSweepGeneration* _cmsGen; // old gen (CMS) MemRegion _span; // span covering above two @@ -827,6 +847,10 @@ void do_mark_sweep_work(bool clear_all_soft_refs, CollectorState first_state, bool should_start_over); + // Work methods for reporting concurrent mode interruption or failure + bool is_external_interruption(); + void report_concurrent_mode_interruption(); + // If the backgrould GC is active, acquire control from the background // GC and do the collection. void acquire_control_and_collect(bool full, bool clear_all_soft_refs); @@ -876,11 +900,11 @@ bool clear_all_soft_refs, size_t size, bool tlab); - void collect_in_background(bool clear_all_soft_refs); - void collect_in_foreground(bool clear_all_soft_refs); + void collect_in_background(bool clear_all_soft_refs, GCCause::Cause cause); + void collect_in_foreground(bool clear_all_soft_refs, GCCause::Cause cause); // In support of ExplicitGCInvokesConcurrent - static void request_full_gc(unsigned int full_gc_count); + static void request_full_gc(unsigned int full_gc_count, GCCause::Cause cause); // Should we unload classes in a particular concurrent cycle? bool should_unload_classes() const { return _should_unload_classes; diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepThread.cpp --- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepThread.cpp Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepThread.cpp Wed Jul 05 18:59:39 2017 +0200 @@ -140,7 +140,9 @@ while (!_should_terminate) { sleepBeforeNextCycle(); if (_should_terminate) break; - _collector->collect_in_background(false); // !clear_all_soft_refs + GCCause::Cause cause = _collector->_full_gc_requested ? + _collector->_full_gc_cause : GCCause::_cms_concurrent_mark; + _collector->collect_in_background(false, cause); } assert(_should_terminate, "just checking"); // Check that the state of any protocol for synchronization diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/vmCMSOperations.cpp --- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/vmCMSOperations.cpp Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/vmCMSOperations.cpp Wed Jul 05 18:59:39 2017 +0200 @@ -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 @@ -26,9 +26,12 @@ #include "gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.inline.hpp" #include "gc_implementation/concurrentMarkSweep/concurrentMarkSweepThread.hpp" #include "gc_implementation/concurrentMarkSweep/vmCMSOperations.hpp" +#include "gc_implementation/shared/gcTimer.hpp" +#include "gc_implementation/shared/gcTraceTime.hpp" #include "gc_implementation/shared/isGCActiveMark.hpp" #include "memory/gcLocker.inline.hpp" #include "runtime/interfaceSupport.hpp" +#include "runtime/os.hpp" #include "utilities/dtrace.hpp" @@ -60,6 +63,7 @@ void VM_CMS_Operation::verify_before_gc() { if (VerifyBeforeGC && GenCollectedHeap::heap()->total_collections() >= VerifyGCStartAt) { + GCTraceTime tm("Verify Before", false, false, _collector->_gc_timer_cm); HandleMark hm; FreelistLocker x(_collector); MutexLockerEx y(_collector->bitMapLock(), Mutex::_no_safepoint_check_flag); @@ -71,6 +75,7 @@ void VM_CMS_Operation::verify_after_gc() { if (VerifyAfterGC && GenCollectedHeap::heap()->total_collections() >= VerifyGCStartAt) { + GCTraceTime tm("Verify After", false, false, _collector->_gc_timer_cm); HandleMark hm; FreelistLocker x(_collector); MutexLockerEx y(_collector->bitMapLock(), Mutex::_no_safepoint_check_flag); @@ -140,6 +145,8 @@ ); #endif /* USDT2 */ + _collector->_gc_timer_cm->register_gc_pause_start("Initial Mark", os::elapsed_counter()); + GenCollectedHeap* gch = GenCollectedHeap::heap(); GCCauseSetter gccs(gch, GCCause::_cms_initial_mark); @@ -149,6 +156,9 @@ _collector->do_CMS_operation(CMSCollector::CMS_op_checkpointRootsInitial, gch->gc_cause()); VM_CMS_Operation::verify_after_gc(); + + _collector->_gc_timer_cm->register_gc_pause_end(os::elapsed_counter()); + #ifndef USDT2 HS_DTRACE_PROBE(hs_private, cms__initmark__end); #else /* USDT2 */ @@ -172,6 +182,8 @@ ); #endif /* USDT2 */ + _collector->_gc_timer_cm->register_gc_pause_start("Final Mark", os::elapsed_counter()); + GenCollectedHeap* gch = GenCollectedHeap::heap(); GCCauseSetter gccs(gch, GCCause::_cms_final_remark); @@ -181,6 +193,10 @@ _collector->do_CMS_operation(CMSCollector::CMS_op_checkpointRootsFinal, gch->gc_cause()); VM_CMS_Operation::verify_after_gc(); + + _collector->save_heap_summary(); + _collector->_gc_timer_cm->register_gc_pause_end(os::elapsed_counter()); + #ifndef USDT2 HS_DTRACE_PROBE(hs_private, cms__remark__end); #else /* USDT2 */ @@ -225,7 +241,7 @@ // In case CMS thread was in icms_wait(), wake it up. CMSCollector::start_icms(); // Nudge the CMS thread to start a concurrent collection. - CMSCollector::request_full_gc(_full_gc_count_before); + CMSCollector::request_full_gc(_full_gc_count_before, _gc_cause); } else { assert(_full_gc_count_before < gch->total_full_collections(), "Error"); FullGCCount_lock->notify_all(); // Inform the Java thread its work is done diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp --- a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp Wed Jul 05 18:59:39 2017 +0200 @@ -36,6 +36,9 @@ #include "gc_implementation/g1/heapRegionRemSet.hpp" #include "gc_implementation/g1/heapRegionSeq.inline.hpp" #include "gc_implementation/shared/vmGCOperations.hpp" +#include "gc_implementation/shared/gcTimer.hpp" +#include "gc_implementation/shared/gcTrace.hpp" +#include "gc_implementation/shared/gcTraceTime.hpp" #include "memory/genOopClosures.inline.hpp" #include "memory/referencePolicy.hpp" #include "memory/resourceArea.hpp" @@ -1342,6 +1345,9 @@ _remark_times.add((now - start) * 1000.0); g1p->record_concurrent_mark_remark_end(); + + G1CMIsAliveClosure is_alive(g1h); + g1h->gc_tracer_cm()->report_object_count_after_gc(&is_alive); } // Base class of the closures that finalize and verify the @@ -2129,6 +2135,7 @@ } g1h->verify_region_sets_optional(); + g1h->trace_heap_after_concurrent_cycle(); } void ConcurrentMark::completeCleanup() { @@ -2439,7 +2446,7 @@ if (G1Log::finer()) { gclog_or_tty->put(' '); } - TraceTime t("GC ref-proc", G1Log::finer(), false, gclog_or_tty); + GCTraceTime t("GC ref-proc", G1Log::finer(), false, g1h->gc_timer_cm()); ReferenceProcessor* rp = g1h->ref_processor_cm(); @@ -2491,10 +2498,13 @@ rp->set_active_mt_degree(active_workers); // Process the weak references. - rp->process_discovered_references(&g1_is_alive, - &g1_keep_alive, - &g1_drain_mark_stack, - executor); + const ReferenceProcessorStats& stats = + rp->process_discovered_references(&g1_is_alive, + &g1_keep_alive, + &g1_drain_mark_stack, + executor, + g1h->gc_timer_cm()); + g1h->gc_tracer_cm()->report_gc_reference_stats(stats); // The do_oop work routines of the keep_alive and drain_marking_stack // oop closures will set the has_overflown flag if we overflow the @@ -3227,6 +3237,9 @@ satb_mq_set.set_active_all_threads( false, /* new active value */ satb_mq_set.is_active() /* expected_active */); + + _g1h->trace_heap_after_concurrent_cycle(); + _g1h->register_concurrent_cycle_end(); } static void print_ms_time_info(const char* prefix, const char* name, diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/share/vm/gc_implementation/g1/concurrentMark.hpp --- a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.hpp Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.hpp Wed Jul 05 18:59:39 2017 +0200 @@ -569,8 +569,6 @@ void clear_has_overflown() { _has_overflown = false; } bool restart_for_overflow() { return _restart_for_overflow; } - bool has_aborted() { return _has_aborted; } - // Methods to enter the two overflow sync barriers void enter_first_sync_barrier(uint worker_id); void enter_second_sync_barrier(uint worker_id); @@ -821,6 +819,8 @@ // Called to abort the marking cycle after a Full GC takes palce. void abort(); + bool has_aborted() { return _has_aborted; } + // This prints the global/local fingers. It is used for debugging. NOT_PRODUCT(void print_finger();) diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/share/vm/gc_implementation/g1/concurrentMarkThread.cpp --- a/hotspot/src/share/vm/gc_implementation/g1/concurrentMarkThread.cpp Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentMarkThread.cpp Wed Jul 05 18:59:39 2017 +0200 @@ -93,7 +93,6 @@ ResourceMark rm; HandleMark hm; double cycle_start = os::elapsedVTime(); - char verbose_str[128]; // We have to ensure that we finish scanning the root regions // before the next GC takes place. To ensure this we have to @@ -155,8 +154,7 @@ } CMCheckpointRootsFinalClosure final_cl(_cm); - sprintf(verbose_str, "GC remark"); - VM_CGC_Operation op(&final_cl, verbose_str, true /* needs_pll */); + VM_CGC_Operation op(&final_cl, "GC remark", true /* needs_pll */); VMThread::execute(&op); } if (cm()->restart_for_overflow()) { @@ -187,8 +185,7 @@ } CMCleanUp cl_cl(_cm); - sprintf(verbose_str, "GC cleanup"); - VM_CGC_Operation op(&cl_cl, verbose_str, false /* needs_pll */); + VM_CGC_Operation op(&cl_cl, "GC cleanup", false /* needs_pll */); VMThread::execute(&op); } else { // We don't want to update the marking status if a GC pause @@ -292,6 +289,7 @@ // called System.gc() with +ExplicitGCInvokesConcurrent). _sts.join(); g1h->increment_old_marking_cycles_completed(true /* concurrent */); + g1h->register_concurrent_cycle_end(); _sts.leave(); } assert(_should_terminate, "just checking"); diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/share/vm/gc_implementation/g1/evacuationInfo.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/src/share/vm/gc_implementation/g1/evacuationInfo.hpp Wed Jul 05 18:59:39 2017 +0200 @@ -0,0 +1,81 @@ +/* + * 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. + * + */ + +#ifndef SHARE_VM_GC_IMPLEMENTATION_SHARED_EVACUATIONINFO_HPP +#define SHARE_VM_GC_IMPLEMENTATION_SHARED_EVACUATIONINFO_HPP + +#include "memory/allocation.hpp" + +class EvacuationInfo : public StackObj { + uint _collectionset_regions; + uint _allocation_regions; + size_t _collectionset_used_before; + size_t _collectionset_used_after; + size_t _alloc_regions_used_before; + size_t _bytes_copied; + uint _regions_freed; + +public: + EvacuationInfo() : _collectionset_regions(0), _allocation_regions(0), _collectionset_used_before(0), + _collectionset_used_after(0), _alloc_regions_used_before(0), + _bytes_copied(0), _regions_freed(0) { } + + void set_collectionset_regions(uint collectionset_regions) { + _collectionset_regions = collectionset_regions; + } + + void set_allocation_regions(uint allocation_regions) { + _allocation_regions = allocation_regions; + } + + void set_collectionset_used_before(size_t used) { + _collectionset_used_before = used; + } + + void increment_collectionset_used_after(size_t used) { + _collectionset_used_after += used; + } + + void set_alloc_regions_used_before(size_t used) { + _alloc_regions_used_before = used; + } + + void set_bytes_copied(size_t copied) { + _bytes_copied = copied; + } + + void set_regions_freed(uint freed) { + _regions_freed += freed; + } + + uint collectionset_regions() { return _collectionset_regions; } + uint allocation_regions() { return _allocation_regions; } + size_t collectionset_used_before() { return _collectionset_used_before; } + size_t collectionset_used_after() { return _collectionset_used_after; } + size_t alloc_regions_used_before() { return _alloc_regions_used_before; } + size_t bytes_copied() { return _bytes_copied; } + uint regions_freed() { return _regions_freed; } +}; + +#endif // SHARE_VM_GC_IMPLEMENTATION_SHARED_EVACUATIONINFO_HPP diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Wed Jul 05 18:59:39 2017 +0200 @@ -38,10 +38,15 @@ #include "gc_implementation/g1/g1MarkSweep.hpp" #include "gc_implementation/g1/g1OopClosures.inline.hpp" #include "gc_implementation/g1/g1RemSet.inline.hpp" +#include "gc_implementation/g1/g1YCTypes.hpp" #include "gc_implementation/g1/heapRegion.inline.hpp" #include "gc_implementation/g1/heapRegionRemSet.hpp" #include "gc_implementation/g1/heapRegionSeq.inline.hpp" #include "gc_implementation/g1/vm_operations_g1.hpp" +#include "gc_implementation/shared/gcHeapSummary.hpp" +#include "gc_implementation/shared/gcTimer.hpp" +#include "gc_implementation/shared/gcTrace.hpp" +#include "gc_implementation/shared/gcTraceTime.hpp" #include "gc_implementation/shared/isGCActiveMark.hpp" #include "memory/gcLocker.inline.hpp" #include "memory/genOopClosures.inline.hpp" @@ -76,7 +81,7 @@ // The number of GC workers is passed to heap_region_par_iterate_chunked(). // It does use run_task() which sets _n_workers in the task. // G1ParTask executes g1_process_strong_roots() -> -// SharedHeap::process_strong_roots() which calls eventuall to +// SharedHeap::process_strong_roots() which calls eventually to // CardTableModRefBS::par_non_clean_card_iterate_work() which uses // SequentialSubTasksDone. SharedHeap::process_strong_roots() also // directly uses SubTasksDone (_process_strong_tasks field in SharedHeap). @@ -457,7 +462,7 @@ #endif // Returns true if the reference points to an object that -// can move in an incremental collecction. +// can move in an incremental collection. bool G1CollectedHeap::is_scavengable(const void* p) { G1CollectedHeap* g1h = G1CollectedHeap::heap(); G1CollectorPolicy* g1p = g1h->g1_policy(); @@ -548,7 +553,7 @@ return res; } - // Wait here until we get notifed either when (a) there are no + // Wait here until we get notified either when (a) there are no // more free regions coming or (b) some regions have been moved on // the secondary_free_list. SecondaryFreeList_lock->wait(Mutex::_no_safepoint_check_flag); @@ -623,7 +628,7 @@ uint first = G1_NULL_HRS_INDEX; if (num_regions == 1) { // Only one region to allocate, no need to go through the slower - // path. The caller will attempt the expasion if this fails, so + // path. The caller will attempt the expansion if this fails, so // let's not try to expand here too. HeapRegion* hr = new_region(word_size, false /* do_expand */); if (hr != NULL) { @@ -688,7 +693,7 @@ // the first region. HeapWord* new_obj = first_hr->bottom(); // This will be the new end of the first region in the series that - // should also match the end of the last region in the seriers. + // should also match the end of the last region in the series. HeapWord* new_end = new_obj + word_size_sum; // This will be the new top of the first region that will reflect // this allocation. @@ -863,7 +868,7 @@ bool* gc_overhead_limit_was_exceeded) { assert_heap_not_locked_and_not_at_safepoint(); - // Loop until the allocation is satisified, or unsatisfied after GC. + // Loop until the allocation is satisfied, or unsatisfied after GC. for (int try_count = 1, gclocker_retry_count = 0; /* we'll return */; try_count += 1) { unsigned int gc_count_before; @@ -1003,7 +1008,7 @@ (*gclocker_retry_count_ret) += 1; } - // We can reach here if we were unsuccessul in scheduling a + // We can reach here if we were unsuccessful in scheduling a // collection (because another thread beat us to it) or if we were // stalled due to the GC locker. In either can we should retry the // allocation attempt in case another thread successfully @@ -1128,7 +1133,7 @@ (*gclocker_retry_count_ret) += 1; } - // We can reach here if we were unsuccessul in scheduling a + // We can reach here if we were unsuccessful in scheduling a // collection (because another thread beat us to it) or if we were // stalled due to the GC locker. In either can we should retry the // allocation attempt in case another thread successfully @@ -1298,10 +1303,17 @@ return false; } + STWGCTimer* gc_timer = G1MarkSweep::gc_timer(); + gc_timer->register_gc_start(os::elapsed_counter()); + + SerialOldTracer* gc_tracer = G1MarkSweep::gc_tracer(); + gc_tracer->report_gc_start(gc_cause(), gc_timer->gc_start()); + SvcGCMarker sgcm(SvcGCMarker::FULL); ResourceMark rm; print_heap_before_gc(); + trace_heap_before_gc(gc_tracer); size_t metadata_prev_used = MetaspaceAux::allocated_used_bytes(); @@ -1322,7 +1334,7 @@ TraceCPUTime tcpu(G1Log::finer(), true, gclog_or_tty); { - TraceTime t(GCCauseString("Full GC", gc_cause()), G1Log::fine(), true, gclog_or_tty); + GCTraceTime t(GCCauseString("Full GC", gc_cause()), G1Log::fine(), true, NULL); TraceCollectorStats tcs(g1mm()->full_collection_counters()); TraceMemoryManagerStats tms(true /* fullGC */, gc_cause()); @@ -1351,7 +1363,7 @@ verify_before_gc(); - pre_full_gc_dump(); + pre_full_gc_dump(gc_timer); COMPILER2_PRESENT(DerivedPointerTable::clear()); @@ -1433,7 +1445,7 @@ reset_gc_time_stamp(); // Since everything potentially moved, we will clear all remembered - // sets, and clear all cards. Later we will rebuild remebered + // sets, and clear all cards. Later we will rebuild remembered // sets. We will also reset the GC time stamps of the regions. clear_rsets_post_compaction(); check_gc_time_stamps(); @@ -1553,8 +1565,12 @@ } print_heap_after_gc(); - - post_full_gc_dump(); + trace_heap_after_gc(gc_tracer); + + post_full_gc_dump(gc_timer); + + gc_timer->register_gc_end(os::elapsed_counter()); + gc_tracer->report_gc_end(gc_timer->gc_end(), gc_timer->time_partitions()); } return true; @@ -1919,7 +1935,7 @@ _ref_processor_stw(NULL), _process_strong_tasks(new SubTasksDone(G1H_PS_NumElements)), _bot_shared(NULL), - _evac_failure_scan_stack(NULL) , + _evac_failure_scan_stack(NULL), _mark_in_progress(false), _cg1r(NULL), _summary_bytes_used(0), _g1mm(NULL), @@ -1939,12 +1955,18 @@ _surviving_young_words(NULL), _old_marking_cycles_started(0), _old_marking_cycles_completed(0), + _concurrent_cycle_started(false), _in_cset_fast_test(NULL), _in_cset_fast_test_base(NULL), _dirty_cards_region_list(NULL), _worker_cset_start_region(NULL), - _worker_cset_start_region_time_stamp(NULL) { - _g1h = this; // To catch bugs. + _worker_cset_start_region_time_stamp(NULL), + _gc_timer_stw(new (ResourceObj::C_HEAP, mtGC) STWGCTimer()), + _gc_timer_cm(new (ResourceObj::C_HEAP, mtGC) ConcurrentGCTimer()), + _gc_tracer_stw(new (ResourceObj::C_HEAP, mtGC) G1NewTracer()), + _gc_tracer_cm(new (ResourceObj::C_HEAP, mtGC) G1OldTracer()) { + + _g1h = this; if (_process_strong_tasks == NULL || !_process_strong_tasks->valid()) { vm_exit_during_initialization("Failed necessary allocation."); } @@ -1959,13 +1981,14 @@ _worker_cset_start_region = NEW_C_HEAP_ARRAY(HeapRegion*, n_queues, mtGC); _worker_cset_start_region_time_stamp = NEW_C_HEAP_ARRAY(unsigned int, n_queues, mtGC); + _evacuation_failed_info_array = NEW_C_HEAP_ARRAY(EvacuationFailedInfo, n_queues, mtGC); for (int i = 0; i < n_queues; i++) { RefToScanQueue* q = new RefToScanQueue(); q->initialize(); _task_queues->register_queue(i, q); - } - + ::new (&_evacuation_failed_info_array[i]) EvacuationFailedInfo(); + } clear_cset_start_regions(); // Initialize the G1EvacuationFailureALot counters and flags. @@ -2025,7 +2048,7 @@ HeapRegion::GrainBytes); // It is important to do this in a way such that concurrent readers can't - // temporarily think somethings in the heap. (I've actually seen this + // temporarily think something is in the heap. (I've actually seen this // happen in asserts: DLD.) _reserved.set_word_size(0); _reserved.set_start((HeapWord*)heap_rs.base()); @@ -2462,7 +2485,7 @@ // We need to clear the "in_progress" flag in the CM thread before // we wake up any waiters (especially when ExplicitInvokesConcurrent // is set) so that if a waiter requests another System.gc() it doesn't - // incorrectly see that a marking cyle is still in progress. + // incorrectly see that a marking cycle is still in progress. if (concurrent) { _cmThread->clear_in_progress(); } @@ -2474,6 +2497,49 @@ FullGCCount_lock->notify_all(); } +void G1CollectedHeap::register_concurrent_cycle_start(jlong start_time) { + _concurrent_cycle_started = true; + _gc_timer_cm->register_gc_start(start_time); + + _gc_tracer_cm->report_gc_start(gc_cause(), _gc_timer_cm->gc_start()); + trace_heap_before_gc(_gc_tracer_cm); +} + +void G1CollectedHeap::register_concurrent_cycle_end() { + if (_concurrent_cycle_started) { + _gc_timer_cm->register_gc_end(os::elapsed_counter()); + + if (_cm->has_aborted()) { + _gc_tracer_cm->report_concurrent_mode_failure(); + } + _gc_tracer_cm->report_gc_end(_gc_timer_cm->gc_end(), _gc_timer_cm->time_partitions()); + + _concurrent_cycle_started = false; + } +} + +void G1CollectedHeap::trace_heap_after_concurrent_cycle() { + if (_concurrent_cycle_started) { + trace_heap_after_gc(_gc_tracer_cm); + } +} + +G1YCType G1CollectedHeap::yc_type() { + bool is_young = g1_policy()->gcs_are_young(); + bool is_initial_mark = g1_policy()->during_initial_mark_pause(); + bool is_during_mark = mark_in_progress(); + + if (is_initial_mark) { + return InitialMark; + } else if (is_during_mark) { + return DuringMark; + } else if (is_young) { + return Normal; + } else { + return Mixed; + } +} + void G1CollectedHeap::collect(GCCause::Cause cause) { assert_heap_not_locked(); @@ -2676,13 +2742,13 @@ break; } - // Noone should have claimed it directly. We can given + // No one should have claimed it directly. We can given // that we claimed its "starts humongous" region. assert(chr->claim_value() != claim_value, "sanity"); assert(chr->humongous_start_region() == r, "sanity"); if (chr->claimHeapRegion(claim_value)) { - // we should always be able to claim it; noone else should + // we should always be able to claim it; no one else should // be trying to claim this region bool res2 = cl->doHeapRegion(chr); @@ -2976,7 +3042,7 @@ // the min TLAB size. // Also, this value can be at most the humongous object threshold, - // since we can't allow tlabs to grow big enough to accomodate + // since we can't allow tlabs to grow big enough to accommodate // humongous objects. HeapRegion* hr = _mutator_alloc_region.get(); @@ -3743,10 +3809,15 @@ return false; } + _gc_timer_stw->register_gc_start(os::elapsed_counter()); + + _gc_tracer_stw->report_gc_start(gc_cause(), _gc_timer_stw->gc_start()); + SvcGCMarker sgcm(SvcGCMarker::MINOR); ResourceMark rm; print_heap_before_gc(); + trace_heap_before_gc(_gc_tracer_stw); HRSPhaseSetter x(HRSPhaseEvacuation); verify_region_sets_optional(); @@ -3771,11 +3842,17 @@ // Inner scope for scope based logging, timers, and stats collection { + EvacuationInfo evacuation_info; + if (g1_policy()->during_initial_mark_pause()) { // We are about to start a marking cycle, so we increment the // full collection counter. increment_old_marking_cycles_started(); + register_concurrent_cycle_start(_gc_timer_stw->gc_start()); } + + _gc_tracer_stw->report_yc_type(yc_type()); + TraceCPUTime tcpu(G1Log::finer(), true, gclog_or_tty); int active_workers = (G1CollectedHeap::use_parallel_gc_threads() ? @@ -3885,7 +3962,7 @@ g1_policy()->print_collection_set(g1_policy()->inc_cset_head(), gclog_or_tty); #endif // YOUNG_LIST_VERBOSE - g1_policy()->finalize_cset(target_pause_time_ms); + g1_policy()->finalize_cset(target_pause_time_ms, evacuation_info); _cm->note_start_of_gc(); // We should not verify the per-thread SATB buffers given that @@ -3921,10 +3998,10 @@ setup_surviving_young_words(); // Initialize the GC alloc regions. - init_gc_alloc_regions(); + init_gc_alloc_regions(evacuation_info); // Actually do the work... - evacuate_collection_set(); + evacuate_collection_set(evacuation_info); // We do this to mainly verify the per-thread SATB buffers // (which have been filtered by now) since we didn't verify @@ -3936,7 +4013,7 @@ true /* verify_thread_buffers */, true /* verify_fingers */); - free_collection_set(g1_policy()->collection_set()); + free_collection_set(g1_policy()->collection_set(), evacuation_info); g1_policy()->clear_collection_set(); cleanup_surviving_young_words(); @@ -3964,13 +4041,19 @@ #endif // YOUNG_LIST_VERBOSE g1_policy()->record_survivor_regions(_young_list->survivor_length(), - _young_list->first_survivor_region(), - _young_list->last_survivor_region()); + _young_list->first_survivor_region(), + _young_list->last_survivor_region()); _young_list->reset_auxilary_lists(); if (evacuation_failed()) { _summary_bytes_used = recalculate_used(); + uint n_queues = MAX2((int)ParallelGCThreads, 1); + for (uint i = 0; i < n_queues; i++) { + if (_evacuation_failed_info_array[i].has_failed()) { + _gc_tracer_stw->report_evacuation_failed(_evacuation_failed_info_array[i]); + } + } } else { // The "used" of the the collection set have already been subtracted // when they were freed. Add in the bytes evacuated. @@ -4013,7 +4096,7 @@ } } - // We redo the verificaiton but now wrt to the new CSet which + // We redo the verification but now wrt to the new CSet which // has just got initialized after the previous CSet was freed. _cm->verify_no_cset_oops(true /* verify_stacks */, true /* verify_enqueued_buffers */, @@ -4026,7 +4109,7 @@ // investigate this in CR 7178365. double sample_end_time_sec = os::elapsedTime(); double pause_time_ms = (sample_end_time_sec - sample_start_time_sec) * MILLIUNITS; - g1_policy()->record_collection_pause_end(pause_time_ms); + g1_policy()->record_collection_pause_end(pause_time_ms, evacuation_info); MemoryService::track_memory_usage(); @@ -4093,14 +4176,19 @@ TASKQUEUE_STATS_ONLY(reset_taskqueue_stats()); print_heap_after_gc(); + trace_heap_after_gc(_gc_tracer_stw); // We must call G1MonitoringSupport::update_sizes() in the same scoping level // as an active TraceMemoryManagerStats object (i.e. before the destructor for the // TraceMemoryManagerStats is called) so that the G1 memory pools are updated // before any GC notifications are raised. g1mm()->update_sizes(); - } - + + _gc_tracer_stw->report_evacuation_info(&evacuation_info); + _gc_tracer_stw->report_tenuring_threshold(_g1_policy->tenuring_threshold()); + _gc_timer_stw->register_gc_end(os::elapsed_counter()); + _gc_tracer_stw->report_gc_end(_gc_timer_stw->gc_end(), _gc_timer_stw->time_partitions()); + } // It should now be safe to tell the concurrent mark thread to start // without its logging output interfering with the logging output // that came from the pause. @@ -4152,7 +4240,7 @@ assert(_mutator_alloc_region.get() == NULL, "post-condition"); } -void G1CollectedHeap::init_gc_alloc_regions() { +void G1CollectedHeap::init_gc_alloc_regions(EvacuationInfo& evacuation_info) { assert_at_safepoint(true /* should_be_vm_thread */); _survivor_gc_alloc_region.init(); @@ -4167,7 +4255,7 @@ // a cleanup and it should be on the free list now), or // d) it's humongous (this means that it was emptied // during a cleanup and was added to the free list, but - // has been subseqently used to allocate a humongous + // has been subsequently used to allocate a humongous // object that may be less than the region size). if (retained_region != NULL && !retained_region->in_collection_set() && @@ -4184,10 +4272,13 @@ retained_region->note_start_of_copying(during_im); _old_gc_alloc_region.set(retained_region); _hr_printer.reuse(retained_region); - } -} - -void G1CollectedHeap::release_gc_alloc_regions(uint no_of_gc_workers) { + evacuation_info.set_alloc_regions_used_before(retained_region->used()); + } +} + +void G1CollectedHeap::release_gc_alloc_regions(uint no_of_gc_workers, EvacuationInfo& evacuation_info) { + evacuation_info.set_allocation_regions(_survivor_gc_alloc_region.count() + + _old_gc_alloc_region.count()); _survivor_gc_alloc_region.release(); // If we have an old GC alloc region to release, we'll save it in // _retained_old_gc_alloc_region. If we don't @@ -4270,7 +4361,7 @@ } oop -G1CollectedHeap::handle_evacuation_failure_par(OopsInHeapRegionClosure* cl, +G1CollectedHeap::handle_evacuation_failure_par(G1ParScanThreadState* _par_scan_state, oop old) { assert(obj_in_cs(old), err_msg("obj: "PTR_FORMAT" should still be in the CSet", @@ -4279,7 +4370,12 @@ oop forward_ptr = old->forward_to_atomic(old); if (forward_ptr == NULL) { // Forward-to-self succeeded. - + assert(_par_scan_state != NULL, "par scan state"); + OopsInHeapRegionClosure* cl = _par_scan_state->evac_failure_closure(); + uint queue_num = _par_scan_state->queue_num(); + + _evacuation_failed = true; + _evacuation_failed_info_array[queue_num].register_copy_failure(old->size()); if (_evac_failure_closure != cl) { MutexLockerEx x(EvacFailureStack_lock, Mutex::_no_safepoint_check_flag); assert(!_drain_in_progress, @@ -4310,8 +4406,6 @@ } void G1CollectedHeap::handle_evacuation_failure_common(oop old, markOop m) { - set_evacuation_failed(true); - preserve_mark_if_necessary(old, m); HeapRegion* r = heap_region_containing(old); @@ -4561,8 +4655,7 @@ if (obj_ptr == NULL) { // This will either forward-to-self, or detect that someone else has // installed a forwarding pointer. - OopsInHeapRegionClosure* cl = _par_scan_state->evac_failure_closure(); - return _g1->handle_evacuation_failure_par(cl, old); + return _g1->handle_evacuation_failure_par(_par_scan_state, old); } oop obj = oop(obj_ptr); @@ -5166,7 +5259,7 @@ // will be copied, the reference field set to point to the // new location, and the RSet updated. Otherwise we need to // use the the non-heap or metadata closures directly to copy - // the refernt object and update the pointer, while avoiding + // the referent object and update the pointer, while avoiding // updating the RSet. if (_g1h->is_in_g1_reserved(p)) { @@ -5334,7 +5427,7 @@ } }; -// Driver routine for parallel reference enqueing. +// Driver routine for parallel reference enqueueing. // Creates an instance of the ref enqueueing gang // task and has the worker threads execute it. @@ -5463,7 +5556,7 @@ // processor would have seen that the reference object had already // been 'discovered' and would have skipped discovering the reference, // but would not have treated the reference object as a regular oop. - // As a reult the copy closure would not have been applied to the + // As a result the copy closure would not have been applied to the // referent object. // // We need to explicitly copy these referent objects - the references @@ -5539,21 +5632,28 @@ // Setup the soft refs policy... rp->setup_policy(false); + ReferenceProcessorStats stats; if (!rp->processing_is_mt()) { // Serial reference processing... - rp->process_discovered_references(&is_alive, - &keep_alive, - &drain_queue, - NULL); + stats = rp->process_discovered_references(&is_alive, + &keep_alive, + &drain_queue, + NULL, + _gc_timer_stw); } else { // Parallel reference processing assert(rp->num_q() == no_of_gc_workers, "sanity"); assert(no_of_gc_workers <= rp->max_num_q(), "sanity"); G1STWRefProcTaskExecutor par_task_executor(this, workers(), _task_queues, no_of_gc_workers); - rp->process_discovered_references(&is_alive, &keep_alive, &drain_queue, &par_task_executor); - } - + stats = rp->process_discovered_references(&is_alive, + &keep_alive, + &drain_queue, + &par_task_executor, + _gc_timer_stw); + } + + _gc_tracer_stw->report_gc_reference_stats(stats); // We have completed copying any necessary live referent objects // (that were not copied during the actual pause) so we can // retire any active alloc buffers @@ -5577,7 +5677,7 @@ // Serial reference processing... rp->enqueue_discovered_references(); } else { - // Parallel reference enqueuing + // Parallel reference enqueueing assert(no_of_gc_workers == workers()->active_workers(), "Need to reset active workers"); @@ -5594,15 +5694,15 @@ // FIXME // CM's reference processing also cleans up the string and symbol tables. // Should we do that here also? We could, but it is a serial operation - // and could signicantly increase the pause time. + // and could significantly increase the pause time. double ref_enq_time = os::elapsedTime() - ref_enq_start; g1_policy()->phase_times()->record_ref_enq_time(ref_enq_time * 1000.0); } -void G1CollectedHeap::evacuate_collection_set() { +void G1CollectedHeap::evacuate_collection_set(EvacuationInfo& evacuation_info) { _expand_heap_after_alloc_failure = true; - set_evacuation_failed(false); + _evacuation_failed = false; // Should G1EvacuationFailureALot be in effect for this GC? NOT_PRODUCT(set_evacuation_failure_alot_for_current_gc();) @@ -5691,7 +5791,7 @@ JNIHandles::weak_oops_do(&is_alive, &keep_alive); } - release_gc_alloc_regions(n_workers); + release_gc_alloc_regions(n_workers, evacuation_info); g1_rem_set()->cleanup_after_oops_into_collection_set_do(); // Reset and re-enable the hot card cache. @@ -5714,7 +5814,7 @@ // Enqueue any remaining references remaining on the STW // reference processor's discovered lists. We need to do // this after the card table is cleaned (and verified) as - // the act of enqueuing entries on to the pending list + // the act of enqueueing entries on to the pending list // will log these updates (and dirty their associated // cards). We need these updates logged to update any // RSets. @@ -5942,7 +6042,7 @@ g1_policy()->phase_times()->record_clear_ct_time(elapsed * 1000.0); } -void G1CollectedHeap::free_collection_set(HeapRegion* cs_head) { +void G1CollectedHeap::free_collection_set(HeapRegion* cs_head, EvacuationInfo& evacuation_info) { size_t pre_used = 0; FreeRegionList local_free_list("Local List for CSet Freeing"); @@ -6028,10 +6128,12 @@ cur->set_evacuation_failed(false); // The region is now considered to be old. _old_set.add(cur); + evacuation_info.increment_collectionset_used_after(cur->used()); } cur = next; } + evacuation_info.set_regions_freed(local_free_list.length()); policy->record_max_rs_lengths(rs_lengths); policy->cset_regions_freed(); diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp Wed Jul 05 18:59:39 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2012, 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 @@ -26,10 +26,12 @@ #define SHARE_VM_GC_IMPLEMENTATION_G1_G1COLLECTEDHEAP_HPP #include "gc_implementation/g1/concurrentMark.hpp" +#include "gc_implementation/g1/evacuationInfo.hpp" #include "gc_implementation/g1/g1AllocRegion.hpp" #include "gc_implementation/g1/g1HRPrinter.hpp" +#include "gc_implementation/g1/g1MonitoringSupport.hpp" #include "gc_implementation/g1/g1RemSet.hpp" -#include "gc_implementation/g1/g1MonitoringSupport.hpp" +#include "gc_implementation/g1/g1YCTypes.hpp" #include "gc_implementation/g1/heapRegionSeq.hpp" #include "gc_implementation/g1/heapRegionSets.hpp" #include "gc_implementation/shared/hSpaceCounters.hpp" @@ -61,7 +63,12 @@ class ConcurrentMark; class ConcurrentMarkThread; class ConcurrentG1Refine; +class ConcurrentGCTimer; class GenerationCounters; +class STWGCTimer; +class G1NewTracer; +class G1OldTracer; +class EvacuationFailedInfo; typedef OverflowTaskQueue RefToScanQueue; typedef GenericTaskQueueSet RefToScanQueueSet; @@ -160,7 +167,7 @@ // An instance is embedded into the G1CH and used as the // (optional) _is_alive_non_header closure in the STW // reference processor. It is also extensively used during -// refence processing during STW evacuation pauses. +// reference processing during STW evacuation pauses. class G1STWIsAliveClosure: public BoolObjectClosure { G1CollectedHeap* _g1; public: @@ -323,10 +330,10 @@ void release_mutator_alloc_region(); // It initializes the GC alloc regions at the start of a GC. - void init_gc_alloc_regions(); + void init_gc_alloc_regions(EvacuationInfo& evacuation_info); // It releases the GC alloc regions at the end of a GC. - void release_gc_alloc_regions(uint no_of_gc_workers); + void release_gc_alloc_regions(uint no_of_gc_workers, EvacuationInfo& evacuation_info); // It does any cleanup that needs to be done on the GC alloc regions // before a Full GC. @@ -389,6 +396,8 @@ // concurrent cycles) we have completed. volatile unsigned int _old_marking_cycles_completed; + bool _concurrent_cycle_started; + // This is a non-product method that is helpful for testing. It is // called at the end of a GC and artificially expands the heap by // allocating a number of dead regions. This way we can induce very @@ -734,6 +743,12 @@ return _old_marking_cycles_completed; } + void register_concurrent_cycle_start(jlong start_time); + void register_concurrent_cycle_end(); + void trace_heap_after_concurrent_cycle(); + + G1YCType yc_type(); + G1HRPrinter* hr_printer() { return &_hr_printer; } protected: @@ -769,7 +784,7 @@ bool do_collection_pause_at_safepoint(double target_pause_time_ms); // Actually do the work of evacuating the collection set. - void evacuate_collection_set(); + void evacuate_collection_set(EvacuationInfo& evacuation_info); // The g1 remembered set of the heap. G1RemSet* _g1_rem_set; @@ -794,7 +809,7 @@ // After a collection pause, make the regions in the CS into free // regions. - void free_collection_set(HeapRegion* cs_head); + void free_collection_set(HeapRegion* cs_head, EvacuationInfo& evacuation_info); // Abandon the current collection set without recording policy // statistics or updating free lists. @@ -863,9 +878,7 @@ // True iff a evacuation has failed in the current collection. bool _evacuation_failed; - // Set the attribute indicating whether evacuation has failed in the - // current collection. - void set_evacuation_failed(bool b) { _evacuation_failed = b; } + EvacuationFailedInfo* _evacuation_failed_info_array; // Failed evacuations cause some logical from-space objects to have // forwarding pointers to themselves. Reset them. @@ -907,7 +920,7 @@ void finalize_for_evac_failure(); // An attempt to evacuate "obj" has failed; take necessary steps. - oop handle_evacuation_failure_par(OopsInHeapRegionClosure* cl, oop obj); + oop handle_evacuation_failure_par(G1ParScanThreadState* _par_scan_state, oop obj); void handle_evacuation_failure_common(oop obj, markOop m); #ifndef PRODUCT @@ -939,13 +952,13 @@ inline bool evacuation_should_fail(); // Reset the G1EvacuationFailureALot counters. Should be called at - // the end of an evacuation pause in which an evacuation failure ocurred. + // the end of an evacuation pause in which an evacuation failure occurred. inline void reset_evacuation_should_fail(); #endif // !PRODUCT // ("Weak") Reference processing support. // - // G1 has 2 instances of the referece processor class. One + // G1 has 2 instances of the reference processor class. One // (_ref_processor_cm) handles reference object discovery // and subsequent processing during concurrent marking cycles. // @@ -995,6 +1008,12 @@ // The (stw) reference processor... ReferenceProcessor* _ref_processor_stw; + STWGCTimer* _gc_timer_stw; + ConcurrentGCTimer* _gc_timer_cm; + + G1OldTracer* _gc_tracer_cm; + G1NewTracer* _gc_tracer_stw; + // During reference object discovery, the _is_alive_non_header // closure (if non-null) is applied to the referent object to // determine whether the referent is live. If so then the @@ -1140,9 +1159,12 @@ // The STW reference processor.... ReferenceProcessor* ref_processor_stw() const { return _ref_processor_stw; } - // The Concurent Marking reference processor... + // The Concurrent Marking reference processor... ReferenceProcessor* ref_processor_cm() const { return _ref_processor_cm; } + ConcurrentGCTimer* gc_timer_cm() const { return _gc_timer_cm; } + G1OldTracer* gc_tracer_cm() const { return _gc_tracer_cm; } + virtual size_t capacity() const; virtual size_t used() const; // This should be called when we're not holding the heap lock. The @@ -1200,7 +1222,7 @@ // verify_region_sets_optional() is planted in the code for // list verification in non-product builds (and it can be enabled in - // product builds by definning HEAP_REGION_SET_FORCE_VERIFY to be 1). + // product builds by defining HEAP_REGION_SET_FORCE_VERIFY to be 1). #if HEAP_REGION_SET_FORCE_VERIFY void verify_region_sets_optional() { verify_region_sets(); @@ -1266,7 +1288,7 @@ // The same as above but assume that the caller holds the Heap_lock. void collect_locked(GCCause::Cause cause); - // True iff a evacuation has failed in the most-recent collection. + // True iff an evacuation has failed in the most-recent collection. bool evacuation_failed() { return _evacuation_failed; } // It will free a region if it has allocated objects in it that are @@ -1554,6 +1576,7 @@ // Override; it uses the "prev" marking information virtual void verify(bool silent); + virtual void print_on(outputStream* st) const; virtual void print_extended_on(outputStream* st) const; virtual void print_on_error(outputStream* st) const; @@ -1839,7 +1862,7 @@ G1ParScanHeapEvacClosure* _evac_cl; G1ParScanPartialArrayClosure* _partial_scan_cl; - int _hash_seed; + int _hash_seed; uint _queue_num; size_t _term_attempts; diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp Wed Jul 05 18:59:39 2017 +0200 @@ -909,7 +909,7 @@ // Anything below that is considered to be zero #define MIN_TIMER_GRANULARITY 0.0000001 -void G1CollectorPolicy::record_collection_pause_end(double pause_time_ms) { +void G1CollectorPolicy::record_collection_pause_end(double pause_time_ms, EvacuationInfo& evacuation_info) { double end_time_sec = os::elapsedTime(); assert(_cur_collection_pause_used_regions_at_start >= cset_region_length(), "otherwise, the subtraction below does not make sense"); @@ -941,6 +941,9 @@ _mmu_tracker->add_pause(end_time_sec - pause_time_ms/1000.0, end_time_sec, false); + evacuation_info.set_collectionset_used_before(_collection_set_bytes_used_before); + evacuation_info.set_bytes_copied(_bytes_copied_during_gc); + if (update_stats) { _trace_gen0_time_data.record_end_collection(pause_time_ms, phase_times()); // this is where we update the allocation rate of the application @@ -1896,7 +1899,7 @@ } -void G1CollectorPolicy::finalize_cset(double target_pause_time_ms) { +void G1CollectorPolicy::finalize_cset(double target_pause_time_ms, EvacuationInfo& evacuation_info) { double young_start_time_sec = os::elapsedTime(); YoungList* young_list = _g1->young_list(); @@ -2102,6 +2105,7 @@ double non_young_end_time_sec = os::elapsedTime(); phase_times()->record_non_young_cset_choice_time_ms((non_young_end_time_sec - non_young_start_time_sec) * 1000.0); + evacuation_info.set_collectionset_regions(cset_region_length()); } void TraceGen0TimeData::record_start_collection(double time_to_stop_the_world_ms) { diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp Wed Jul 05 18:59:39 2017 +0200 @@ -671,7 +671,7 @@ // Record the start and end of an evacuation pause. void record_collection_pause_start(double start_time_sec); - void record_collection_pause_end(double pause_time_ms); + void record_collection_pause_end(double pause_time_ms, EvacuationInfo& evacuation_info); // Record the start and end of a full collection. void record_full_collection_start(); @@ -720,7 +720,7 @@ // Choose a new collection set. Marks the chosen regions as being // "in_collection_set", and links them together. The head and number of // the collection set are available via access methods. - void finalize_cset(double target_pause_time_ms); + void finalize_cset(double target_pause_time_ms, EvacuationInfo& evacuation_info); // The head of the list (via "next_in_collection_set()") representing the // current collection set. @@ -879,6 +879,7 @@ ageTable _survivors_age_table; public: + uint tenuring_threshold() const { return _tenuring_threshold; } inline GCAllocPurpose evacuation_destination(HeapRegion* src_region, uint age, size_t word_sz) { diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/share/vm/gc_implementation/g1/g1GCPhaseTimes.hpp --- a/hotspot/src/share/vm/gc_implementation/g1/g1GCPhaseTimes.hpp Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/src/share/vm/gc_implementation/g1/g1GCPhaseTimes.hpp Wed Jul 05 18:59:39 2017 +0200 @@ -38,7 +38,7 @@ NOT_PRODUCT(static const T _uninitialized;) // We are caching the sum and average to only have to calculate them once. - // This is not done in an MT-safe way. It is intetened to allow single + // This is not done in an MT-safe way. It is intended to allow single // threaded code to call sum() and average() multiple times in any order // without having to worry about the cost. bool _has_new_data; diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/share/vm/gc_implementation/g1/g1MarkSweep.cpp --- a/hotspot/src/share/vm/gc_implementation/g1/g1MarkSweep.cpp Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/src/share/vm/gc_implementation/g1/g1MarkSweep.cpp Wed Jul 05 18:59:39 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2012, 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 @@ -31,6 +31,10 @@ #include "code/icBuffer.hpp" #include "gc_implementation/g1/g1Log.hpp" #include "gc_implementation/g1/g1MarkSweep.hpp" +#include "gc_implementation/shared/gcHeapSummary.hpp" +#include "gc_implementation/shared/gcTimer.hpp" +#include "gc_implementation/shared/gcTrace.hpp" +#include "gc_implementation/shared/gcTraceTime.hpp" #include "memory/gcLocker.hpp" #include "memory/genCollectedHeap.hpp" #include "memory/modRefBarrierSet.hpp" @@ -119,7 +123,7 @@ void G1MarkSweep::mark_sweep_phase1(bool& marked_for_unloading, bool clear_all_softrefs) { // Recursively traverse all live objects and mark them - TraceTime tm("phase 1", G1Log::fine() && Verbose, true, gclog_or_tty); + GCTraceTime tm("phase 1", G1Log::fine() && Verbose, true, gc_timer()); GenMarkSweep::trace(" 1"); SharedHeap* sh = SharedHeap::heap(); @@ -139,10 +143,13 @@ assert(rp == G1CollectedHeap::heap()->ref_processor_stw(), "Sanity"); rp->setup_policy(clear_all_softrefs); - rp->process_discovered_references(&GenMarkSweep::is_alive, - &GenMarkSweep::keep_alive, - &GenMarkSweep::follow_stack_closure, - NULL); + const ReferenceProcessorStats& stats = + rp->process_discovered_references(&GenMarkSweep::is_alive, + &GenMarkSweep::keep_alive, + &GenMarkSweep::follow_stack_closure, + NULL, + gc_timer()); + gc_tracer()->report_gc_reference_stats(stats); // This is the point where the entire marking should have completed. @@ -185,6 +192,8 @@ gclog_or_tty->print_cr("]"); } } + + gc_tracer()->report_object_count_after_gc(&GenMarkSweep::is_alive); } class G1PrepareCompactClosure: public HeapRegionClosure { @@ -257,7 +266,7 @@ G1CollectedHeap* g1h = G1CollectedHeap::heap(); - TraceTime tm("phase 2", G1Log::fine() && Verbose, true, gclog_or_tty); + GCTraceTime tm("phase 2", G1Log::fine() && Verbose, true, gc_timer()); GenMarkSweep::trace("2"); // find the first region @@ -294,7 +303,7 @@ G1CollectedHeap* g1h = G1CollectedHeap::heap(); // Adjust the pointers to reflect the new locations - TraceTime tm("phase 3", G1Log::fine() && Verbose, true, gclog_or_tty); + GCTraceTime tm("phase 3", G1Log::fine() && Verbose, true, gc_timer()); GenMarkSweep::trace("3"); SharedHeap* sh = SharedHeap::heap(); @@ -353,7 +362,7 @@ // to use a higher index (saved from phase2) when verifying perm_gen. G1CollectedHeap* g1h = G1CollectedHeap::heap(); - TraceTime tm("phase 4", G1Log::fine() && Verbose, true, gclog_or_tty); + GCTraceTime tm("phase 4", G1Log::fine() && Verbose, true, gc_timer()); GenMarkSweep::trace("4"); G1SpaceCompactClosure blk; diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/share/vm/gc_implementation/g1/g1MarkSweep.hpp --- a/hotspot/src/share/vm/gc_implementation/g1/g1MarkSweep.hpp Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/src/share/vm/gc_implementation/g1/g1MarkSweep.hpp Wed Jul 05 18:59:39 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2010, 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 @@ -54,6 +54,9 @@ static void invoke_at_safepoint(ReferenceProcessor* rp, bool clear_all_softrefs); + static STWGCTimer* gc_timer() { return GenMarkSweep::_gc_timer; } + static SerialOldTracer* gc_tracer() { return GenMarkSweep::_gc_tracer; } + private: // Mark live objects diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/share/vm/gc_implementation/g1/g1MonitoringSupport.hpp --- a/hotspot/src/share/vm/gc_implementation/g1/g1MonitoringSupport.hpp Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/src/share/vm/gc_implementation/g1/g1MonitoringSupport.hpp Wed Jul 05 18:59:39 2017 +0200 @@ -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 @@ -224,6 +224,7 @@ // Monitoring support used by // MemoryService // jstat counters + // Tracing size_t overall_reserved() { return _overall_reserved; } size_t overall_committed() { return _overall_committed; } diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/share/vm/gc_implementation/g1/g1YCTypes.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/src/share/vm/gc_implementation/g1/g1YCTypes.hpp Wed Jul 05 18:59:39 2017 +0200 @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2012, 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. + * + */ + +#ifndef SHARE_VM_GC_IMPLEMENTATION_G1_G1YCTYPES_HPP +#define SHARE_VM_GC_IMPLEMENTATION_G1_G1YCTYPES_HPP + +#include "utilities/debug.hpp" + +enum G1YCType { + Normal, + InitialMark, + DuringMark, + Mixed, + G1YCTypeEndSentinel +}; + +class G1YCTypeHelper { + public: + static const char* to_string(G1YCType type) { + switch(type) { + case Normal: return "Normal"; + case InitialMark: return "Initial Mark"; + case DuringMark: return "During Mark"; + case Mixed: return "Mixed"; + default: ShouldNotReachHere(); return NULL; + } + } +}; + +#endif // SHARE_VM_GC_IMPLEMENTATION_G1_G1YCTYPES_HPP diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/share/vm/gc_implementation/g1/vm_operations_g1.cpp --- a/hotspot/src/share/vm/gc_implementation/g1/vm_operations_g1.cpp Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/src/share/vm/gc_implementation/g1/vm_operations_g1.cpp Wed Jul 05 18:59:39 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2012, 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 @@ -28,6 +28,8 @@ #include "gc_implementation/g1/g1CollectorPolicy.hpp" #include "gc_implementation/g1/g1Log.hpp" #include "gc_implementation/g1/vm_operations_g1.hpp" +#include "gc_implementation/shared/gcTimer.hpp" +#include "gc_implementation/shared/gcTraceTime.hpp" #include "gc_implementation/shared/isGCActiveMark.hpp" #include "gc_implementation/g1/vm_operations_g1.hpp" #include "runtime/interfaceSupport.hpp" @@ -227,7 +229,7 @@ void VM_CGC_Operation::doit() { gclog_or_tty->date_stamp(G1Log::fine() && PrintGCDateStamps); TraceCPUTime tcpu(G1Log::finer(), true, gclog_or_tty); - TraceTime t(_printGCMessage, G1Log::fine(), true, gclog_or_tty); + GCTraceTime t(_printGCMessage, G1Log::fine(), true, G1CollectedHeap::heap()->gc_timer_cm()); SharedHeap* sh = SharedHeap::heap(); // This could go away if CollectedHeap gave access to _gc_is_active... if (sh != NULL) { diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/share/vm/gc_implementation/parNew/parNewGeneration.cpp --- a/hotspot/src/share/vm/gc_implementation/parNew/parNewGeneration.cpp Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/src/share/vm/gc_implementation/parNew/parNewGeneration.cpp Wed Jul 05 18:59:39 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2012, 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 @@ -29,6 +29,11 @@ #include "gc_implementation/shared/adaptiveSizePolicy.hpp" #include "gc_implementation/shared/ageTable.hpp" #include "gc_implementation/shared/parGCAllocBuffer.hpp" +#include "gc_implementation/shared/gcHeapSummary.hpp" +#include "gc_implementation/shared/gcTimer.hpp" +#include "gc_implementation/shared/gcTrace.hpp" +#include "gc_implementation/shared/gcTraceTime.hpp" +#include "gc_implementation/shared/copyFailedInfo.hpp" #include "gc_implementation/shared/spaceDecorator.hpp" #include "memory/defNewGeneration.inline.hpp" #include "memory/genCollectedHeap.hpp" @@ -75,7 +80,6 @@ work_queue_set_, &term_), _is_alive_closure(gen_), _scan_weak_ref_closure(gen_, this), _keep_alive_closure(&_scan_weak_ref_closure), - _promotion_failure_size(0), _strong_roots_time(0.0), _term_time(0.0) { #if TASKQUEUE_STATS @@ -279,13 +283,10 @@ } } -void ParScanThreadState::print_and_clear_promotion_failure_size() { - if (_promotion_failure_size != 0) { - if (PrintPromotionFailure) { - gclog_or_tty->print(" (%d: promotion failure size = " SIZE_FORMAT ") ", - _thread_num, _promotion_failure_size); - } - _promotion_failure_size = 0; +void ParScanThreadState::print_promotion_failure_size() { + if (_promotion_failed_info.has_failed() && PrintPromotionFailure) { + gclog_or_tty->print(" (%d: promotion failure size = " SIZE_FORMAT ") ", + _thread_num, _promotion_failed_info.first_size()); } } @@ -305,6 +306,7 @@ inline ParScanThreadState& thread_state(int i); + void trace_promotion_failed(YoungGCTracer& gc_tracer); void reset(int active_workers, bool promotion_failed); void flush(); @@ -353,13 +355,21 @@ return ((ParScanThreadState*)_data)[i]; } +void ParScanThreadStateSet::trace_promotion_failed(YoungGCTracer& gc_tracer) { + for (int i = 0; i < length(); ++i) { + if (thread_state(i).promotion_failed()) { + gc_tracer.report_promotion_failed(thread_state(i).promotion_failed_info()); + thread_state(i).promotion_failed_info().reset(); + } + } +} void ParScanThreadStateSet::reset(int active_threads, bool promotion_failed) { _term.reset_for_reuse(active_threads); if (promotion_failed) { for (int i = 0; i < length(); ++i) { - thread_state(i).print_and_clear_promotion_failure_size(); + thread_state(i).print_promotion_failure_size(); } } } @@ -583,14 +593,6 @@ gch->set_n_termination(active_workers); } -// The "i" passed to this method is the part of the work for -// this thread. It is not the worker ID. The "i" is derived -// from _started_workers which is incremented in internal_note_start() -// called in GangWorker loop() and which is called under the -// which is called under the protection of the gang monitor and is -// called after a task is started. So "i" is based on -// first-come-first-served. - void ParNewGenTask::work(uint worker_id) { GenCollectedHeap* gch = GenCollectedHeap::heap(); // Since this is being done in a separate thread, need new resource @@ -876,16 +878,45 @@ } +// A Generation that does parallel young-gen collection. + bool ParNewGeneration::_avoid_promotion_undo = false; -// A Generation that does parallel young-gen collection. +void ParNewGeneration::handle_promotion_failed(GenCollectedHeap* gch, ParScanThreadStateSet& thread_state_set, ParNewTracer& gc_tracer) { + assert(_promo_failure_scan_stack.is_empty(), "post condition"); + _promo_failure_scan_stack.clear(true); // Clear cached segments. + + remove_forwarding_pointers(); + if (PrintGCDetails) { + gclog_or_tty->print(" (promotion failed)"); + } + // All the spaces are in play for mark-sweep. + swap_spaces(); // Make life simpler for CMS || rescan; see 6483690. + from()->set_next_compaction_space(to()); + gch->set_incremental_collection_failed(); + // Inform the next generation that a promotion failure occurred. + _next_gen->promotion_failure_occurred(); + + // Trace promotion failure in the parallel GC threads + thread_state_set.trace_promotion_failed(gc_tracer); + // Single threaded code may have reported promotion failure to the global state + if (_promotion_failed_info.has_failed()) { + gc_tracer.report_promotion_failed(_promotion_failed_info); + } + // Reset the PromotionFailureALot counters. + NOT_PRODUCT(Universe::heap()->reset_promotion_should_fail();) +} void ParNewGeneration::collect(bool full, bool clear_all_soft_refs, size_t size, bool is_tlab) { assert(full || size > 0, "otherwise we don't want to collect"); + GenCollectedHeap* gch = GenCollectedHeap::heap(); + + _gc_timer->register_gc_start(os::elapsed_counter()); + assert(gch->kind() == CollectedHeap::GenCollectedHeap, "not a CMS generational heap"); AdaptiveSizePolicy* size_policy = gch->gen_policy()->size_policy(); @@ -906,7 +937,7 @@ set_avoid_promotion_undo(true); } - // If the next generation is too full to accomodate worst-case promotion + // If the next generation is too full to accommodate worst-case promotion // from this generation, pass on collection; let the next generation // do it. if (!collection_attempt_is_safe()) { @@ -915,6 +946,10 @@ } assert(to()->is_empty(), "Else not collection_attempt_is_safe"); + ParNewTracer gc_tracer; + gc_tracer.report_gc_start(gch->gc_cause(), _gc_timer->gc_start()); + gch->trace_heap_before_gc(&gc_tracer); + init_assuming_no_promotion_failure(); if (UseAdaptiveSizePolicy) { @@ -922,7 +957,7 @@ size_policy->minor_collection_begin(); } - TraceTime t1(GCCauseString("GC", gch->gc_cause()), PrintGC && !PrintGCDetails, true, gclog_or_tty); + GCTraceTime t1(GCCauseString("GC", gch->gc_cause()), PrintGC && !PrintGCDetails, true, NULL); // Capture heap used before collection (for printing). size_t gch_prev_used = gch->used(); @@ -975,17 +1010,21 @@ rp->setup_policy(clear_all_soft_refs); // Can the mt_degree be set later (at run_task() time would be best)? rp->set_active_mt_degree(active_workers); + ReferenceProcessorStats stats; if (rp->processing_is_mt()) { ParNewRefProcTaskExecutor task_executor(*this, thread_state_set); - rp->process_discovered_references(&is_alive, &keep_alive, - &evacuate_followers, &task_executor); + stats = rp->process_discovered_references(&is_alive, &keep_alive, + &evacuate_followers, &task_executor, + _gc_timer); } else { thread_state_set.flush(); gch->set_par_threads(0); // 0 ==> non-parallel. gch->save_marks(); - rp->process_discovered_references(&is_alive, &keep_alive, - &evacuate_followers, NULL); + stats = rp->process_discovered_references(&is_alive, &keep_alive, + &evacuate_followers, NULL, + _gc_timer); } + gc_tracer.report_gc_reference_stats(stats); if (!promotion_failed()) { // Swap the survivor spaces. eden()->clear(SpaceDecorator::Mangle); @@ -1010,22 +1049,7 @@ adjust_desired_tenuring_threshold(); } else { - assert(_promo_failure_scan_stack.is_empty(), "post condition"); - _promo_failure_scan_stack.clear(true); // Clear cached segments. - - remove_forwarding_pointers(); - if (PrintGCDetails) { - gclog_or_tty->print(" (promotion failed)"); - } - // All the spaces are in play for mark-sweep. - swap_spaces(); // Make life simpler for CMS || rescan; see 6483690. - from()->set_next_compaction_space(to()); - gch->set_incremental_collection_failed(); - // Inform the next generation that a promotion failure occurred. - _next_gen->promotion_failure_occurred(); - - // Reset the PromotionFailureALot counters. - NOT_PRODUCT(Universe::heap()->reset_promotion_should_fail();) + handle_promotion_failed(gch, thread_state_set, gc_tracer); } // set new iteration safe limit for the survivor spaces from()->set_concurrent_iteration_safe_limit(from()->top()); @@ -1065,6 +1089,13 @@ rp->enqueue_discovered_references(NULL); } rp->verify_no_references_recorded(); + + gch->trace_heap_after_gc(&gc_tracer); + gc_tracer.report_tenuring_threshold(tenuring_threshold()); + + _gc_timer->register_gc_end(os::elapsed_counter()); + + gc_tracer.report_gc_end(_gc_timer->gc_end(), _gc_timer->time_partitions()); } static int sum; @@ -1174,8 +1205,7 @@ new_obj = old; preserve_mark_if_necessary(old, m); - // Log the size of the maiden promotion failure - par_scan_state->log_promotion_failure(sz); + par_scan_state->register_promotion_failure(sz); } old->forward_to(new_obj); @@ -1300,8 +1330,7 @@ failed_to_promote = true; preserve_mark_if_necessary(old, m); - // Log the size of the maiden promotion failure - par_scan_state->log_promotion_failure(sz); + par_scan_state->register_promotion_failure(sz); } } else { // Is in to-space; do copying ourselves. @@ -1599,8 +1628,7 @@ } #undef BUSY -void ParNewGeneration::ref_processor_init() -{ +void ParNewGeneration::ref_processor_init() { if (_ref_processor == NULL) { // Allocate and initialize a reference processor _ref_processor = diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/share/vm/gc_implementation/parNew/parNewGeneration.hpp --- a/hotspot/src/share/vm/gc_implementation/parNew/parNewGeneration.hpp Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/src/share/vm/gc_implementation/parNew/parNewGeneration.hpp Wed Jul 05 18:59:39 2017 +0200 @@ -25,7 +25,9 @@ #ifndef SHARE_VM_GC_IMPLEMENTATION_PARNEW_PARNEWGENERATION_HPP #define SHARE_VM_GC_IMPLEMENTATION_PARNEW_PARNEWGENERATION_HPP +#include "gc_implementation/shared/gcTrace.hpp" #include "gc_implementation/shared/parGCAllocBuffer.hpp" +#include "gc_implementation/shared/copyFailedInfo.hpp" #include "memory/defNewGeneration.hpp" #include "utilities/taskqueue.hpp" @@ -105,7 +107,7 @@ #endif // TASKQUEUE_STATS // Stats for promotion failure - size_t _promotion_failure_size; + PromotionFailedInfo _promotion_failed_info; // Timing numbers. double _start; @@ -180,13 +182,16 @@ void undo_alloc_in_to_space(HeapWord* obj, size_t word_sz); // Promotion failure stats - size_t promotion_failure_size() { return promotion_failure_size(); } - void log_promotion_failure(size_t sz) { - if (_promotion_failure_size == 0) { - _promotion_failure_size = sz; - } + void register_promotion_failure(size_t sz) { + _promotion_failed_info.register_copy_failure(sz); } - void print_and_clear_promotion_failure_size(); + PromotionFailedInfo& promotion_failed_info() { + return _promotion_failed_info; + } + bool promotion_failed() { + return _promotion_failed_info.has_failed(); + } + void print_promotion_failure_size(); #if TASKQUEUE_STATS TaskQueueStats & taskqueue_stats() const { return _work_queue->stats; } @@ -337,6 +342,8 @@ // word being overwritten with a self-forwarding-pointer. void preserve_mark_if_necessary(oop obj, markOop m); + void handle_promotion_failed(GenCollectedHeap* gch, ParScanThreadStateSet& thread_state_set, ParNewTracer& gc_tracer); + protected: bool _survivor_overflow; diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.cpp --- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.cpp Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.cpp Wed Jul 05 18:59:39 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2012, 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 @@ -35,6 +35,8 @@ #include "gc_implementation/parallelScavenge/psPromotionManager.hpp" #include "gc_implementation/parallelScavenge/psScavenge.hpp" #include "gc_implementation/parallelScavenge/vmPSOperations.hpp" +#include "gc_implementation/shared/gcHeapSummary.hpp" +#include "gc_implementation/shared/gcWhen.hpp" #include "memory/gcLocker.inline.hpp" #include "oops/oop.inline.hpp" #include "runtime/handles.inline.hpp" @@ -642,6 +644,29 @@ ensure_parsability(false); // no need to retire TLABs for verification } +PSHeapSummary ParallelScavengeHeap::create_ps_heap_summary() { + PSOldGen* old = old_gen(); + HeapWord* old_committed_end = (HeapWord*)old->virtual_space()->committed_high_addr(); + VirtualSpaceSummary old_summary(old->reserved().start(), old_committed_end, old->reserved().end()); + SpaceSummary old_space(old->reserved().start(), old_committed_end, old->used_in_bytes()); + + PSYoungGen* young = young_gen(); + VirtualSpaceSummary young_summary(young->reserved().start(), + (HeapWord*)young->virtual_space()->committed_high_addr(), young->reserved().end()); + + MutableSpace* eden = young_gen()->eden_space(); + SpaceSummary eden_space(eden->bottom(), eden->end(), eden->used_in_bytes()); + + MutableSpace* from = young_gen()->from_space(); + SpaceSummary from_space(from->bottom(), from->end(), from->used_in_bytes()); + + MutableSpace* to = young_gen()->to_space(); + SpaceSummary to_space(to->bottom(), to->end(), to->used_in_bytes()); + + VirtualSpaceSummary heap_summary = create_heap_space_summary(); + return PSHeapSummary(heap_summary, used(), old_summary, old_space, young_summary, eden_space, from_space, to_space); +} + void ParallelScavengeHeap::print_on(outputStream* st) const { young_gen()->print_on(st); old_gen()->print_on(st); @@ -706,6 +731,12 @@ } } +void ParallelScavengeHeap::trace_heap(GCWhen::Type when, GCTracer* gc_tracer) { + const PSHeapSummary& heap_summary = create_ps_heap_summary(); + const MetaspaceSummary& metaspace_summary = create_metaspace_summary(); + gc_tracer->report_gc_heap_summary(when, heap_summary, metaspace_summary); +} + ParallelScavengeHeap* ParallelScavengeHeap::heap() { assert(_psh != NULL, "Uninitialized access to ParallelScavengeHeap::heap()"); assert(_psh->kind() == CollectedHeap::ParallelScavengeHeap, "not a parallel scavenge heap"); diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.hpp --- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.hpp Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.hpp Wed Jul 05 18:59:39 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2012, 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 @@ -30,14 +30,18 @@ #include "gc_implementation/parallelScavenge/psOldGen.hpp" #include "gc_implementation/parallelScavenge/psYoungGen.hpp" #include "gc_implementation/shared/gcPolicyCounters.hpp" +#include "gc_implementation/shared/gcWhen.hpp" #include "gc_interface/collectedHeap.inline.hpp" #include "utilities/ostream.hpp" class AdjoiningGenerations; +class CollectorPolicy; +class GCHeapSummary; class GCTaskManager; -class PSAdaptiveSizePolicy; class GenerationSizer; class CollectorPolicy; +class PSAdaptiveSizePolicy; +class PSHeapSummary; class ParallelScavengeHeap : public CollectedHeap { friend class VMStructs; @@ -65,6 +69,8 @@ static GCTaskManager* _gc_task_manager; // The task manager. + void trace_heap(GCWhen::Type when, GCTracer* tracer); + protected: static inline size_t total_invocations(); HeapWord* allocate_new_tlab(size_t size); @@ -219,6 +225,7 @@ jlong millis_since_last_gc(); void prepare_for_verify(); + PSHeapSummary create_ps_heap_summary(); virtual void print_on(outputStream* st) const; virtual void print_on_error(outputStream* st) const; virtual void print_gc_threads_on(outputStream* st) const; diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/share/vm/gc_implementation/parallelScavenge/pcTasks.cpp --- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/pcTasks.cpp Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/pcTasks.cpp Wed Jul 05 18:59:39 2017 +0200 @@ -27,6 +27,8 @@ #include "code/codeCache.hpp" #include "gc_implementation/parallelScavenge/pcTasks.hpp" #include "gc_implementation/parallelScavenge/psParallelCompact.hpp" +#include "gc_implementation/shared/gcTimer.hpp" +#include "gc_implementation/shared/gcTraceTime.hpp" #include "gc_interface/collectedHeap.hpp" #include "memory/universe.hpp" #include "oops/objArrayKlass.inline.hpp" @@ -48,8 +50,8 @@ ResourceMark rm; - NOT_PRODUCT(TraceTime tm("ThreadRootsMarkingTask", - PrintGCDetails && TraceParallelOldGCTasks, true, gclog_or_tty)); + NOT_PRODUCT(GCTraceTime tm("ThreadRootsMarkingTask", + PrintGCDetails && TraceParallelOldGCTasks, true, NULL)); ParCompactionManager* cm = ParCompactionManager::gc_thread_compaction_manager(which); @@ -77,8 +79,8 @@ void MarkFromRootsTask::do_it(GCTaskManager* manager, uint which) { assert(Universe::heap()->is_gc_active(), "called outside gc"); - NOT_PRODUCT(TraceTime tm("MarkFromRootsTask", - PrintGCDetails && TraceParallelOldGCTasks, true, gclog_or_tty)); + NOT_PRODUCT(GCTraceTime tm("MarkFromRootsTask", + PrintGCDetails && TraceParallelOldGCTasks, true, NULL)); ParCompactionManager* cm = ParCompactionManager::gc_thread_compaction_manager(which); PSParallelCompact::MarkAndPushClosure mark_and_push_closure(cm); @@ -148,8 +150,8 @@ { assert(Universe::heap()->is_gc_active(), "called outside gc"); - NOT_PRODUCT(TraceTime tm("RefProcTask", - PrintGCDetails && TraceParallelOldGCTasks, true, gclog_or_tty)); + NOT_PRODUCT(GCTraceTime tm("RefProcTask", + PrintGCDetails && TraceParallelOldGCTasks, true, NULL)); ParCompactionManager* cm = ParCompactionManager::gc_thread_compaction_manager(which); PSParallelCompact::MarkAndPushClosure mark_and_push_closure(cm); @@ -204,8 +206,8 @@ void StealMarkingTask::do_it(GCTaskManager* manager, uint which) { assert(Universe::heap()->is_gc_active(), "called outside gc"); - NOT_PRODUCT(TraceTime tm("StealMarkingTask", - PrintGCDetails && TraceParallelOldGCTasks, true, gclog_or_tty)); + NOT_PRODUCT(GCTraceTime tm("StealMarkingTask", + PrintGCDetails && TraceParallelOldGCTasks, true, NULL)); ParCompactionManager* cm = ParCompactionManager::gc_thread_compaction_manager(which); @@ -237,8 +239,8 @@ void StealRegionCompactionTask::do_it(GCTaskManager* manager, uint which) { assert(Universe::heap()->is_gc_active(), "called outside gc"); - NOT_PRODUCT(TraceTime tm("StealRegionCompactionTask", - PrintGCDetails && TraceParallelOldGCTasks, true, gclog_or_tty)); + NOT_PRODUCT(GCTraceTime tm("StealRegionCompactionTask", + PrintGCDetails && TraceParallelOldGCTasks, true, NULL)); ParCompactionManager* cm = ParCompactionManager::gc_thread_compaction_manager(which); @@ -304,8 +306,8 @@ void UpdateDensePrefixTask::do_it(GCTaskManager* manager, uint which) { - NOT_PRODUCT(TraceTime tm("UpdateDensePrefixTask", - PrintGCDetails && TraceParallelOldGCTasks, true, gclog_or_tty)); + NOT_PRODUCT(GCTraceTime tm("UpdateDensePrefixTask", + PrintGCDetails && TraceParallelOldGCTasks, true, NULL)); ParCompactionManager* cm = ParCompactionManager::gc_thread_compaction_manager(which); @@ -319,8 +321,8 @@ void DrainStacksCompactionTask::do_it(GCTaskManager* manager, uint which) { assert(Universe::heap()->is_gc_active(), "called outside gc"); - NOT_PRODUCT(TraceTime tm("DrainStacksCompactionTask", - PrintGCDetails && TraceParallelOldGCTasks, true, gclog_or_tty)); + NOT_PRODUCT(GCTraceTime tm("DrainStacksCompactionTask", + PrintGCDetails && TraceParallelOldGCTasks, true, NULL)); ParCompactionManager* cm = ParCompactionManager::gc_thread_compaction_manager(which); diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/share/vm/gc_implementation/parallelScavenge/psMarkSweep.cpp --- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psMarkSweep.cpp Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psMarkSweep.cpp Wed Jul 05 18:59:39 2017 +0200 @@ -34,6 +34,10 @@ #include "gc_implementation/parallelScavenge/psOldGen.hpp" #include "gc_implementation/parallelScavenge/psScavenge.hpp" #include "gc_implementation/parallelScavenge/psYoungGen.hpp" +#include "gc_implementation/shared/gcHeapSummary.hpp" +#include "gc_implementation/shared/gcTimer.hpp" +#include "gc_implementation/shared/gcTrace.hpp" +#include "gc_implementation/shared/gcTraceTime.hpp" #include "gc_implementation/shared/isGCActiveMark.hpp" #include "gc_implementation/shared/markSweep.hpp" #include "gc_implementation/shared/spaceDecorator.hpp" @@ -108,8 +112,12 @@ } ParallelScavengeHeap* heap = (ParallelScavengeHeap*)Universe::heap(); + assert(heap->kind() == CollectedHeap::ParallelScavengeHeap, "Sanity"); GCCause::Cause gc_cause = heap->gc_cause(); - assert(heap->kind() == CollectedHeap::ParallelScavengeHeap, "Sanity"); + + _gc_timer->register_gc_start(os::elapsed_counter()); + _gc_tracer->report_gc_start(gc_cause, _gc_timer->gc_start()); + PSAdaptiveSizePolicy* size_policy = heap->size_policy(); // The scope of casr should end after code that can change @@ -131,6 +139,7 @@ AdaptiveSizePolicyOutput(size_policy, heap->total_collections()); heap->print_heap_before_gc(); + heap->trace_heap_before_gc(_gc_tracer); // Fill in TLABs heap->accumulate_statistics_all_tlabs(); @@ -147,7 +156,7 @@ old_gen->verify_object_start_array(); } - heap->pre_full_gc_dump(); + heap->pre_full_gc_dump(_gc_timer); // Filled in below to track the state of the young gen after the collection. bool eden_empty; @@ -159,7 +168,7 @@ gclog_or_tty->date_stamp(PrintGC && PrintGCDateStamps); TraceCPUTime tcpu(PrintGCDetails, true, gclog_or_tty); - TraceTime t1(GCCauseString("Full GC", gc_cause), PrintGC, !PrintGCDetails, gclog_or_tty); + GCTraceTime t1(GCCauseString("Full GC", gc_cause), PrintGC, !PrintGCDetails, NULL); TraceCollectorStats tcs(counters()); TraceMemoryManagerStats tms(true /* Full GC */,gc_cause); @@ -374,13 +383,18 @@ NOT_PRODUCT(ref_processor()->verify_no_references_recorded()); heap->print_heap_after_gc(); + heap->trace_heap_after_gc(_gc_tracer); - heap->post_full_gc_dump(); + heap->post_full_gc_dump(_gc_timer); #ifdef TRACESPINNING ParallelTaskTerminator::print_termination_counts(); #endif + _gc_timer->register_gc_end(os::elapsed_counter()); + + _gc_tracer->report_gc_end(_gc_timer->gc_end(), _gc_timer->time_partitions()); + return true; } @@ -498,7 +512,7 @@ void PSMarkSweep::mark_sweep_phase1(bool clear_all_softrefs) { // Recursively traverse all live objects and mark them - TraceTime tm("phase 1", PrintGCDetails && Verbose, true, gclog_or_tty); + GCTraceTime tm("phase 1", PrintGCDetails && Verbose, true, _gc_timer); trace(" 1"); ParallelScavengeHeap* heap = (ParallelScavengeHeap*)Universe::heap(); @@ -531,8 +545,10 @@ // Process reference objects found during marking { ref_processor()->setup_policy(clear_all_softrefs); - ref_processor()->process_discovered_references( - is_alive_closure(), mark_and_push_closure(), follow_stack_closure(), NULL); + const ReferenceProcessorStats& stats = + ref_processor()->process_discovered_references( + is_alive_closure(), mark_and_push_closure(), follow_stack_closure(), NULL, _gc_timer); + gc_tracer()->report_gc_reference_stats(stats); } // This is the point where the entire marking should have completed. @@ -552,11 +568,12 @@ // Clean up unreferenced symbols in symbol table. SymbolTable::unlink(); + _gc_tracer->report_object_count_after_gc(is_alive_closure()); } void PSMarkSweep::mark_sweep_phase2() { - TraceTime tm("phase 2", PrintGCDetails && Verbose, true, gclog_or_tty); + GCTraceTime tm("phase 2", PrintGCDetails && Verbose, true, _gc_timer); trace("2"); // Now all live objects are marked, compute the new object addresses. @@ -586,7 +603,7 @@ void PSMarkSweep::mark_sweep_phase3() { // Adjust the pointers to reflect the new locations - TraceTime tm("phase 3", PrintGCDetails && Verbose, true, gclog_or_tty); + GCTraceTime tm("phase 3", PrintGCDetails && Verbose, true, _gc_timer); trace("3"); ParallelScavengeHeap* heap = (ParallelScavengeHeap*)Universe::heap(); @@ -629,7 +646,7 @@ void PSMarkSweep::mark_sweep_phase4() { EventMark m("4 compact heap"); - TraceTime tm("phase 4", PrintGCDetails && Verbose, true, gclog_or_tty); + GCTraceTime tm("phase 4", PrintGCDetails && Verbose, true, _gc_timer); trace("4"); // All pointers are now adjusted, move objects accordingly diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp --- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp Wed Jul 05 18:59:39 2017 +0200 @@ -39,6 +39,10 @@ #include "gc_implementation/parallelScavenge/psPromotionManager.inline.hpp" #include "gc_implementation/parallelScavenge/psScavenge.hpp" #include "gc_implementation/parallelScavenge/psYoungGen.hpp" +#include "gc_implementation/shared/gcHeapSummary.hpp" +#include "gc_implementation/shared/gcTimer.hpp" +#include "gc_implementation/shared/gcTrace.hpp" +#include "gc_implementation/shared/gcTraceTime.hpp" #include "gc_implementation/shared/isGCActiveMark.hpp" #include "gc_interface/gcCause.hpp" #include "memory/gcLocker.inline.hpp" @@ -799,6 +803,8 @@ } #endif // #ifdef ASSERT +STWGCTimer PSParallelCompact::_gc_timer; +ParallelOldTracer PSParallelCompact::_gc_tracer; elapsedTimer PSParallelCompact::_accumulated_time; unsigned int PSParallelCompact::_total_invocations = 0; unsigned int PSParallelCompact::_maximum_compaction_gc_num = 0; @@ -972,7 +978,7 @@ // at each young gen gc. Do the update unconditionally (even though a // promotion failure does not swap spaces) because an unknown number of minor // collections will have swapped the spaces an unknown number of times. - TraceTime tm("pre compact", print_phases(), true, gclog_or_tty); + GCTraceTime tm("pre compact", print_phases(), true, &_gc_timer); ParallelScavengeHeap* heap = gc_heap(); _space_info[from_space_id].set_space(heap->young_gen()->from_space()); _space_info[to_space_id].set_space(heap->young_gen()->to_space()); @@ -989,6 +995,7 @@ _total_invocations++; heap->print_heap_before_gc(); + heap->trace_heap_before_gc(&_gc_tracer); // Fill in TLABs heap->accumulate_statistics_all_tlabs(); @@ -1014,7 +1021,7 @@ void PSParallelCompact::post_compact() { - TraceTime tm("post compact", print_phases(), true, gclog_or_tty); + GCTraceTime tm("post compact", print_phases(), true, &_gc_timer); for (unsigned int id = old_space_id; id < last_space_id; ++id) { // Clear the marking bitmap, summary data and split info. @@ -1840,7 +1847,7 @@ void PSParallelCompact::summary_phase(ParCompactionManager* cm, bool maximum_compaction) { - TraceTime tm("summary phase", print_phases(), true, gclog_or_tty); + GCTraceTime tm("summary phase", print_phases(), true, &_gc_timer); // trace("2"); #ifdef ASSERT @@ -1998,11 +2005,15 @@ return false; } + ParallelScavengeHeap* heap = gc_heap(); + + _gc_timer.register_gc_start(os::elapsed_counter()); + _gc_tracer.report_gc_start(heap->gc_cause(), _gc_timer.gc_start()); + TimeStamp marking_start; TimeStamp compaction_start; TimeStamp collection_exit; - ParallelScavengeHeap* heap = gc_heap(); GCCause::Cause gc_cause = heap->gc_cause(); PSYoungGen* young_gen = heap->young_gen(); PSOldGen* old_gen = heap->old_gen(); @@ -2018,7 +2029,7 @@ heap->record_gen_tops_before_GC(); } - heap->pre_full_gc_dump(); + heap->pre_full_gc_dump(&_gc_timer); _print_phases = PrintGCDetails && PrintParallelOldGCPhaseTimes; @@ -2045,7 +2056,7 @@ gclog_or_tty->date_stamp(PrintGC && PrintGCDateStamps); TraceCPUTime tcpu(PrintGCDetails, true, gclog_or_tty); - TraceTime t1(GCCauseString("Full GC", gc_cause), PrintGC, !PrintGCDetails, gclog_or_tty); + GCTraceTime t1(GCCauseString("Full GC", gc_cause), PrintGC, !PrintGCDetails, NULL); TraceCollectorStats tcs(counters()); TraceMemoryManagerStats tms(true /* Full GC */,gc_cause); @@ -2065,7 +2076,7 @@ bool marked_for_unloading = false; marking_start.update(); - marking_phase(vmthread_cm, maximum_heap_compaction); + marking_phase(vmthread_cm, maximum_heap_compaction, &_gc_tracer); bool max_on_system_gc = UseMaximumCompactionOnSystemGC && gc_cause == GCCause::_java_lang_system_gc; @@ -2218,6 +2229,8 @@ collection_exit.update(); heap->print_heap_after_gc(); + heap->trace_heap_after_gc(&_gc_tracer); + if (PrintGCTaskTimeStamps) { gclog_or_tty->print_cr("VM-Thread " INT64_FORMAT " " INT64_FORMAT " " INT64_FORMAT, @@ -2226,12 +2239,17 @@ gc_task_manager()->print_task_time_stamps(); } - heap->post_full_gc_dump(); + heap->post_full_gc_dump(&_gc_timer); #ifdef TRACESPINNING ParallelTaskTerminator::print_termination_counts(); #endif + _gc_timer.register_gc_end(os::elapsed_counter()); + + _gc_tracer.report_dense_prefix(dense_prefix(old_space_id)); + _gc_tracer.report_gc_end(_gc_timer.gc_end(), _gc_timer.time_partitions()); + return true; } @@ -2330,9 +2348,10 @@ } void PSParallelCompact::marking_phase(ParCompactionManager* cm, - bool maximum_heap_compaction) { + bool maximum_heap_compaction, + ParallelOldTracer *gc_tracer) { // Recursively traverse all live objects and mark them - TraceTime tm("marking phase", print_phases(), true, gclog_or_tty); + GCTraceTime tm("marking phase", print_phases(), true, &_gc_timer); ParallelScavengeHeap* heap = gc_heap(); uint parallel_gc_threads = heap->gc_task_manager()->workers(); @@ -2347,7 +2366,8 @@ ClassLoaderDataGraph::clear_claimed_marks(); { - TraceTime tm_m("par mark", print_phases(), true, gclog_or_tty); + GCTraceTime tm_m("par mark", print_phases(), true, &_gc_timer); + ParallelScavengeHeap::ParStrongRootsScope psrs; GCTaskQueue* q = GCTaskQueue::create(); @@ -2375,19 +2395,24 @@ // Process reference objects found during marking { - TraceTime tm_r("reference processing", print_phases(), true, gclog_or_tty); + GCTraceTime tm_r("reference processing", print_phases(), true, &_gc_timer); + + ReferenceProcessorStats stats; if (ref_processor()->processing_is_mt()) { RefProcTaskExecutor task_executor; - ref_processor()->process_discovered_references( + stats = ref_processor()->process_discovered_references( is_alive_closure(), &mark_and_push_closure, &follow_stack_closure, - &task_executor); + &task_executor, &_gc_timer); } else { - ref_processor()->process_discovered_references( - is_alive_closure(), &mark_and_push_closure, &follow_stack_closure, NULL); + stats = ref_processor()->process_discovered_references( + is_alive_closure(), &mark_and_push_closure, &follow_stack_closure, NULL, + &_gc_timer); } + + gc_tracer->report_gc_reference_stats(stats); } - TraceTime tm_c("class unloading", print_phases(), true, gclog_or_tty); + GCTraceTime tm_c("class unloading", print_phases(), true, &_gc_timer); // This is the point where the entire marking should have completed. assert(cm->marking_stacks_empty(), "Marking should have completed"); @@ -2406,6 +2431,7 @@ // Clean up unreferenced symbols in symbol table. SymbolTable::unlink(); + _gc_tracer.report_object_count_after_gc(is_alive_closure()); } void PSParallelCompact::follow_klass(ParCompactionManager* cm, Klass* klass) { @@ -2446,7 +2472,7 @@ void PSParallelCompact::adjust_roots() { // Adjust the pointers to reflect the new locations - TraceTime tm("adjust roots", print_phases(), true, gclog_or_tty); + GCTraceTime tm("adjust roots", print_phases(), true, &_gc_timer); // Need new claim bits when tracing through and adjusting pointers. ClassLoaderDataGraph::clear_claimed_marks(); @@ -2482,7 +2508,7 @@ void PSParallelCompact::enqueue_region_draining_tasks(GCTaskQueue* q, uint parallel_gc_threads) { - TraceTime tm("drain task setup", print_phases(), true, gclog_or_tty); + GCTraceTime tm("drain task setup", print_phases(), true, &_gc_timer); // Find the threads that are active unsigned int which = 0; @@ -2556,7 +2582,7 @@ void PSParallelCompact::enqueue_dense_prefix_tasks(GCTaskQueue* q, uint parallel_gc_threads) { - TraceTime tm("dense prefix task setup", print_phases(), true, gclog_or_tty); + GCTraceTime tm("dense prefix task setup", print_phases(), true, &_gc_timer); ParallelCompactData& sd = PSParallelCompact::summary_data(); @@ -2638,7 +2664,7 @@ GCTaskQueue* q, ParallelTaskTerminator* terminator_ptr, uint parallel_gc_threads) { - TraceTime tm("steal task setup", print_phases(), true, gclog_or_tty); + GCTraceTime tm("steal task setup", print_phases(), true, &_gc_timer); // Once a thread has drained it's stack, it should try to steal regions from // other threads. @@ -2686,7 +2712,7 @@ void PSParallelCompact::compact() { // trace("5"); - TraceTime tm("compaction phase", print_phases(), true, gclog_or_tty); + GCTraceTime tm("compaction phase", print_phases(), true, &_gc_timer); ParallelScavengeHeap* heap = (ParallelScavengeHeap*)Universe::heap(); assert(heap->kind() == CollectedHeap::ParallelScavengeHeap, "Sanity"); @@ -2703,7 +2729,7 @@ enqueue_region_stealing_tasks(q, &terminator, active_gc_threads); { - TraceTime tm_pc("par compact", print_phases(), true, gclog_or_tty); + GCTraceTime tm_pc("par compact", print_phases(), true, &_gc_timer); gc_task_manager()->execute_and_wait(q); @@ -2717,7 +2743,7 @@ { // Update the deferred objects, if any. Any compaction manager can be used. - TraceTime tm_du("deferred updates", print_phases(), true, gclog_or_tty); + GCTraceTime tm_du("deferred updates", print_phases(), true, &_gc_timer); ParCompactionManager* cm = ParCompactionManager::manager_array(0); for (unsigned int id = old_space_id; id < last_space_id; ++id) { update_deferred_objects(cm, SpaceId(id)); diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.hpp --- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.hpp Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.hpp Wed Jul 05 18:59:39 2017 +0200 @@ -46,6 +46,8 @@ class PreGCValues; class MoveAndUpdateClosure; class RefProcTaskExecutor; +class ParallelOldTracer; +class STWGCTimer; // The SplitInfo class holds the information needed to 'split' a source region // so that the live data can be copied to two destination *spaces*. Normally, @@ -972,6 +974,8 @@ friend class RefProcTaskProxy; private: + static STWGCTimer _gc_timer; + static ParallelOldTracer _gc_tracer; static elapsedTimer _accumulated_time; static unsigned int _total_invocations; static unsigned int _maximum_compaction_gc_num; @@ -1015,7 +1019,8 @@ // Mark live objects static void marking_phase(ParCompactionManager* cm, - bool maximum_heap_compaction); + bool maximum_heap_compaction, + ParallelOldTracer *gc_tracer); template static inline void follow_root(ParCompactionManager* cm, T* p); @@ -1284,6 +1289,8 @@ // Reference Processing static ReferenceProcessor* const ref_processor() { return _ref_processor; } + static STWGCTimer* gc_timer() { return &_gc_timer; } + // Return the SpaceId for the given address. static SpaceId space_id(HeapWord* addr); diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/share/vm/gc_implementation/parallelScavenge/psPromotionManager.cpp --- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psPromotionManager.cpp Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psPromotionManager.cpp Wed Jul 05 18:59:39 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 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,6 +27,7 @@ #include "gc_implementation/parallelScavenge/psOldGen.hpp" #include "gc_implementation/parallelScavenge/psPromotionManager.inline.hpp" #include "gc_implementation/parallelScavenge/psScavenge.inline.hpp" +#include "gc_implementation/shared/gcTrace.hpp" #include "gc_implementation/shared/mutableSpace.hpp" #include "memory/memRegion.hpp" #include "oops/oop.inline.hpp" @@ -49,7 +50,7 @@ guarantee(_manager_array != NULL, "Could not initialize promotion manager"); _stack_array_depth = new OopStarTaskQueueSet(ParallelGCThreads); - guarantee(_stack_array_depth != NULL, "Cound not initialize promotion manager"); + guarantee(_stack_array_depth != NULL, "Could not initialize promotion manager"); // Create and register the PSPromotionManager(s) for the worker threads. for(uint i=0; iclaimed_stack_depth()->is_empty(), "should be empty"); + if (manager->_promotion_failed_info.has_failed()) { + gc_tracer.report_promotion_failed(manager->_promotion_failed_info); + promotion_failure_occurred = true; + } manager->flush_labs(); } + return promotion_failure_occurred; } #if TASKQUEUE_STATS @@ -187,6 +195,8 @@ _old_lab.initialize(MemRegion(lab_base, (size_t)0)); _old_gen_is_full = false; + _promotion_failed_info.reset(); + TASKQUEUE_STATS_ONLY(reset_stats()); } @@ -305,6 +315,8 @@ // We won any races, we "own" this object. assert(obj == obj->forwardee(), "Sanity"); + _promotion_failed_info.register_copy_failure(obj->size()); + obj->push_contents(this); // Save the mark if needed diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/share/vm/gc_implementation/parallelScavenge/psPromotionManager.hpp --- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psPromotionManager.hpp Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psPromotionManager.hpp Wed Jul 05 18:59:39 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 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 @@ -26,6 +26,8 @@ #define SHARE_VM_GC_IMPLEMENTATION_PARALLELSCAVENGE_PSPROMOTIONMANAGER_HPP #include "gc_implementation/parallelScavenge/psPromotionLAB.hpp" +#include "gc_implementation/shared/gcTrace.hpp" +#include "gc_implementation/shared/copyFailedInfo.hpp" #include "memory/allocation.hpp" #include "utilities/taskqueue.hpp" @@ -33,7 +35,7 @@ // psPromotionManager is used by a single thread to manage object survival // during a scavenge. The promotion manager contains thread local data only. // -// NOTE! Be carefull when allocating the stacks on cheap. If you are going +// NOTE! Be careful when allocating the stacks on cheap. If you are going // to use a promotion manager in more than one thread, the stacks MUST be // on cheap. This can lead to memory leaks, though, as they are not auto // deallocated. @@ -85,6 +87,8 @@ uint _array_chunk_size; uint _min_array_size_for_chunking; + PromotionFailedInfo _promotion_failed_info; + // Accessors static PSOldGen* old_gen() { return _old_gen; } static MutableSpace* young_space() { return _young_space; } @@ -149,7 +153,7 @@ static void initialize(); static void pre_scavenge(); - static void post_scavenge(); + static bool post_scavenge(YoungGCTracer& gc_tracer); static PSPromotionManager* gc_thread_promotion_manager(int index); static PSPromotionManager* vm_thread_promotion_manager(); diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/share/vm/gc_implementation/parallelScavenge/psPromotionManager.inline.hpp --- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psPromotionManager.inline.hpp Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psPromotionManager.inline.hpp Wed Jul 05 18:59:39 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 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 @@ -152,7 +152,7 @@ // This is the promotion failed test, and code handling. // The code belongs here for two reasons. It is slightly - // different thatn the code below, and cannot share the + // different than the code below, and cannot share the // CAS testing code. Keeping the code here also minimizes // the impact on the common case fast path code. diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/share/vm/gc_implementation/parallelScavenge/psScavenge.cpp --- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psScavenge.cpp Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psScavenge.cpp Wed Jul 05 18:59:39 2017 +0200 @@ -34,6 +34,10 @@ #include "gc_implementation/parallelScavenge/psParallelCompact.hpp" #include "gc_implementation/parallelScavenge/psScavenge.inline.hpp" #include "gc_implementation/parallelScavenge/psTasks.hpp" +#include "gc_implementation/shared/gcHeapSummary.hpp" +#include "gc_implementation/shared/gcTimer.hpp" +#include "gc_implementation/shared/gcTrace.hpp" +#include "gc_implementation/shared/gcTraceTime.hpp" #include "gc_implementation/shared/isGCActiveMark.hpp" #include "gc_implementation/shared/spaceDecorator.hpp" #include "gc_interface/gcCause.hpp" @@ -63,10 +67,11 @@ HeapWord* PSScavenge::_young_generation_boundary = NULL; uintptr_t PSScavenge::_young_generation_boundary_compressed = 0; elapsedTimer PSScavenge::_accumulated_time; +STWGCTimer PSScavenge::_gc_timer; +ParallelScavengeTracer PSScavenge::_gc_tracer; Stack PSScavenge::_preserved_mark_stack; Stack PSScavenge::_preserved_oop_stack; CollectorCounters* PSScavenge::_counters = NULL; -bool PSScavenge::_promotion_failed = false; // Define before use class PSIsAliveClosure: public BoolObjectClosure { @@ -259,6 +264,8 @@ assert(_preserved_mark_stack.is_empty(), "should be empty"); assert(_preserved_oop_stack.is_empty(), "should be empty"); + _gc_timer.register_gc_start(os::elapsed_counter()); + TimeStamp scavenge_entry; TimeStamp scavenge_midpoint; TimeStamp scavenge_exit; @@ -278,11 +285,14 @@ return false; } + _gc_tracer.report_gc_start(heap->gc_cause(), _gc_timer.gc_start()); + bool promotion_failure_occurred = false; PSYoungGen* young_gen = heap->young_gen(); PSOldGen* old_gen = heap->old_gen(); PSAdaptiveSizePolicy* size_policy = heap->size_policy(); + heap->increment_total_collections(); AdaptiveSizePolicyOutput(size_policy, heap->total_collections()); @@ -299,12 +309,12 @@ } heap->print_heap_before_gc(); + heap->trace_heap_before_gc(&_gc_tracer); assert(!NeverTenure || _tenuring_threshold == markOopDesc::max_age + 1, "Sanity"); assert(!AlwaysTenure || _tenuring_threshold == 0, "Sanity"); size_t prev_used = heap->used(); - assert(promotion_failed() == false, "Sanity"); // Fill in TLABs heap->accumulate_statistics_all_tlabs(); @@ -321,7 +331,7 @@ gclog_or_tty->date_stamp(PrintGC && PrintGCDateStamps); TraceCPUTime tcpu(PrintGCDetails, true, gclog_or_tty); - TraceTime t1(GCCauseString("GC", gc_cause), PrintGC, !PrintGCDetails, gclog_or_tty); + GCTraceTime t1(GCCauseString("GC", gc_cause), PrintGC, !PrintGCDetails, NULL); TraceCollectorStats tcs(counters()); TraceMemoryManagerStats tms(false /* not full GC */,gc_cause); @@ -387,7 +397,7 @@ // We'll use the promotion manager again later. PSPromotionManager* promotion_manager = PSPromotionManager::vm_thread_promotion_manager(); { - // TraceTime("Roots"); + GCTraceTime tm("Scavenge", false, false, &_gc_timer); ParallelScavengeHeap::ParStrongRootsScope psrs; GCTaskQueue* q = GCTaskQueue::create(); @@ -429,36 +439,41 @@ // Process reference objects discovered during scavenge { + GCTraceTime tm("References", false, false, &_gc_timer); + reference_processor()->setup_policy(false); // not always_clear reference_processor()->set_active_mt_degree(active_workers); PSKeepAliveClosure keep_alive(promotion_manager); PSEvacuateFollowersClosure evac_followers(promotion_manager); + ReferenceProcessorStats stats; if (reference_processor()->processing_is_mt()) { PSRefProcTaskExecutor task_executor; - reference_processor()->process_discovered_references( - &_is_alive_closure, &keep_alive, &evac_followers, &task_executor); + stats = reference_processor()->process_discovered_references( + &_is_alive_closure, &keep_alive, &evac_followers, &task_executor, + &_gc_timer); } else { - reference_processor()->process_discovered_references( - &_is_alive_closure, &keep_alive, &evac_followers, NULL); + stats = reference_processor()->process_discovered_references( + &_is_alive_closure, &keep_alive, &evac_followers, NULL, &_gc_timer); + } + + _gc_tracer.report_gc_reference_stats(stats); + + // Enqueue reference objects discovered during scavenge. + if (reference_processor()->processing_is_mt()) { + PSRefProcTaskExecutor task_executor; + reference_processor()->enqueue_discovered_references(&task_executor); + } else { + reference_processor()->enqueue_discovered_references(NULL); } } - // Enqueue reference objects discovered during scavenge. - if (reference_processor()->processing_is_mt()) { - PSRefProcTaskExecutor task_executor; - reference_processor()->enqueue_discovered_references(&task_executor); - } else { - reference_processor()->enqueue_discovered_references(NULL); - } - + GCTraceTime tm("StringTable", false, false, &_gc_timer); // Unlink any dead interned Strings and process the remaining live ones. PSScavengeRootsClosure root_closure(promotion_manager); StringTable::unlink_or_oops_do(&_is_alive_closure, &root_closure); // Finally, flush the promotion_manager's labs, and deallocate its stacks. - PSPromotionManager::post_scavenge(); - - promotion_failure_occurred = promotion_failed(); + promotion_failure_occurred = PSPromotionManager::post_scavenge(_gc_tracer); if (promotion_failure_occurred) { clean_up_failed_promotion(); if (PrintGC) { @@ -473,8 +488,6 @@ if (!promotion_failure_occurred) { // Swap the survivor spaces. - - young_gen->eden_space()->clear(SpaceDecorator::Mangle); young_gen->from_space()->clear(SpaceDecorator::Mangle); young_gen->swap_spaces(); @@ -612,7 +625,11 @@ NOT_PRODUCT(reference_processor()->verify_no_references_recorded()); - CodeCache::prune_scavenge_root_nmethods(); + { + GCTraceTime tm("Prune Scavenge Root Methods", false, false, &_gc_timer); + + CodeCache::prune_scavenge_root_nmethods(); + } // Re-verify object start arrays if (VerifyObjectStartArray && @@ -652,6 +669,8 @@ } heap->print_heap_after_gc(); + heap->trace_heap_after_gc(&_gc_tracer); + _gc_tracer.report_tenuring_threshold(tenuring_threshold()); if (ZapUnusedHeapArea) { young_gen->eden_space()->check_mangled_unused_area_complete(); @@ -672,6 +691,11 @@ ParallelTaskTerminator::print_termination_counts(); #endif + + _gc_timer.register_gc_end(os::elapsed_counter()); + + _gc_tracer.report_gc_end(_gc_timer.gc_end(), _gc_timer.time_partitions()); + return !promotion_failure_occurred; } @@ -681,7 +705,6 @@ void PSScavenge::clean_up_failed_promotion() { ParallelScavengeHeap* heap = (ParallelScavengeHeap*)Universe::heap(); assert(heap->kind() == CollectedHeap::ParallelScavengeHeap, "Sanity"); - assert(promotion_failed(), "Sanity"); PSYoungGen* young_gen = heap->young_gen(); @@ -706,7 +729,6 @@ // Clear the preserved mark and oop stack caches. _preserved_mark_stack.clear(true); _preserved_oop_stack.clear(true); - _promotion_failed = false; } // Reset the PromotionFailureALot counters. @@ -717,11 +739,10 @@ // fails. Some markOops will need preservation, some will not. Note // that the entire eden is traversed after a failed promotion, with // all forwarded headers replaced by the default markOop. This means -// it is not neccessary to preserve most markOops. +// it is not necessary to preserve most markOops. void PSScavenge::oop_promotion_failed(oop obj, markOop obj_mark) { - _promotion_failed = true; if (obj_mark->must_be_preserved_for_promotion_failure(obj)) { - // Should use per-worker private stakcs hetre rather than + // Should use per-worker private stacks here rather than // locking a common pair of stacks. ThreadCritical tc; _preserved_oop_stack.push(obj); diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/share/vm/gc_implementation/parallelScavenge/psScavenge.hpp --- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psScavenge.hpp Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psScavenge.hpp Wed Jul 05 18:59:39 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 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 @@ -28,6 +28,7 @@ #include "gc_implementation/parallelScavenge/cardTableExtension.hpp" #include "gc_implementation/parallelScavenge/psVirtualspace.hpp" #include "gc_implementation/shared/collectorCounters.hpp" +#include "gc_implementation/shared/gcTrace.hpp" #include "memory/allocation.hpp" #include "oops/oop.hpp" #include "utilities/stack.hpp" @@ -37,8 +38,10 @@ class OopStack; class ReferenceProcessor; class ParallelScavengeHeap; +class ParallelScavengeTracer; class PSIsAliveClosure; class PSRefProcTaskExecutor; +class STWGCTimer; class PSScavenge: AllStatic { friend class PSIsAliveClosure; @@ -68,6 +71,8 @@ static bool _survivor_overflow; // Overflow this collection static uint _tenuring_threshold; // tenuring threshold for next scavenge static elapsedTimer _accumulated_time; // total time spent on scavenge + static STWGCTimer _gc_timer; // GC time book keeper + static ParallelScavengeTracer _gc_tracer; // GC tracing // The lowest address possible for the young_gen. // This is used to decide if an oop should be scavenged, // cards should be marked, etc. @@ -77,7 +82,6 @@ static Stack _preserved_mark_stack; // List of marks to be restored after failed promotion static Stack _preserved_oop_stack; // List of oops that need their mark restored. static CollectorCounters* _counters; // collector performance counters - static bool _promotion_failed; static void clean_up_failed_promotion(); @@ -93,7 +97,6 @@ // Accessors static uint tenuring_threshold() { return _tenuring_threshold; } static elapsedTimer* accumulated_time() { return &_accumulated_time; } - static bool promotion_failed() { return _promotion_failed; } static int consecutive_skipped_scavenges() { return _consecutive_skipped_scavenges; } diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/share/vm/gc_implementation/shared/copyFailedInfo.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/src/share/vm/gc_implementation/shared/copyFailedInfo.hpp Wed Jul 05 18:59:39 2017 +0200 @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2012, 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. + * + */ + +#ifndef SHARE_VM_GC_IMPLEMENTATION_SHARED_COPYFAILEDINFO_HPP +#define SHARE_VM_GC_IMPLEMENTATION_SHARED_COPYFAILEDINFO_HPP + +#include "runtime/thread.hpp" +#include "utilities/globalDefinitions.hpp" + +class CopyFailedInfo : public CHeapObj { + size_t _first_size; + size_t _smallest_size; + size_t _total_size; + uint _count; + + public: + CopyFailedInfo() : _first_size(0), _smallest_size(0), _total_size(0), _count(0) {} + + virtual void register_copy_failure(size_t size) { + if (_first_size == 0) { + _first_size = size; + _smallest_size = size; + } else if (size < _smallest_size) { + _smallest_size = size; + } + _total_size += size; + _count++; + } + + virtual void reset() { + _first_size = 0; + _smallest_size = 0; + _total_size = 0; + _count = 0; + } + + bool has_failed() const { return _count != 0; } + size_t first_size() const { return _first_size; } + size_t smallest_size() const { return _smallest_size; } + size_t total_size() const { return _total_size; } + uint failed_count() const { return _count; } +}; + +class PromotionFailedInfo : public CopyFailedInfo { + OSThread* _thread; + + public: + PromotionFailedInfo() : CopyFailedInfo(), _thread(NULL) {} + + void register_copy_failure(size_t size) { + CopyFailedInfo::register_copy_failure(size); + if (_thread == NULL) { + _thread = Thread::current()->osthread(); + } else { + assert(_thread == Thread::current()->osthread(), "The PromotionFailedInfo should be thread local."); + } + } + + void reset() { + CopyFailedInfo::reset(); + _thread = NULL; + } + + OSThread* thread() const { return _thread; } +}; + +class EvacuationFailedInfo : public CopyFailedInfo {}; + +#endif /* SHARE_VM_GC_IMPLEMENTATION_SHARED_COPYFAILEDINFO_HPP */ diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/share/vm/gc_implementation/shared/gcHeapSummary.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/src/share/vm/gc_implementation/shared/gcHeapSummary.hpp Wed Jul 05 18:59:39 2017 +0200 @@ -0,0 +1,142 @@ +/* + * Copyright (c) 2012, 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. + * + */ + +#ifndef SHARE_VM_GC_IMPLEMENTATION_SHARED_GCHEAPSUMMARY_HPP +#define SHARE_VM_GC_IMPLEMENTATION_SHARED_GCHEAPSUMMARY_HPP + +#include "memory/allocation.hpp" + +class VirtualSpaceSummary : public StackObj { + HeapWord* _start; + HeapWord* _committed_end; + HeapWord* _reserved_end; +public: + VirtualSpaceSummary() : + _start(NULL), _committed_end(NULL), _reserved_end(NULL) { } + VirtualSpaceSummary(HeapWord* start, HeapWord* committed_end, HeapWord* reserved_end) : + _start(start), _committed_end(committed_end), _reserved_end(reserved_end) { } + + HeapWord* start() const { return _start; } + HeapWord* committed_end() const { return _committed_end; } + HeapWord* reserved_end() const { return _reserved_end; } + size_t committed_size() const { return (uintptr_t)_committed_end - (uintptr_t)_start; } + size_t reserved_size() const { return (uintptr_t)_reserved_end - (uintptr_t)_start; } +}; + +class SpaceSummary : public StackObj { + HeapWord* _start; + HeapWord* _end; + size_t _used; +public: + SpaceSummary() : + _start(NULL), _end(NULL), _used(0) { } + SpaceSummary(HeapWord* start, HeapWord* end, size_t used) : + _start(start), _end(end), _used(used) { } + + HeapWord* start() const { return _start; } + HeapWord* end() const { return _end; } + size_t used() const { return _used; } + size_t size() const { return (uintptr_t)_end - (uintptr_t)_start; } +}; + +class MetaspaceSizes : public StackObj { + size_t _capacity; + size_t _used; + size_t _reserved; + + public: + MetaspaceSizes() : _capacity(0), _used(0), _reserved(0) {} + MetaspaceSizes(size_t capacity, size_t used, size_t reserved) : + _capacity(capacity), _used(used), _reserved(reserved) {} + + size_t capacity() const { return _capacity; } + size_t used() const { return _used; } + size_t reserved() const { return _reserved; } +}; + +class GCHeapSummary; +class PSHeapSummary; + +class GCHeapSummaryVisitor { + public: + virtual void visit(const GCHeapSummary* heap_summary) const = 0; + virtual void visit(const PSHeapSummary* heap_summary) const {} +}; + +class GCHeapSummary : public StackObj { + VirtualSpaceSummary _heap; + size_t _used; + + public: + GCHeapSummary() : + _heap(), _used(0) { } + GCHeapSummary(VirtualSpaceSummary& heap_space, size_t used) : + _heap(heap_space), _used(used) { } + + const VirtualSpaceSummary& heap() const { return _heap; } + size_t used() const { return _used; } + + virtual void accept(GCHeapSummaryVisitor* visitor) const { + visitor->visit(this); + } +}; + +class PSHeapSummary : public GCHeapSummary { + VirtualSpaceSummary _old; + SpaceSummary _old_space; + VirtualSpaceSummary _young; + SpaceSummary _eden; + SpaceSummary _from; + SpaceSummary _to; + public: + PSHeapSummary(VirtualSpaceSummary& heap_space, size_t heap_used, VirtualSpaceSummary old, SpaceSummary old_space, VirtualSpaceSummary young, SpaceSummary eden, SpaceSummary from, SpaceSummary to) : + GCHeapSummary(heap_space, heap_used), _old(old), _old_space(old_space), _young(young), _eden(eden), _from(from), _to(to) { } + const VirtualSpaceSummary& old() const { return _old; } + const SpaceSummary& old_space() const { return _old_space; } + const VirtualSpaceSummary& young() const { return _young; } + const SpaceSummary& eden() const { return _eden; } + const SpaceSummary& from() const { return _from; } + const SpaceSummary& to() const { return _to; } + + virtual void accept(GCHeapSummaryVisitor* visitor) const { + visitor->visit(this); + } +}; + +class MetaspaceSummary : public StackObj { + MetaspaceSizes _meta_space; + MetaspaceSizes _data_space; + MetaspaceSizes _class_space; + + public: + MetaspaceSummary() : _meta_space(), _data_space(), _class_space() {} + MetaspaceSummary(const MetaspaceSizes& meta_space, const MetaspaceSizes& data_space, const MetaspaceSizes& class_space) : + _meta_space(meta_space), _data_space(data_space), _class_space(class_space) { } + + const MetaspaceSizes& meta_space() const { return _meta_space; } + const MetaspaceSizes& data_space() const { return _data_space; } + const MetaspaceSizes& class_space() const { return _class_space; } +}; + +#endif // SHARE_VM_GC_IMPLEMENTATION_SHARED_GCHEAPSUMMARY_HPP diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/share/vm/gc_implementation/shared/gcTimer.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/src/share/vm/gc_implementation/shared/gcTimer.cpp Wed Jul 05 18:59:39 2017 +0200 @@ -0,0 +1,374 @@ +/* + * Copyright (c) 2012, 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. + * + */ + +#include "precompiled.hpp" +#include "gc_implementation/shared/gcTimer.hpp" +#include "utilities/growableArray.hpp" + +void GCTimer::register_gc_start(jlong time) { + _time_partitions.clear(); + _gc_start = time; +} + +void GCTimer::register_gc_end(jlong time) { + assert(!_time_partitions.has_active_phases(), + "We should have ended all started phases, before ending the GC"); + + _gc_end = time; +} + +void GCTimer::register_gc_pause_start(const char* name, jlong time) { + _time_partitions.report_gc_phase_start(name, time); +} + +void GCTimer::register_gc_pause_end(jlong time) { + _time_partitions.report_gc_phase_end(time); +} + +void GCTimer::register_gc_phase_start(const char* name, jlong time) { + _time_partitions.report_gc_phase_start(name, time); +} + +void GCTimer::register_gc_phase_end(jlong time) { + _time_partitions.report_gc_phase_end(time); +} + + +void STWGCTimer::register_gc_start(jlong time) { + GCTimer::register_gc_start(time); + register_gc_pause_start("GC Pause", time); +} + +void STWGCTimer::register_gc_end(jlong time) { + register_gc_pause_end(time); + GCTimer::register_gc_end(time); +} + +void ConcurrentGCTimer::register_gc_pause_start(const char* name, jlong time) { + GCTimer::register_gc_pause_start(name, time); +} + +void ConcurrentGCTimer::register_gc_pause_end(jlong time) { + GCTimer::register_gc_pause_end(time); +} + +void PhasesStack::clear() { + _next_phase_level = 0; +} + +void PhasesStack::push(int phase_index) { + assert(_next_phase_level < PHASE_LEVELS, "Overflow"); + + _phase_indices[_next_phase_level] = phase_index; + + _next_phase_level++; +} + +int PhasesStack::pop() { + assert(_next_phase_level > 0, "Underflow"); + + _next_phase_level--; + + return _phase_indices[_next_phase_level]; +} + +int PhasesStack::count() const { + return _next_phase_level; +} + + +TimePartitions::TimePartitions() { + _phases = new (ResourceObj::C_HEAP, mtGC) GrowableArray(INITIAL_CAPACITY, true, mtGC); + clear(); +} + +TimePartitions::~TimePartitions() { + delete _phases; + _phases = NULL; +} + +void TimePartitions::clear() { + _phases->clear(); + _active_phases.clear(); + _sum_of_pauses = 0; + _longest_pause = 0; +} + +void TimePartitions::report_gc_phase_start(const char* name, jlong time) { + assert(_phases->length() <= 1000, "Too many recored phases?"); + + int level = _active_phases.count(); + + PausePhase phase; + phase.set_level(level); + phase.set_name(name); + phase.set_start(time); + + int index = _phases->append(phase); + + _active_phases.push(index); +} + +void TimePartitions::update_statistics(GCPhase* phase) { + // FIXME: This should only be done for pause phases + if (phase->level() == 0) { + jlong pause = phase->end() - phase->start(); + _sum_of_pauses += pause; + _longest_pause = MAX2(pause, _longest_pause); + } +} + +void TimePartitions::report_gc_phase_end(jlong time) { + int phase_index = _active_phases.pop(); + GCPhase* phase = _phases->adr_at(phase_index); + phase->set_end(time); + update_statistics(phase); +} + +int TimePartitions::num_phases() const { + return _phases->length(); +} + +GCPhase* TimePartitions::phase_at(int index) const { + assert(index >= 0, "Out of bounds"); + assert(index < _phases->length(), "Out of bounds"); + + return _phases->adr_at(index); +} + +jlong TimePartitions::sum_of_pauses() { + return _sum_of_pauses; +} + +jlong TimePartitions::longest_pause() { + return _longest_pause; +} + +bool TimePartitions::has_active_phases() { + return _active_phases.count() > 0; +} + +bool TimePartitionPhasesIterator::has_next() { + return _next < _time_partitions->num_phases(); +} + +GCPhase* TimePartitionPhasesIterator::next() { + assert(has_next(), "Must have phases left"); + return _time_partitions->phase_at(_next++); +} + + +/////////////// Unit tests /////////////// + +#ifndef PRODUCT + +class TimePartitionPhasesIteratorTest { + public: + static void all() { + one_pause(); + two_pauses(); + one_sub_pause_phase(); + many_sub_pause_phases(); + many_sub_pause_phases2(); + max_nested_pause_phases(); + } + + static void validate_pause_phase(GCPhase* phase, int level, const char* name, jlong start, jlong end) { + assert(phase->level() == level, "Incorrect level"); + assert(strcmp(phase->name(), name) == 0, "Incorrect name"); + assert(phase->start() == start, "Incorrect start"); + assert(phase->end() == end, "Incorrect end"); + } + + static void one_pause() { + TimePartitions time_partitions; + time_partitions.report_gc_phase_start("PausePhase", 2); + time_partitions.report_gc_phase_end(8); + + TimePartitionPhasesIterator iter(&time_partitions); + + validate_pause_phase(iter.next(), 0, "PausePhase", 2, 8); + assert(time_partitions.sum_of_pauses() == 8-2, "Incorrect"); + assert(time_partitions.longest_pause() == 8-2, "Incorrect"); + + assert(!iter.has_next(), "Too many elements"); + } + + static void two_pauses() { + TimePartitions time_partitions; + time_partitions.report_gc_phase_start("PausePhase1", 2); + time_partitions.report_gc_phase_end(3); + time_partitions.report_gc_phase_start("PausePhase2", 4); + time_partitions.report_gc_phase_end(6); + + TimePartitionPhasesIterator iter(&time_partitions); + + validate_pause_phase(iter.next(), 0, "PausePhase1", 2, 3); + validate_pause_phase(iter.next(), 0, "PausePhase2", 4, 6); + + assert(time_partitions.sum_of_pauses() == 3, "Incorrect"); + assert(time_partitions.longest_pause() == 2, "Incorrect"); + + assert(!iter.has_next(), "Too many elements"); + } + + static void one_sub_pause_phase() { + TimePartitions time_partitions; + time_partitions.report_gc_phase_start("PausePhase", 2); + time_partitions.report_gc_phase_start("SubPhase", 3); + time_partitions.report_gc_phase_end(4); + time_partitions.report_gc_phase_end(5); + + TimePartitionPhasesIterator iter(&time_partitions); + + validate_pause_phase(iter.next(), 0, "PausePhase", 2, 5); + validate_pause_phase(iter.next(), 1, "SubPhase", 3, 4); + + assert(time_partitions.sum_of_pauses() == 3, "Incorrect"); + assert(time_partitions.longest_pause() == 3, "Incorrect"); + + assert(!iter.has_next(), "Too many elements"); + } + + static void max_nested_pause_phases() { + TimePartitions time_partitions; + time_partitions.report_gc_phase_start("PausePhase", 2); + time_partitions.report_gc_phase_start("SubPhase1", 3); + time_partitions.report_gc_phase_start("SubPhase2", 4); + time_partitions.report_gc_phase_start("SubPhase3", 5); + time_partitions.report_gc_phase_end(6); + time_partitions.report_gc_phase_end(7); + time_partitions.report_gc_phase_end(8); + time_partitions.report_gc_phase_end(9); + + TimePartitionPhasesIterator iter(&time_partitions); + + validate_pause_phase(iter.next(), 0, "PausePhase", 2, 9); + validate_pause_phase(iter.next(), 1, "SubPhase1", 3, 8); + validate_pause_phase(iter.next(), 2, "SubPhase2", 4, 7); + validate_pause_phase(iter.next(), 3, "SubPhase3", 5, 6); + + assert(time_partitions.sum_of_pauses() == 7, "Incorrect"); + assert(time_partitions.longest_pause() == 7, "Incorrect"); + + assert(!iter.has_next(), "Too many elements"); + } + + static void many_sub_pause_phases() { + TimePartitions time_partitions; + time_partitions.report_gc_phase_start("PausePhase", 2); + + time_partitions.report_gc_phase_start("SubPhase1", 3); + time_partitions.report_gc_phase_end(4); + time_partitions.report_gc_phase_start("SubPhase2", 5); + time_partitions.report_gc_phase_end(6); + time_partitions.report_gc_phase_start("SubPhase3", 7); + time_partitions.report_gc_phase_end(8); + time_partitions.report_gc_phase_start("SubPhase4", 9); + time_partitions.report_gc_phase_end(10); + + time_partitions.report_gc_phase_end(11); + + TimePartitionPhasesIterator iter(&time_partitions); + + validate_pause_phase(iter.next(), 0, "PausePhase", 2, 11); + validate_pause_phase(iter.next(), 1, "SubPhase1", 3, 4); + validate_pause_phase(iter.next(), 1, "SubPhase2", 5, 6); + validate_pause_phase(iter.next(), 1, "SubPhase3", 7, 8); + validate_pause_phase(iter.next(), 1, "SubPhase4", 9, 10); + + assert(time_partitions.sum_of_pauses() == 9, "Incorrect"); + assert(time_partitions.longest_pause() == 9, "Incorrect"); + + assert(!iter.has_next(), "Too many elements"); + } + + static void many_sub_pause_phases2() { + TimePartitions time_partitions; + time_partitions.report_gc_phase_start("PausePhase", 2); + + time_partitions.report_gc_phase_start("SubPhase1", 3); + time_partitions.report_gc_phase_start("SubPhase11", 4); + time_partitions.report_gc_phase_end(5); + time_partitions.report_gc_phase_start("SubPhase12", 6); + time_partitions.report_gc_phase_end(7); + time_partitions.report_gc_phase_end(8); + time_partitions.report_gc_phase_start("SubPhase2", 9); + time_partitions.report_gc_phase_start("SubPhase21", 10); + time_partitions.report_gc_phase_end(11); + time_partitions.report_gc_phase_start("SubPhase22", 12); + time_partitions.report_gc_phase_end(13); + time_partitions.report_gc_phase_end(14); + time_partitions.report_gc_phase_start("SubPhase3", 15); + time_partitions.report_gc_phase_end(16); + + time_partitions.report_gc_phase_end(17); + + TimePartitionPhasesIterator iter(&time_partitions); + + validate_pause_phase(iter.next(), 0, "PausePhase", 2, 17); + validate_pause_phase(iter.next(), 1, "SubPhase1", 3, 8); + validate_pause_phase(iter.next(), 2, "SubPhase11", 4, 5); + validate_pause_phase(iter.next(), 2, "SubPhase12", 6, 7); + validate_pause_phase(iter.next(), 1, "SubPhase2", 9, 14); + validate_pause_phase(iter.next(), 2, "SubPhase21", 10, 11); + validate_pause_phase(iter.next(), 2, "SubPhase22", 12, 13); + validate_pause_phase(iter.next(), 1, "SubPhase3", 15, 16); + + assert(time_partitions.sum_of_pauses() == 15, "Incorrect"); + assert(time_partitions.longest_pause() == 15, "Incorrect"); + + assert(!iter.has_next(), "Too many elements"); + } +}; + +class GCTimerTest { +public: + static void all() { + gc_start(); + gc_end(); + } + + static void gc_start() { + GCTimer gc_timer; + gc_timer.register_gc_start(1); + + assert(gc_timer.gc_start() == 1, "Incorrect"); + } + + static void gc_end() { + GCTimer gc_timer; + gc_timer.register_gc_start(1); + gc_timer.register_gc_end(2); + + assert(gc_timer.gc_end() == 2, "Incorrect"); + } +}; + +void GCTimerAllTest::all() { + GCTimerTest::all(); + TimePartitionPhasesIteratorTest::all(); +} + +#endif diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/share/vm/gc_implementation/shared/gcTimer.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/src/share/vm/gc_implementation/shared/gcTimer.hpp Wed Jul 05 18:59:39 2017 +0200 @@ -0,0 +1,195 @@ +/* + * Copyright (c) 2012, 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. + * + */ + +#ifndef SHARE_VM_GC_IMPLEMENTATION_SHARED_GCTIMER_HPP +#define SHARE_VM_GC_IMPLEMENTATION_SHARED_GCTIMER_HPP + +#include "memory/allocation.hpp" +#include "prims/jni_md.h" +#include "utilities/macros.hpp" + +class ConcurrentPhase; +class GCPhase; +class PausePhase; + +template class GrowableArray; + +class PhaseVisitor { + public: + virtual void visit(GCPhase* phase) = 0; + virtual void visit(PausePhase* phase) { visit((GCPhase*)phase); } + virtual void visit(ConcurrentPhase* phase) { visit((GCPhase*)phase); } +}; + +class GCPhase { + const char* _name; + int _level; + jlong _start; + jlong _end; + + public: + void set_name(const char* name) { _name = name; } + const char* name() { return _name; } + + int level() { return _level; } + void set_level(int level) { _level = level; } + + jlong start() { return _start; } + void set_start(jlong time) { _start = time; } + + jlong end() { return _end; } + void set_end(jlong time) { _end = time; } + + virtual void accept(PhaseVisitor* visitor) = 0; +}; + +class PausePhase : public GCPhase { + public: + void accept(PhaseVisitor* visitor) { + visitor->visit(this); + } +}; + +class ConcurrentPhase : public GCPhase { + void accept(PhaseVisitor* visitor) { + visitor->visit(this); + } +}; + +class PhasesStack { + public: + // FIXME: Temporary set to 5 (used to be 4), since Reference processing needs it. + static const int PHASE_LEVELS = 5; + + private: + int _phase_indices[PHASE_LEVELS]; + int _next_phase_level; + + public: + PhasesStack() { clear(); } + void clear(); + + void push(int phase_index); + int pop(); + int count() const; +}; + +class TimePartitions { + static const int INITIAL_CAPACITY = 10; + + // Currently we only support pause phases. + GrowableArray* _phases; + PhasesStack _active_phases; + + jlong _sum_of_pauses; + jlong _longest_pause; + + public: + TimePartitions(); + ~TimePartitions(); + void clear(); + + void report_gc_phase_start(const char* name, jlong time); + void report_gc_phase_end(jlong time); + + int num_phases() const; + GCPhase* phase_at(int index) const; + + jlong sum_of_pauses(); + jlong longest_pause(); + + bool has_active_phases(); + private: + void update_statistics(GCPhase* phase); +}; + +class PhasesIterator { + public: + virtual bool has_next() = 0; + virtual GCPhase* next() = 0; +}; + +class GCTimer : public ResourceObj { + NOT_PRODUCT(friend class GCTimerTest;) + protected: + jlong _gc_start; + jlong _gc_end; + TimePartitions _time_partitions; + + public: + virtual void register_gc_start(jlong time); + virtual void register_gc_end(jlong time); + + void register_gc_phase_start(const char* name, jlong time); + void register_gc_phase_end(jlong time); + + jlong gc_start() { return _gc_start; } + jlong gc_end() { return _gc_end; } + + TimePartitions* time_partitions() { return &_time_partitions; } + + long longest_pause(); + long sum_of_pauses(); + + protected: + void register_gc_pause_start(const char* name, jlong time); + void register_gc_pause_end(jlong time); +}; + +class STWGCTimer : public GCTimer { + public: + virtual void register_gc_start(jlong time); + virtual void register_gc_end(jlong time); +}; + +class ConcurrentGCTimer : public GCTimer { + public: + void register_gc_pause_start(const char* name, jlong time); + void register_gc_pause_end(jlong time); +}; + +class TimePartitionPhasesIterator { + TimePartitions* _time_partitions; + int _next; + + public: + TimePartitionPhasesIterator(TimePartitions* time_partitions) : _time_partitions(time_partitions), _next(0) { } + + virtual bool has_next(); + virtual GCPhase* next(); +}; + + +/////////////// Unit tests /////////////// + +#ifndef PRODUCT + +class GCTimerAllTest { + public: + static void all(); +}; + +#endif + +#endif // SHARE_VM_GC_IMPLEMENTATION_SHARED_GCTIMER_HPP diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/share/vm/gc_implementation/shared/gcTrace.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/src/share/vm/gc_implementation/shared/gcTrace.cpp Wed Jul 05 18:59:39 2017 +0200 @@ -0,0 +1,207 @@ +/* + * Copyright (c) 2012, 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. + * + */ + +#include "precompiled.hpp" +#include "gc_implementation/shared/gcHeapSummary.hpp" +#include "gc_implementation/shared/gcTimer.hpp" +#include "gc_implementation/shared/gcTrace.hpp" +#include "gc_implementation/shared/copyFailedInfo.hpp" +#include "memory/heapInspection.hpp" +#include "memory/referenceProcessorStats.hpp" +#include "utilities/globalDefinitions.hpp" + +#if INCLUDE_ALL_GCS +#include "gc_implementation/g1/evacuationInfo.hpp" +#endif + +#define assert_unset_gc_id() assert(_shared_gc_info.id() == SharedGCInfo::UNSET_GCID, "GC already started?") +#define assert_set_gc_id() assert(_shared_gc_info.id() != SharedGCInfo::UNSET_GCID, "GC not started?") + +static jlong GCTracer_next_gc_id = 0; +static GCId create_new_gc_id() { + return GCTracer_next_gc_id++; +} + +void GCTracer::report_gc_start_impl(GCCause::Cause cause, jlong timestamp) { + assert_unset_gc_id(); + + GCId gc_id = create_new_gc_id(); + _shared_gc_info.set_id(gc_id); + _shared_gc_info.set_cause(cause); + _shared_gc_info.set_start_timestamp(timestamp); +} + +void GCTracer::report_gc_start(GCCause::Cause cause, jlong timestamp) { + assert_unset_gc_id(); + + report_gc_start_impl(cause, timestamp); +} + +bool GCTracer::has_reported_gc_start() const { + return _shared_gc_info.id() != SharedGCInfo::UNSET_GCID; +} + +void GCTracer::report_gc_end_impl(jlong timestamp, TimePartitions* time_partitions) { + assert_set_gc_id(); + + _shared_gc_info.set_sum_of_pauses(time_partitions->sum_of_pauses()); + _shared_gc_info.set_longest_pause(time_partitions->longest_pause()); + _shared_gc_info.set_end_timestamp(timestamp); + + send_phase_events(time_partitions); + send_garbage_collection_event(); +} + +void GCTracer::report_gc_end(jlong timestamp, TimePartitions* time_partitions) { + assert_set_gc_id(); + + report_gc_end_impl(timestamp, time_partitions); + + _shared_gc_info.set_id(SharedGCInfo::UNSET_GCID); +} + +void GCTracer::report_gc_reference_stats(const ReferenceProcessorStats& rps) const { + assert_set_gc_id(); + + send_reference_stats_event(REF_SOFT, rps.soft_count()); + send_reference_stats_event(REF_WEAK, rps.weak_count()); + send_reference_stats_event(REF_FINAL, rps.final_count()); + send_reference_stats_event(REF_PHANTOM, rps.phantom_count()); +} + +#if INCLUDE_SERVICES +void ObjectCountEventSenderClosure::do_cinfo(KlassInfoEntry* entry) { + if (should_send_event(entry)) { + send_event(entry); + } +} + +void ObjectCountEventSenderClosure::send_event(KlassInfoEntry* entry) { + _gc_tracer->send_object_count_after_gc_event(entry->klass(), entry->count(), + entry->words() * BytesPerWord); +} + +bool ObjectCountEventSenderClosure::should_send_event(KlassInfoEntry* entry) const { + double percentage_of_heap = ((double) entry->words()) / _total_size_in_words; + return percentage_of_heap > _size_threshold_percentage; +} + +void GCTracer::report_object_count_after_gc(BoolObjectClosure* is_alive_cl) { + assert_set_gc_id(); + + if (should_send_object_count_after_gc_event()) { + ResourceMark rm; + + KlassInfoTable cit(false); + if (!cit.allocation_failed()) { + HeapInspection hi(false, false, false, NULL); + hi.populate_table(&cit, is_alive_cl); + + ObjectCountEventSenderClosure event_sender(this, cit.size_of_instances_in_words()); + cit.iterate(&event_sender); + } + } +} +#endif + +void GCTracer::report_gc_heap_summary(GCWhen::Type when, const GCHeapSummary& heap_summary, const MetaspaceSummary& meta_space_summary) const { + assert_set_gc_id(); + + send_gc_heap_summary_event(when, heap_summary); + send_meta_space_summary_event(when, meta_space_summary); +} + +void YoungGCTracer::report_gc_end_impl(jlong timestamp, TimePartitions* time_partitions) { + assert_set_gc_id(); + assert(_tenuring_threshold != UNSET_TENURING_THRESHOLD, "Tenuring threshold has not been reported"); + + GCTracer::report_gc_end_impl(timestamp, time_partitions); + send_young_gc_event(); + + _tenuring_threshold = UNSET_TENURING_THRESHOLD; +} + +void YoungGCTracer::report_promotion_failed(const PromotionFailedInfo& pf_info) { + assert_set_gc_id(); + + send_promotion_failed_event(pf_info); +} + +void YoungGCTracer::report_tenuring_threshold(const uint tenuring_threshold) { + _tenuring_threshold = tenuring_threshold; +} + +void OldGCTracer::report_gc_end_impl(jlong timestamp, TimePartitions* time_partitions) { + assert_set_gc_id(); + + GCTracer::report_gc_end_impl(timestamp, time_partitions); + send_old_gc_event(); +} + +void ParallelOldTracer::report_gc_end_impl(jlong timestamp, TimePartitions* time_partitions) { + assert_set_gc_id(); + + OldGCTracer::report_gc_end_impl(timestamp, time_partitions); + send_parallel_old_event(); +} + +void ParallelOldTracer::report_dense_prefix(void* dense_prefix) { + assert_set_gc_id(); + + _parallel_old_gc_info.report_dense_prefix(dense_prefix); +} + +void OldGCTracer::report_concurrent_mode_failure() { + assert_set_gc_id(); + + send_concurrent_mode_failure_event(); +} + +#if INCLUDE_ALL_GCS +void G1NewTracer::report_yc_type(G1YCType type) { + assert_set_gc_id(); + + _g1_young_gc_info.set_type(type); +} + +void G1NewTracer::report_gc_end_impl(jlong timestamp, TimePartitions* time_partitions) { + assert_set_gc_id(); + + YoungGCTracer::report_gc_end_impl(timestamp, time_partitions); + send_g1_young_gc_event(); +} + +void G1NewTracer::report_evacuation_info(EvacuationInfo* info) { + assert_set_gc_id(); + + send_evacuation_info_event(info); +} + +void G1NewTracer::report_evacuation_failed(EvacuationFailedInfo& ef_info) { + assert_set_gc_id(); + + send_evacuation_failed_event(ef_info); + ef_info.reset(); +} +#endif diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/share/vm/gc_implementation/shared/gcTrace.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/src/share/vm/gc_implementation/shared/gcTrace.hpp Wed Jul 05 18:59:39 2017 +0200 @@ -0,0 +1,255 @@ +/* + * Copyright (c) 2012, 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. + * + */ + +#ifndef SHARE_VM_GC_IMPLEMENTATION_SHARED_GCTRACE_HPP +#define SHARE_VM_GC_IMPLEMENTATION_SHARED_GCTRACE_HPP + +#include "gc_interface/gcCause.hpp" +#include "gc_interface/gcName.hpp" +#include "gc_implementation/shared/gcWhen.hpp" +#include "gc_implementation/shared/copyFailedInfo.hpp" +#include "memory/allocation.hpp" +#include "memory/klassInfoClosure.hpp" +#include "memory/referenceType.hpp" +#if INCLUDE_ALL_GCS +#include "gc_implementation/g1/g1YCTypes.hpp" +#endif +#include "utilities/macros.hpp" + +typedef uint GCId; + +class EvacuationInfo; +class GCHeapSummary; +class MetaspaceSummary; +class PSHeapSummary; +class ReferenceProcessorStats; +class TimePartitions; +class BoolObjectClosure; + +class SharedGCInfo VALUE_OBJ_CLASS_SPEC { + static const jlong UNSET_TIMESTAMP = -1; + + public: + static const GCId UNSET_GCID = (GCId)-1; + + private: + GCId _id; + GCName _name; + GCCause::Cause _cause; + jlong _start_timestamp; + jlong _end_timestamp; + jlong _sum_of_pauses; + jlong _longest_pause; + + public: + SharedGCInfo(GCName name) : _id(UNSET_GCID), _name(name), _cause(GCCause::_last_gc_cause), + _start_timestamp(UNSET_TIMESTAMP), _end_timestamp(UNSET_TIMESTAMP), _sum_of_pauses(0), _longest_pause(0) {} + + void set_id(GCId id) { _id = id; } + GCId id() const { return _id; } + + void set_start_timestamp(jlong timestamp) { _start_timestamp = timestamp; } + jlong start_timestamp() const { return _start_timestamp; } + + void set_end_timestamp(jlong timestamp) { _end_timestamp = timestamp; } + jlong end_timestamp() const { return _end_timestamp; } + + void set_name(GCName name) { _name = name; } + GCName name() const { return _name; } + + void set_cause(GCCause::Cause cause) { _cause = cause; } + GCCause::Cause cause() const { return _cause; } + + void set_sum_of_pauses(jlong duration) { _sum_of_pauses = duration; } + jlong sum_of_pauses() const { return _sum_of_pauses; } + + void set_longest_pause(jlong duration) { _longest_pause = duration; } + jlong longest_pause() const { return _longest_pause; } +}; + +class ParallelOldGCInfo VALUE_OBJ_CLASS_SPEC { + void* _dense_prefix; + public: + ParallelOldGCInfo() : _dense_prefix(NULL) {} + void report_dense_prefix(void* addr) { + _dense_prefix = addr; + } + void* dense_prefix() const { return _dense_prefix; } +}; + +#if INCLUDE_ALL_GCS + +class G1YoungGCInfo VALUE_OBJ_CLASS_SPEC { + G1YCType _type; + public: + G1YoungGCInfo() : _type(G1YCTypeEndSentinel) {} + void set_type(G1YCType type) { + _type = type; + } + G1YCType type() const { return _type; } +}; + +#endif // INCLUDE_ALL_GCS + +class GCTracer : public ResourceObj { + friend class ObjectCountEventSenderClosure; + protected: + SharedGCInfo _shared_gc_info; + + public: + void report_gc_start(GCCause::Cause cause, jlong timestamp); + void report_gc_end(jlong timestamp, TimePartitions* time_partitions); + void report_gc_heap_summary(GCWhen::Type when, const GCHeapSummary& heap_summary, const MetaspaceSummary& meta_space_summary) const; + void report_gc_reference_stats(const ReferenceProcessorStats& rp) const; + void report_object_count_after_gc(BoolObjectClosure* object_filter) NOT_SERVICES_RETURN; + + bool has_reported_gc_start() const; + + protected: + GCTracer(GCName name) : _shared_gc_info(name) {} + virtual void report_gc_start_impl(GCCause::Cause cause, jlong timestamp); + virtual void report_gc_end_impl(jlong timestamp, TimePartitions* time_partitions); + + private: + void send_garbage_collection_event() const; + void send_gc_heap_summary_event(GCWhen::Type when, const GCHeapSummary& heap_summary) const; + void send_meta_space_summary_event(GCWhen::Type when, const MetaspaceSummary& meta_space_summary) const; + void send_reference_stats_event(ReferenceType type, size_t count) const; + void send_phase_events(TimePartitions* time_partitions) const; + void send_object_count_after_gc_event(Klass* klass, jlong count, julong total_size) const NOT_SERVICES_RETURN; + bool should_send_object_count_after_gc_event() const; +}; + +class ObjectCountEventSenderClosure : public KlassInfoClosure { + GCTracer* _gc_tracer; + const double _size_threshold_percentage; + const size_t _total_size_in_words; + public: + ObjectCountEventSenderClosure(GCTracer* gc_tracer, size_t total_size_in_words) : + _gc_tracer(gc_tracer), + _size_threshold_percentage(ObjectCountCutOffPercent / 100), + _total_size_in_words(total_size_in_words) + {} + virtual void do_cinfo(KlassInfoEntry* entry); + protected: + virtual void send_event(KlassInfoEntry* entry); + private: + bool should_send_event(KlassInfoEntry* entry) const; +}; + +class YoungGCTracer : public GCTracer { + static const uint UNSET_TENURING_THRESHOLD = (uint) -1; + + uint _tenuring_threshold; + + protected: + YoungGCTracer(GCName name) : GCTracer(name), _tenuring_threshold(UNSET_TENURING_THRESHOLD) {} + virtual void report_gc_end_impl(jlong timestamp, TimePartitions* time_partitions); + + public: + void report_promotion_failed(const PromotionFailedInfo& pf_info); + void report_tenuring_threshold(const uint tenuring_threshold); + + private: + void send_young_gc_event() const; + void send_promotion_failed_event(const PromotionFailedInfo& pf_info) const; +}; + +class OldGCTracer : public GCTracer { + protected: + OldGCTracer(GCName name) : GCTracer(name) {} + virtual void report_gc_end_impl(jlong timestamp, TimePartitions* time_partitions); + + public: + void report_concurrent_mode_failure(); + + private: + void send_old_gc_event() const; + void send_concurrent_mode_failure_event(); +}; + +class ParallelOldTracer : public OldGCTracer { + ParallelOldGCInfo _parallel_old_gc_info; + + public: + ParallelOldTracer() : OldGCTracer(ParallelOld) {} + void report_dense_prefix(void* dense_prefix); + + protected: + void report_gc_end_impl(jlong timestamp, TimePartitions* time_partitions); + + private: + void send_parallel_old_event() const; +}; + +class SerialOldTracer : public OldGCTracer { + public: + SerialOldTracer() : OldGCTracer(SerialOld) {} +}; + +class ParallelScavengeTracer : public YoungGCTracer { + public: + ParallelScavengeTracer() : YoungGCTracer(ParallelScavenge) {} +}; + +class DefNewTracer : public YoungGCTracer { + public: + DefNewTracer() : YoungGCTracer(DefNew) {} +}; + +class ParNewTracer : public YoungGCTracer { + public: + ParNewTracer() : YoungGCTracer(ParNew) {} +}; + +#if INCLUDE_ALL_GCS +class G1NewTracer : public YoungGCTracer { + G1YoungGCInfo _g1_young_gc_info; + + public: + G1NewTracer() : YoungGCTracer(G1New) {} + + void report_yc_type(G1YCType type); + void report_gc_end_impl(jlong timestamp, TimePartitions* time_partitions); + void report_evacuation_info(EvacuationInfo* info); + void report_evacuation_failed(EvacuationFailedInfo& ef_info); + + private: + void send_g1_young_gc_event(); + void send_evacuation_info_event(EvacuationInfo* info); + void send_evacuation_failed_event(const EvacuationFailedInfo& ef_info) const; +}; +#endif + +class CMSTracer : public OldGCTracer { + public: + CMSTracer() : OldGCTracer(ConcurrentMarkSweep) {} +}; + +class G1OldTracer : public OldGCTracer { + public: + G1OldTracer() : OldGCTracer(G1Old) {} +}; + +#endif // SHARE_VM_GC_IMPLEMENTATION_SHARED_GCTRACE_HPP diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/share/vm/gc_implementation/shared/gcTraceSend.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/src/share/vm/gc_implementation/shared/gcTraceSend.cpp Wed Jul 05 18:59:39 2017 +0200 @@ -0,0 +1,318 @@ +/* + * Copyright (c) 2012, 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. + * + */ + +#include "precompiled.hpp" +#include "gc_implementation/shared/gcHeapSummary.hpp" +#include "gc_implementation/shared/gcTimer.hpp" +#include "gc_implementation/shared/gcTrace.hpp" +#include "gc_implementation/shared/gcWhen.hpp" +#include "gc_implementation/shared/copyFailedInfo.hpp" +#include "trace/tracing.hpp" +#include "trace/traceBackend.hpp" +#if INCLUDE_ALL_GCS +#include "gc_implementation/g1/evacuationInfo.hpp" +#include "gc_implementation/g1/g1YCTypes.hpp" +#endif + +// All GC dependencies against the trace framework is contained within this file. + +typedef uintptr_t TraceAddress; + +void GCTracer::send_garbage_collection_event() const { + EventGCGarbageCollection event(UNTIMED); + if (event.should_commit()) { + event.set_gcId(_shared_gc_info.id()); + event.set_name(_shared_gc_info.name()); + event.set_cause((u2) _shared_gc_info.cause()); + event.set_sumOfPauses(_shared_gc_info.sum_of_pauses()); + event.set_longestPause(_shared_gc_info.longest_pause()); + event.set_starttime(_shared_gc_info.start_timestamp()); + event.set_endtime(_shared_gc_info.end_timestamp()); + event.commit(); + } +} + +void GCTracer::send_reference_stats_event(ReferenceType type, size_t count) const { + EventGCReferenceStatistics e; + if (e.should_commit()) { + e.set_gcId(_shared_gc_info.id()); + e.set_type((u1)type); + e.set_count(count); + e.commit(); + } +} + +void ParallelOldTracer::send_parallel_old_event() const { + EventGCParallelOld e(UNTIMED); + if (e.should_commit()) { + e.set_gcId(_shared_gc_info.id()); + e.set_densePrefix((TraceAddress)_parallel_old_gc_info.dense_prefix()); + e.set_starttime(_shared_gc_info.start_timestamp()); + e.set_endtime(_shared_gc_info.end_timestamp()); + e.commit(); + } +} + +void YoungGCTracer::send_young_gc_event() const { + EventGCYoungGarbageCollection e(UNTIMED); + if (e.should_commit()) { + e.set_gcId(_shared_gc_info.id()); + e.set_tenuringThreshold(_tenuring_threshold); + e.set_starttime(_shared_gc_info.start_timestamp()); + e.set_endtime(_shared_gc_info.end_timestamp()); + e.commit(); + } +} + +void OldGCTracer::send_old_gc_event() const { + EventGCOldGarbageCollection e(UNTIMED); + if (e.should_commit()) { + e.set_gcId(_shared_gc_info.id()); + e.set_starttime(_shared_gc_info.start_timestamp()); + e.set_endtime(_shared_gc_info.end_timestamp()); + e.commit(); + } +} + +static TraceStructCopyFailed to_trace_struct(const CopyFailedInfo& cf_info) { + TraceStructCopyFailed failed_info; + failed_info.set_objectCount(cf_info.failed_count()); + failed_info.set_firstSize(cf_info.first_size()); + failed_info.set_smallestSize(cf_info.smallest_size()); + failed_info.set_totalSize(cf_info.total_size()); + return failed_info; +} + +void YoungGCTracer::send_promotion_failed_event(const PromotionFailedInfo& pf_info) const { + EventPromotionFailed e; + if (e.should_commit()) { + e.set_gcId(_shared_gc_info.id()); + e.set_data(to_trace_struct(pf_info)); + e.set_thread(pf_info.thread()->thread_id()); + e.commit(); + } +} + +// Common to CMS and G1 +void OldGCTracer::send_concurrent_mode_failure_event() { + EventConcurrentModeFailure e; + if (e.should_commit()) { + e.set_gcId(_shared_gc_info.id()); + e.commit(); + } +} + +#if INCLUDE_SERVICES +void GCTracer::send_object_count_after_gc_event(Klass* klass, jlong count, julong total_size) const { + EventObjectCountAfterGC e; + if (e.should_commit()) { + e.set_gcId(_shared_gc_info.id()); + e.set_class(klass); + e.set_count(count); + e.set_totalSize(total_size); + e.commit(); + } +} +#endif + +bool GCTracer::should_send_object_count_after_gc_event() const { +#if INCLUDE_TRACE + return Tracing::is_event_enabled(EventObjectCountAfterGC::eventId); +#else + return false; +#endif +} + +#if INCLUDE_ALL_GCS +void G1NewTracer::send_g1_young_gc_event() { + EventGCG1GarbageCollection e(UNTIMED); + if (e.should_commit()) { + e.set_gcId(_shared_gc_info.id()); + e.set_type(_g1_young_gc_info.type()); + e.set_starttime(_shared_gc_info.start_timestamp()); + e.set_endtime(_shared_gc_info.end_timestamp()); + e.commit(); + } +} + +void G1NewTracer::send_evacuation_info_event(EvacuationInfo* info) { + EventEvacuationInfo e; + if (e.should_commit()) { + e.set_gcId(_shared_gc_info.id()); + e.set_cSetRegions(info->collectionset_regions()); + e.set_cSetUsedBefore(info->collectionset_used_before()); + e.set_cSetUsedAfter(info->collectionset_used_after()); + e.set_allocationRegions(info->allocation_regions()); + e.set_allocRegionsUsedBefore(info->alloc_regions_used_before()); + e.set_allocRegionsUsedAfter(info->alloc_regions_used_before() + info->bytes_copied()); + e.set_bytesCopied(info->bytes_copied()); + e.set_regionsFreed(info->regions_freed()); + e.commit(); + } +} + +void G1NewTracer::send_evacuation_failed_event(const EvacuationFailedInfo& ef_info) const { + EventEvacuationFailed e; + if (e.should_commit()) { + e.set_gcId(_shared_gc_info.id()); + e.set_data(to_trace_struct(ef_info)); + e.commit(); + } +} +#endif + +static TraceStructVirtualSpace to_trace_struct(const VirtualSpaceSummary& summary) { + TraceStructVirtualSpace space; + space.set_start((TraceAddress)summary.start()); + space.set_committedEnd((TraceAddress)summary.committed_end()); + space.set_committedSize(summary.committed_size()); + space.set_reservedEnd((TraceAddress)summary.reserved_end()); + space.set_reservedSize(summary.reserved_size()); + return space; +} + +static TraceStructObjectSpace to_trace_struct(const SpaceSummary& summary) { + TraceStructObjectSpace space; + space.set_start((TraceAddress)summary.start()); + space.set_end((TraceAddress)summary.end()); + space.set_used(summary.used()); + space.set_size(summary.size()); + return space; +} + +class GCHeapSummaryEventSender : public GCHeapSummaryVisitor { + GCId _id; + GCWhen::Type _when; + public: + GCHeapSummaryEventSender(GCId id, GCWhen::Type when) : _id(id), _when(when) {} + + void visit(const GCHeapSummary* heap_summary) const { + const VirtualSpaceSummary& heap_space = heap_summary->heap(); + + EventGCHeapSummary e; + if (e.should_commit()) { + e.set_gcId(_id); + e.set_when((u1)_when); + e.set_heapSpace(to_trace_struct(heap_space)); + e.set_heapUsed(heap_summary->used()); + e.commit(); + } + } + + void visit(const PSHeapSummary* ps_heap_summary) const { + visit((GCHeapSummary*)ps_heap_summary); + + const VirtualSpaceSummary& old_summary = ps_heap_summary->old(); + const SpaceSummary& old_space = ps_heap_summary->old_space(); + const VirtualSpaceSummary& young_summary = ps_heap_summary->young(); + const SpaceSummary& eden_space = ps_heap_summary->eden(); + const SpaceSummary& from_space = ps_heap_summary->from(); + const SpaceSummary& to_space = ps_heap_summary->to(); + + EventPSHeapSummary e; + if (e.should_commit()) { + e.set_gcId(_id); + e.set_when((u1)_when); + + e.set_oldSpace(to_trace_struct(ps_heap_summary->old())); + e.set_oldObjectSpace(to_trace_struct(ps_heap_summary->old_space())); + e.set_youngSpace(to_trace_struct(ps_heap_summary->young())); + e.set_edenSpace(to_trace_struct(ps_heap_summary->eden())); + e.set_fromSpace(to_trace_struct(ps_heap_summary->from())); + e.set_toSpace(to_trace_struct(ps_heap_summary->to())); + e.commit(); + } + } +}; + +void GCTracer::send_gc_heap_summary_event(GCWhen::Type when, const GCHeapSummary& heap_summary) const { + GCHeapSummaryEventSender visitor(_shared_gc_info.id(), when); + heap_summary.accept(&visitor); +} + +static TraceStructMetaspaceSizes to_trace_struct(const MetaspaceSizes& sizes) { + TraceStructMetaspaceSizes meta_sizes; + + meta_sizes.set_capacity(sizes.capacity()); + meta_sizes.set_used(sizes.used()); + meta_sizes.set_reserved(sizes.reserved()); + + return meta_sizes; +} + +void GCTracer::send_meta_space_summary_event(GCWhen::Type when, const MetaspaceSummary& meta_space_summary) const { + EventMetaspaceSummary e; + if (e.should_commit()) { + e.set_gcId(_shared_gc_info.id()); + e.set_when((u1) when); + e.set_metaspace(to_trace_struct(meta_space_summary.meta_space())); + e.set_dataSpace(to_trace_struct(meta_space_summary.data_space())); + e.set_classSpace(to_trace_struct(meta_space_summary.class_space())); + e.commit(); + } +} + +class PhaseSender : public PhaseVisitor { + GCId _gc_id; + public: + PhaseSender(GCId gc_id) : _gc_id(gc_id) {} + + template + void send_phase(PausePhase* pause) { + T event(UNTIMED); + if (event.should_commit()) { + event.set_gcId(_gc_id); + event.set_name(pause->name()); + event.set_starttime(pause->start()); + event.set_endtime(pause->end()); + event.commit(); + } + } + + void visit(GCPhase* pause) { ShouldNotReachHere(); } + void visit(ConcurrentPhase* pause) { Unimplemented(); } + void visit(PausePhase* pause) { + assert(PhasesStack::PHASE_LEVELS == 5, "Need more event types"); + + switch (pause->level()) { + case 0: send_phase(pause); break; + case 1: send_phase(pause); break; + case 2: send_phase(pause); break; + case 3: send_phase(pause); break; + default: /* Ignore sending this phase */ break; + } + } + +#undef send_phase +}; + +void GCTracer::send_phase_events(TimePartitions* time_partitions) const { + PhaseSender phase_reporter(_shared_gc_info.id()); + + TimePartitionPhasesIterator iter(time_partitions); + while (iter.has_next()) { + GCPhase* phase = iter.next(); + phase->accept(&phase_reporter); + } +} diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/share/vm/gc_implementation/shared/gcTraceTime.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/src/share/vm/gc_implementation/shared/gcTraceTime.cpp Wed Jul 05 18:59:39 2017 +0200 @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2012, 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. + * + */ + +#include "precompiled.hpp" +#include "gc_implementation/shared/gcTimer.hpp" +#include "gc_implementation/shared/gcTraceTime.hpp" +#include "runtime/globals.hpp" +#include "runtime/os.hpp" +#include "runtime/safepoint.hpp" +#include "runtime/thread.inline.hpp" +#include "runtime/timer.hpp" +#include "utilities/ostream.hpp" + + +GCTraceTime::GCTraceTime(const char* title, bool doit, bool print_cr, GCTimer* timer) : + _title(title), _doit(doit), _print_cr(print_cr), _timer(timer) { + if (_doit || _timer != NULL) { + _start_counter = os::elapsed_counter(); + } + + if (_timer != NULL) { + assert(SafepointSynchronize::is_at_safepoint(), "Tracing currently only supported at safepoints"); + assert(Thread::current()->is_VM_thread(), "Tracing currently only supported from the VM thread"); + + _timer->register_gc_phase_start(title, _start_counter); + } + + if (_doit) { + if (PrintGCTimeStamps) { + gclog_or_tty->stamp(); + gclog_or_tty->print(": "); + } + gclog_or_tty->print("[%s", title); + gclog_or_tty->flush(); + } +} + +GCTraceTime::~GCTraceTime() { + jlong stop_counter = 0; + + if (_doit || _timer != NULL) { + stop_counter = os::elapsed_counter(); + } + + if (_timer != NULL) { + _timer->register_gc_phase_end(stop_counter); + } + + if (_doit) { + double seconds = TimeHelper::counter_to_seconds(stop_counter - _start_counter); + if (_print_cr) { + gclog_or_tty->print_cr(", %3.7f secs]", seconds); + } else { + gclog_or_tty->print(", %3.7f secs]", seconds); + } + gclog_or_tty->flush(); + } +} diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/share/vm/gc_implementation/shared/gcTraceTime.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/src/share/vm/gc_implementation/shared/gcTraceTime.hpp Wed Jul 05 18:59:39 2017 +0200 @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2012, 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. + * + */ + +#ifndef SHARE_VM_GC_IMPLEMENTATION_SHARED_GCTRACETIME_HPP +#define SHARE_VM_GC_IMPLEMENTATION_SHARED_GCTRACETIME_HPP + +#include "prims/jni_md.h" + +class GCTimer; + +class GCTraceTime { + const char* _title; + bool _doit; + bool _print_cr; + GCTimer* _timer; + jlong _start_counter; + + public: + GCTraceTime(const char* title, bool doit, bool print_cr, GCTimer* timer); + ~GCTraceTime(); +}; + +#endif // SHARE_VM_GC_IMPLEMENTATION_SHARED_GCTRACETIME_HPP diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/share/vm/gc_implementation/shared/gcWhen.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/src/share/vm/gc_implementation/shared/gcWhen.hpp Wed Jul 05 18:59:39 2017 +0200 @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2012, 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. + * + */ + +#ifndef SHARE_VM_GC_IMPLEMENTATION_SHARED_GCWHEN_HPP +#define SHARE_VM_GC_IMPLEMENTATION_SHARED_GCWHEN_HPP + +#include "memory/allocation.hpp" +#include "utilities/debug.hpp" + +class GCWhen : AllStatic { + public: + enum Type { + BeforeGC, + AfterGC, + GCWhenEndSentinel + }; + + static const char* to_string(GCWhen::Type when) { + switch (when) { + case BeforeGC: return "Before GC"; + case AfterGC: return "After GC"; + default: ShouldNotReachHere(); return NULL; + } + } +}; + +#endif // SHARE_VM_GC_IMPLEMENTATION_SHARED_GCWHEN_HPP diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/share/vm/gc_implementation/shared/markSweep.cpp --- a/hotspot/src/share/vm/gc_implementation/shared/markSweep.cpp Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/src/share/vm/gc_implementation/shared/markSweep.cpp Wed Jul 05 18:59:39 2017 +0200 @@ -24,6 +24,8 @@ #include "precompiled.hpp" #include "compiler/compileBroker.hpp" +#include "gc_implementation/shared/gcTimer.hpp" +#include "gc_implementation/shared/gcTrace.hpp" #include "gc_implementation/shared/markSweep.inline.hpp" #include "gc_interface/collectedHeap.inline.hpp" #include "oops/methodData.hpp" @@ -41,6 +43,8 @@ size_t MarkSweep::_preserved_count_max = 0; PreservedMark* MarkSweep::_preserved_marks = NULL; ReferenceProcessor* MarkSweep::_ref_processor = NULL; +STWGCTimer* MarkSweep::_gc_timer = NULL; +SerialOldTracer* MarkSweep::_gc_tracer = NULL; MarkSweep::FollowRootClosure MarkSweep::follow_root_closure; CodeBlobToOopClosure MarkSweep::follow_code_root_closure(&MarkSweep::follow_root_closure, /*do_marking=*/ true); @@ -173,7 +177,10 @@ void MarkSweep::KeepAliveClosure::do_oop(oop* p) { MarkSweep::KeepAliveClosure::do_oop_work(p); } void MarkSweep::KeepAliveClosure::do_oop(narrowOop* p) { MarkSweep::KeepAliveClosure::do_oop_work(p); } -void marksweep_init() { /* empty */ } +void marksweep_init() { + MarkSweep::_gc_timer = new (ResourceObj::C_HEAP, mtGC) STWGCTimer(); + MarkSweep::_gc_tracer = new (ResourceObj::C_HEAP, mtGC) SerialOldTracer(); +} #ifndef PRODUCT diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/share/vm/gc_implementation/shared/markSweep.hpp --- a/hotspot/src/share/vm/gc_implementation/shared/markSweep.hpp Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/src/share/vm/gc_implementation/shared/markSweep.hpp Wed Jul 05 18:59:39 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -36,6 +36,8 @@ class ReferenceProcessor; class DataLayout; +class SerialOldTracer; +class STWGCTimer; // MarkSweep takes care of global mark-compact garbage collection for a // GenCollectedHeap using a four-phase pointer forwarding algorithm. All @@ -128,6 +130,9 @@ // Reference processing (used in ...follow_contents) static ReferenceProcessor* _ref_processor; + static STWGCTimer* _gc_timer; + static SerialOldTracer* _gc_tracer; + // Non public closures static KeepAliveClosure keep_alive; @@ -151,6 +156,9 @@ // Reference Processing static ReferenceProcessor* const ref_processor() { return _ref_processor; } + static STWGCTimer* gc_timer() { return _gc_timer; } + static SerialOldTracer* gc_tracer() { return _gc_tracer; } + // Call backs for marking static void mark_object(oop obj); // Mark pointer and follow contents. Empty marking stack afterwards. diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/share/vm/gc_implementation/shared/vmGCOperations.cpp --- a/hotspot/src/share/vm/gc_implementation/shared/vmGCOperations.cpp Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/src/share/vm/gc_implementation/shared/vmGCOperations.cpp Wed Jul 05 18:59:39 2017 +0200 @@ -145,32 +145,37 @@ return false; } +bool VM_GC_HeapInspection::collect() { + if (GC_locker::is_active()) { + return false; + } + Universe::heap()->collect_as_vm_thread(GCCause::_heap_inspection); + return true; +} + void VM_GC_HeapInspection::doit() { HandleMark hm; - CollectedHeap* ch = Universe::heap(); - ch->ensure_parsability(false); // must happen, even if collection does - // not happen (e.g. due to GC_locker) + Universe::heap()->ensure_parsability(false); // must happen, even if collection does + // not happen (e.g. due to GC_locker) + // or _full_gc being false if (_full_gc) { - // The collection attempt below would be skipped anyway if - // the gc locker is held. The following dump may then be a tad - // misleading to someone expecting only live objects to show - // up in the dump (see CR 6944195). Just issue a suitable warning - // in that case and do not attempt to do a collection. - // The latter is a subtle point, because even a failed attempt - // to GC will, in fact, induce one in the future, which we - // probably want to avoid in this case because the GC that we may - // be about to attempt holds value for us only - // if it happens now and not if it happens in the eventual - // future. - if (GC_locker::is_active()) { + if (!collect()) { + // The collection attempt was skipped because the gc locker is held. + // The following dump may then be a tad misleading to someone expecting + // only live objects to show up in the dump (see CR 6944195). Just issue + // a suitable warning in that case and do not attempt to do a collection. + // The latter is a subtle point, because even a failed attempt + // to GC will, in fact, induce one in the future, which we + // probably want to avoid in this case because the GC that we may + // be about to attempt holds value for us only + // if it happens now and not if it happens in the eventual + // future. warning("GC locker is held; pre-dump GC was skipped"); - } else { - ch->collect_as_vm_thread(GCCause::_heap_inspection); } } HeapInspection inspect(_csv_format, _print_help, _print_class_stats, _columns); - inspect.heap_inspection(_out, _need_prologue /* need_prologue */); + inspect.heap_inspection(_out); } diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/share/vm/gc_implementation/shared/vmGCOperations.hpp --- a/hotspot/src/share/vm/gc_implementation/shared/vmGCOperations.hpp Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/src/share/vm/gc_implementation/shared/vmGCOperations.hpp Wed Jul 05 18:59:39 2017 +0200 @@ -129,21 +129,18 @@ private: outputStream* _out; bool _full_gc; - bool _need_prologue; bool _csv_format; // "comma separated values" format for spreadsheet. bool _print_help; bool _print_class_stats; const char* _columns; public: - VM_GC_HeapInspection(outputStream* out, bool request_full_gc, - bool need_prologue) : + VM_GC_HeapInspection(outputStream* out, bool request_full_gc) : VM_GC_Operation(0 /* total collections, dummy, ignored */, GCCause::_heap_inspection /* GC Cause */, 0 /* total full collections, dummy, ignored */, request_full_gc) { _out = out; _full_gc = request_full_gc; - _need_prologue = need_prologue; _csv_format = false; _print_help = false; _print_class_stats = false; @@ -159,6 +156,8 @@ void set_print_help(bool value) {_print_help = value;} void set_print_class_stats(bool value) {_print_class_stats = value;} void set_columns(const char* value) {_columns = value;} + protected: + bool collect(); }; diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/share/vm/gc_interface/allocTracer.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/src/share/vm/gc_interface/allocTracer.cpp Wed Jul 05 18:59:39 2017 +0200 @@ -0,0 +1,48 @@ +/* + * 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. + * + */ + +#include "precompiled.hpp" +#include "gc_interface/allocTracer.hpp" +#include "trace/tracing.hpp" +#include "runtime/handles.hpp" +#include "utilities/globalDefinitions.hpp" + +void AllocTracer::send_allocation_outside_tlab_event(KlassHandle klass, size_t alloc_size) { + EventAllocObjectOutsideTLAB event; + if (event.should_commit()) { + event.set_class(klass()); + event.set_allocationSize(alloc_size); + event.commit(); + } +} + +void AllocTracer::send_allocation_in_new_tlab_event(KlassHandle klass, size_t tlab_size, size_t alloc_size) { + EventAllocObjectInNewTLAB event; + if (event.should_commit()) { + event.set_class(klass()); + event.set_allocationSize(alloc_size); + event.set_tlabSize(tlab_size); + event.commit(); + } +} diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/share/vm/gc_interface/allocTracer.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/src/share/vm/gc_interface/allocTracer.hpp Wed Jul 05 18:59:39 2017 +0200 @@ -0,0 +1,37 @@ +/* + * 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. + * + */ + +#ifndef SHARE_VM_GC_INTERFACE_ALLOCTRACER_HPP +#define SHARE_VM_GC_INTERFACE_ALLOCTRACER_HPP + +#include "memory/allocation.hpp" +#include "runtime/handles.hpp" + +class AllocTracer : AllStatic { + public: + static void send_allocation_outside_tlab_event(KlassHandle klass, size_t alloc_size); + static void send_allocation_in_new_tlab_event(KlassHandle klass, size_t tlab_size, size_t alloc_size); +}; + +#endif /* SHARE_VM_GC_INTERFACE_ALLOCTRACER_HPP */ diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/share/vm/gc_interface/collectedHeap.cpp --- a/hotspot/src/share/vm/gc_interface/collectedHeap.cpp Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/src/share/vm/gc_interface/collectedHeap.cpp Wed Jul 05 18:59:39 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2012, 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 @@ -24,9 +24,15 @@ #include "precompiled.hpp" #include "classfile/systemDictionary.hpp" +#include "gc_implementation/shared/gcHeapSummary.hpp" +#include "gc_implementation/shared/gcTrace.hpp" +#include "gc_implementation/shared/gcTraceTime.hpp" +#include "gc_implementation/shared/gcWhen.hpp" #include "gc_implementation/shared/vmGCOperations.hpp" +#include "gc_interface/allocTracer.hpp" #include "gc_interface/collectedHeap.hpp" #include "gc_interface/collectedHeap.inline.hpp" +#include "memory/metaspace.hpp" #include "oops/oop.inline.hpp" #include "oops/instanceMirrorKlass.hpp" #include "runtime/init.hpp" @@ -65,11 +71,71 @@ } } +VirtualSpaceSummary CollectedHeap::create_heap_space_summary() { + size_t capacity_in_words = capacity() / HeapWordSize; + + return VirtualSpaceSummary( + reserved_region().start(), reserved_region().start() + capacity_in_words, reserved_region().end()); +} + +GCHeapSummary CollectedHeap::create_heap_summary() { + VirtualSpaceSummary heap_space = create_heap_space_summary(); + return GCHeapSummary(heap_space, used()); +} + +MetaspaceSummary CollectedHeap::create_metaspace_summary() { + const MetaspaceSizes meta_space( + 0, /*MetaspaceAux::capacity_in_bytes(),*/ + 0, /*MetaspaceAux::used_in_bytes(),*/ + MetaspaceAux::reserved_in_bytes()); + const MetaspaceSizes data_space( + 0, /*MetaspaceAux::capacity_in_bytes(Metaspace::NonClassType),*/ + 0, /*MetaspaceAux::used_in_bytes(Metaspace::NonClassType),*/ + MetaspaceAux::reserved_in_bytes(Metaspace::NonClassType)); + const MetaspaceSizes class_space( + 0, /*MetaspaceAux::capacity_in_bytes(Metaspace::ClassType),*/ + 0, /*MetaspaceAux::used_in_bytes(Metaspace::ClassType),*/ + MetaspaceAux::reserved_in_bytes(Metaspace::ClassType)); + + return MetaspaceSummary(meta_space, data_space, class_space); +} + +void CollectedHeap::print_heap_before_gc() { + if (PrintHeapAtGC) { + Universe::print_heap_before_gc(); + } + if (_gc_heap_log != NULL) { + _gc_heap_log->log_heap_before(); + } +} + +void CollectedHeap::print_heap_after_gc() { + if (PrintHeapAtGC) { + Universe::print_heap_after_gc(); + } + if (_gc_heap_log != NULL) { + _gc_heap_log->log_heap_after(); + } +} + +void CollectedHeap::trace_heap(GCWhen::Type when, GCTracer* gc_tracer) { + const GCHeapSummary& heap_summary = create_heap_summary(); + const MetaspaceSummary& metaspace_summary = create_metaspace_summary(); + gc_tracer->report_gc_heap_summary(when, heap_summary, metaspace_summary); +} + +void CollectedHeap::trace_heap_before_gc(GCTracer* gc_tracer) { + trace_heap(GCWhen::BeforeGC, gc_tracer); +} + +void CollectedHeap::trace_heap_after_gc(GCTracer* gc_tracer) { + trace_heap(GCWhen::AfterGC, gc_tracer); +} + // Memory state functions. CollectedHeap::CollectedHeap() : _n_par_threads(0) - { const size_t max_len = size_t(arrayOopDesc::max_array_length(T_INT)); const size_t elements_per_word = HeapWordSize / sizeof(jint); @@ -185,7 +251,7 @@ } #endif -HeapWord* CollectedHeap::allocate_from_tlab_slow(Thread* thread, size_t size) { +HeapWord* CollectedHeap::allocate_from_tlab_slow(KlassHandle klass, Thread* thread, size_t size) { // Retain tlab and allocate object in shared space if // the amount free in the tlab is too large to discard. @@ -209,6 +275,9 @@ if (obj == NULL) { return NULL; } + + AllocTracer::send_allocation_in_new_tlab_event(klass, new_tlab_size * HeapWordSize, size * HeapWordSize); + if (ZeroTLAB) { // ..and clear it. Copy::zero_to_words(obj, new_tlab_size); @@ -458,28 +527,28 @@ } } -void CollectedHeap::pre_full_gc_dump() { +void CollectedHeap::pre_full_gc_dump(GCTimer* timer) { if (HeapDumpBeforeFullGC) { - TraceTime tt("Heap Dump (before full gc): ", PrintGCDetails, false, gclog_or_tty); + GCTraceTime tt("Heap Dump (before full gc): ", PrintGCDetails, false, timer); // We are doing a "major" collection and a heap dump before // major collection has been requested. HeapDumper::dump_heap(); } if (PrintClassHistogramBeforeFullGC) { - TraceTime tt("Class Histogram (before full gc): ", PrintGCDetails, true, gclog_or_tty); - VM_GC_HeapInspection inspector(gclog_or_tty, false /* ! full gc */, false /* ! prologue */); + GCTraceTime tt("Class Histogram (before full gc): ", PrintGCDetails, true, timer); + VM_GC_HeapInspection inspector(gclog_or_tty, false /* ! full gc */); inspector.doit(); } } -void CollectedHeap::post_full_gc_dump() { +void CollectedHeap::post_full_gc_dump(GCTimer* timer) { if (HeapDumpAfterFullGC) { - TraceTime tt("Heap Dump (after full gc): ", PrintGCDetails, false, gclog_or_tty); + GCTraceTime tt("Heap Dump (after full gc): ", PrintGCDetails, false, timer); HeapDumper::dump_heap(); } if (PrintClassHistogramAfterFullGC) { - TraceTime tt("Class Histogram (after full gc): ", PrintGCDetails, true, gclog_or_tty); - VM_GC_HeapInspection inspector(gclog_or_tty, false /* ! full gc */, false /* ! prologue */); + GCTraceTime tt("Class Histogram (after full gc): ", PrintGCDetails, true, timer); + VM_GC_HeapInspection inspector(gclog_or_tty, false /* ! full gc */); inspector.doit(); } } @@ -490,7 +559,7 @@ assert(size >= 0, "int won't convert to size_t"); HeapWord* obj; assert(ScavengeRootsInCode > 0, "must be"); - obj = common_mem_allocate_init(size, CHECK_NULL); + obj = common_mem_allocate_init(real_klass, size, CHECK_NULL); post_allocation_setup_common(klass, obj); assert(Universe::is_bootstrapping() || !((oop)obj)->is_array(), "must not be an array"); diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/share/vm/gc_interface/collectedHeap.hpp --- a/hotspot/src/share/vm/gc_interface/collectedHeap.hpp Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/src/share/vm/gc_interface/collectedHeap.hpp Wed Jul 05 18:59:39 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2012, 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 @@ -26,6 +26,7 @@ #define SHARE_VM_GC_INTERFACE_COLLECTEDHEAP_HPP #include "gc_interface/gcCause.hpp" +#include "gc_implementation/shared/gcWhen.hpp" #include "memory/allocation.hpp" #include "memory/barrierSet.hpp" #include "runtime/handles.hpp" @@ -38,11 +39,16 @@ // class defines the functions that a heap must implement, and contains // infrastructure common to all heaps. +class AdaptiveSizePolicy; class BarrierSet; +class CollectorPolicy; +class GCHeapSummary; +class GCTimer; +class GCTracer; +class MetaspaceSummary; +class Thread; class ThreadClosure; -class AdaptiveSizePolicy; -class Thread; -class CollectorPolicy; +class VirtualSpaceSummary; class GCMessage : public FormatBuffer<1024> { public: @@ -128,16 +134,16 @@ virtual void resize_all_tlabs(); // Allocate from the current thread's TLAB, with broken-out slow path. - inline static HeapWord* allocate_from_tlab(Thread* thread, size_t size); - static HeapWord* allocate_from_tlab_slow(Thread* thread, size_t size); + inline static HeapWord* allocate_from_tlab(KlassHandle klass, Thread* thread, size_t size); + static HeapWord* allocate_from_tlab_slow(KlassHandle klass, Thread* thread, size_t size); // Allocate an uninitialized block of the given size, or returns NULL if // this is impossible. - inline static HeapWord* common_mem_allocate_noinit(size_t size, TRAPS); + inline static HeapWord* common_mem_allocate_noinit(KlassHandle klass, size_t size, TRAPS); // Like allocate_init, but the block returned by a successful allocation // is guaranteed initialized to zeros. - inline static HeapWord* common_mem_allocate_init(size_t size, TRAPS); + inline static HeapWord* common_mem_allocate_init(KlassHandle klass, size_t size, TRAPS); // Helper functions for (VM) allocation. inline static void post_allocation_setup_common(KlassHandle klass, HeapWord* obj); @@ -166,6 +172,8 @@ // Fill with a single object (either an int array or a java.lang.Object). static inline void fill_with_object_impl(HeapWord* start, size_t words, bool zap = true); + virtual void trace_heap(GCWhen::Type when, GCTracer* tracer); + // Verification functions virtual void check_for_bad_heap_word_value(HeapWord* addr, size_t size) PRODUCT_RETURN; @@ -202,8 +210,6 @@ MemRegion reserved_region() const { return _reserved; } address base() const { return (address)reserved_region().start(); } - // Future cleanup here. The following functions should specify bytes or - // heapwords as part of their signature. virtual size_t capacity() const = 0; virtual size_t used() const = 0; @@ -550,8 +556,13 @@ virtual void prepare_for_verify() = 0; // Generate any dumps preceding or following a full gc - void pre_full_gc_dump(); - void post_full_gc_dump(); + void pre_full_gc_dump(GCTimer* timer); + void post_full_gc_dump(GCTimer* timer); + + VirtualSpaceSummary create_heap_space_summary(); + GCHeapSummary create_heap_summary(); + + MetaspaceSummary create_metaspace_summary(); // Print heap information on the given outputStream. virtual void print_on(outputStream* st) const = 0; @@ -560,7 +571,7 @@ print_on(tty); } // Print more detailed heap information on the given - // outputStream. The default behaviour is to call print_on(). It is + // outputStream. The default behavior is to call print_on(). It is // up to each subclass to override it and add any additional output // it needs. virtual void print_extended_on(outputStream* st) const { @@ -589,23 +600,11 @@ // Default implementation does nothing. virtual void print_tracing_info() const = 0; - // If PrintHeapAtGC is set call the appropriate routi - void print_heap_before_gc() { - if (PrintHeapAtGC) { - Universe::print_heap_before_gc(); - } - if (_gc_heap_log != NULL) { - _gc_heap_log->log_heap_before(); - } - } - void print_heap_after_gc() { - if (PrintHeapAtGC) { - Universe::print_heap_after_gc(); - } - if (_gc_heap_log != NULL) { - _gc_heap_log->log_heap_after(); - } - } + void print_heap_before_gc(); + void print_heap_after_gc(); + + void trace_heap_before_gc(GCTracer* gc_tracer); + void trace_heap_after_gc(GCTracer* gc_tracer); // Heap verification virtual void verify(bool silent, VerifyOption option) = 0; @@ -619,7 +618,7 @@ inline bool promotion_should_fail(); // Reset the PromotionFailureALot counters. Should be called at the end of a - // GC in which promotion failure ocurred. + // GC in which promotion failure occurred. inline void reset_promotion_should_fail(volatile size_t* count); inline void reset_promotion_should_fail(); #endif // #ifndef PRODUCT diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/share/vm/gc_interface/collectedHeap.inline.hpp --- a/hotspot/src/share/vm/gc_interface/collectedHeap.inline.hpp Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/src/share/vm/gc_interface/collectedHeap.inline.hpp Wed Jul 05 18:59:39 2017 +0200 @@ -25,6 +25,7 @@ #ifndef SHARE_VM_GC_INTERFACE_COLLECTEDHEAP_INLINE_HPP #define SHARE_VM_GC_INTERFACE_COLLECTEDHEAP_INLINE_HPP +#include "gc_interface/allocTracer.hpp" #include "gc_interface/collectedHeap.hpp" #include "memory/threadLocalAllocBuffer.inline.hpp" #include "memory/universe.hpp" @@ -107,7 +108,7 @@ post_allocation_notify(klass, (oop)obj); } -HeapWord* CollectedHeap::common_mem_allocate_noinit(size_t size, TRAPS) { +HeapWord* CollectedHeap::common_mem_allocate_noinit(KlassHandle klass, size_t size, TRAPS) { // Clear unhandled oops for memory allocation. Memory allocation might // not take out a lock if from tlab, so clear here. @@ -120,7 +121,7 @@ HeapWord* result = NULL; if (UseTLAB) { - result = CollectedHeap::allocate_from_tlab(THREAD, size); + result = allocate_from_tlab(klass, THREAD, size); if (result != NULL) { assert(!HAS_PENDING_EXCEPTION, "Unexpected exception, will result in uninitialized storage"); @@ -136,6 +137,9 @@ assert(!HAS_PENDING_EXCEPTION, "Unexpected exception, will result in uninitialized storage"); THREAD->incr_allocated_bytes(size * HeapWordSize); + + AllocTracer::send_allocation_outside_tlab_event(klass, size * HeapWordSize); + return result; } @@ -165,13 +169,13 @@ } } -HeapWord* CollectedHeap::common_mem_allocate_init(size_t size, TRAPS) { - HeapWord* obj = common_mem_allocate_noinit(size, CHECK_NULL); +HeapWord* CollectedHeap::common_mem_allocate_init(KlassHandle klass, size_t size, TRAPS) { + HeapWord* obj = common_mem_allocate_noinit(klass, size, CHECK_NULL); init_obj(obj, size); return obj; } -HeapWord* CollectedHeap::allocate_from_tlab(Thread* thread, size_t size) { +HeapWord* CollectedHeap::allocate_from_tlab(KlassHandle klass, Thread* thread, size_t size) { assert(UseTLAB, "should use UseTLAB"); HeapWord* obj = thread->tlab().allocate(size); @@ -179,7 +183,7 @@ return obj; } // Otherwise... - return allocate_from_tlab_slow(thread, size); + return allocate_from_tlab_slow(klass, thread, size); } void CollectedHeap::init_obj(HeapWord* obj, size_t size) { @@ -194,7 +198,7 @@ debug_only(check_for_valid_allocation_state()); assert(!Universe::heap()->is_gc_active(), "Allocation during gc not allowed"); assert(size >= 0, "int won't convert to size_t"); - HeapWord* obj = common_mem_allocate_init(size, CHECK_NULL); + HeapWord* obj = common_mem_allocate_init(klass, size, CHECK_NULL); post_allocation_setup_obj(klass, obj); NOT_PRODUCT(Universe::heap()->check_for_bad_heap_word_value(obj, size)); return (oop)obj; @@ -207,7 +211,7 @@ debug_only(check_for_valid_allocation_state()); assert(!Universe::heap()->is_gc_active(), "Allocation during gc not allowed"); assert(size >= 0, "int won't convert to size_t"); - HeapWord* obj = common_mem_allocate_init(size, CHECK_NULL); + HeapWord* obj = common_mem_allocate_init(klass, size, CHECK_NULL); post_allocation_setup_array(klass, obj, length); NOT_PRODUCT(Universe::heap()->check_for_bad_heap_word_value(obj, size)); return (oop)obj; @@ -220,7 +224,7 @@ debug_only(check_for_valid_allocation_state()); assert(!Universe::heap()->is_gc_active(), "Allocation during gc not allowed"); assert(size >= 0, "int won't convert to size_t"); - HeapWord* obj = common_mem_allocate_noinit(size, CHECK_NULL); + HeapWord* obj = common_mem_allocate_noinit(klass, size, CHECK_NULL); ((oop)obj)->set_klass_gap(0); post_allocation_setup_array(klass, obj, length); #ifndef PRODUCT diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/share/vm/gc_interface/gcCause.cpp --- a/hotspot/src/share/vm/gc_interface/gcCause.cpp Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/src/share/vm/gc_interface/gcCause.cpp Wed Jul 05 18:59:39 2017 +0200 @@ -72,6 +72,9 @@ case _cms_final_remark: return "CMS Final Remark"; + case _cms_concurrent_mark: + return "CMS Concurrent Mark"; + case _old_generation_expanded_on_last_scavenge: return "Old Generation Expanded On Last Scavenge"; diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/share/vm/gc_interface/gcCause.hpp --- a/hotspot/src/share/vm/gc_interface/gcCause.hpp Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/src/share/vm/gc_interface/gcCause.hpp Wed Jul 05 18:59:39 2017 +0200 @@ -60,6 +60,7 @@ _cms_generation_full, _cms_initial_mark, _cms_final_remark, + _cms_concurrent_mark, _old_generation_expanded_on_last_scavenge, _old_generation_too_full_to_scavenge, diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/share/vm/gc_interface/gcName.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/src/share/vm/gc_interface/gcName.hpp Wed Jul 05 18:59:39 2017 +0200 @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2002, 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. + * + */ + +#ifndef SHARE_VM_GC_INTERFACE_GCNAME_HPP +#define SHARE_VM_GC_INTERFACE_GCNAME_HPP + +#include "utilities/debug.hpp" + +enum GCName { + ParallelOld, + SerialOld, + PSMarkSweep, + ParallelScavenge, + DefNew, + ParNew, + G1New, + ConcurrentMarkSweep, + G1Old, + GCNameEndSentinel +}; + +class GCNameHelper { + public: + static const char* to_string(GCName name) { + switch(name) { + case ParallelOld: return "ParallelOld"; + case SerialOld: return "SerialOld"; + case PSMarkSweep: return "PSMarkSweep"; + case ParallelScavenge: return "ParallelScavenge"; + case DefNew: return "DefNew"; + case ParNew: return "ParNew"; + case G1New: return "G1New"; + case ConcurrentMarkSweep: return "ConcurrentMarkSweep"; + case G1Old: return "G1Old"; + default: ShouldNotReachHere(); return NULL; + } + } +}; + +#endif // SHARE_VM_GC_INTERFACE_GCNAME_HPP diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/share/vm/memory/allocation.hpp --- a/hotspot/src/share/vm/memory/allocation.hpp Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/src/share/vm/memory/allocation.hpp Wed Jul 05 18:59:39 2017 +0200 @@ -157,7 +157,8 @@ mtJavaHeap = 0x0C00, // Java heap mtClassShared = 0x0D00, // class data sharing mtTest = 0x0E00, // Test type for verifying NMT - mt_number_of_types = 0x000E, // number of memory types (mtDontTrack + mtTracing = 0x0F00, // memory used for Tracing + mt_number_of_types = 0x000F, // number of memory types (mtDontTrack // is not included as validate type) mtDontTrack = 0x0F00, // memory we do not or cannot track mt_masks = 0x7F00, diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/share/vm/memory/defNewGeneration.cpp --- a/hotspot/src/share/vm/memory/defNewGeneration.cpp Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/src/share/vm/memory/defNewGeneration.cpp Wed Jul 05 18:59:39 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2012, 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 @@ -25,6 +25,10 @@ #include "precompiled.hpp" #include "gc_implementation/shared/collectorCounters.hpp" #include "gc_implementation/shared/gcPolicyCounters.hpp" +#include "gc_implementation/shared/gcHeapSummary.hpp" +#include "gc_implementation/shared/gcTimer.hpp" +#include "gc_implementation/shared/gcTraceTime.hpp" +#include "gc_implementation/shared/gcTrace.hpp" #include "gc_implementation/shared/spaceDecorator.hpp" #include "memory/defNewGeneration.inline.hpp" #include "memory/gcLocker.inline.hpp" @@ -223,6 +227,8 @@ _next_gen = NULL; _tenuring_threshold = MaxTenuringThreshold; _pretenure_size_threshold_words = PretenureSizeThreshold >> LogHeapWordSize; + + _gc_timer = new (ResourceObj::C_HEAP, mtGC) STWGCTimer(); } void DefNewGeneration::compute_space_boundaries(uintx minimum_eden_size, @@ -558,12 +564,18 @@ size_t size, bool is_tlab) { assert(full || size > 0, "otherwise we don't want to collect"); + GenCollectedHeap* gch = GenCollectedHeap::heap(); + + _gc_timer->register_gc_start(os::elapsed_counter()); + DefNewTracer gc_tracer; + gc_tracer.report_gc_start(gch->gc_cause(), _gc_timer->gc_start()); + _next_gen = gch->next_gen(this); assert(_next_gen != NULL, "This must be the youngest gen, and not the only gen"); - // If the next generation is too full to accomodate promotion + // If the next generation is too full to accommodate promotion // from this generation, pass on collection; let the next generation // do it. if (!collection_attempt_is_safe()) { @@ -577,10 +589,12 @@ init_assuming_no_promotion_failure(); - TraceTime t1(GCCauseString("GC", gch->gc_cause()), PrintGC && !PrintGCDetails, true, gclog_or_tty); + GCTraceTime t1(GCCauseString("GC", gch->gc_cause()), PrintGC && !PrintGCDetails, true, NULL); // Capture heap used before collection (for printing). size_t gch_prev_used = gch->used(); + gch->trace_heap_before_gc(&gc_tracer); + SpecializationStats::clear(); // These can be shared for all code paths @@ -631,9 +645,12 @@ FastKeepAliveClosure keep_alive(this, &scan_weak_ref); ReferenceProcessor* rp = ref_processor(); rp->setup_policy(clear_all_soft_refs); + const ReferenceProcessorStats& stats = rp->process_discovered_references(&is_alive, &keep_alive, &evacuate_followers, - NULL); - if (!promotion_failed()) { + NULL, _gc_timer); + gc_tracer.report_gc_reference_stats(stats); + + if (!_promotion_failed) { // Swap the survivor spaces. eden()->clear(SpaceDecorator::Mangle); from()->clear(SpaceDecorator::Mangle); @@ -680,6 +697,7 @@ // Inform the next generation that a promotion failure occurred. _next_gen->promotion_failure_occurred(); + gc_tracer.report_promotion_failed(_promotion_failed_info); // Reset the PromotionFailureALot counters. NOT_PRODUCT(Universe::heap()->reset_promotion_should_fail();) @@ -689,11 +707,18 @@ to()->set_concurrent_iteration_safe_limit(to()->top()); SpecializationStats::print(); - // We need to use a monotonically non-deccreasing time in ms + // We need to use a monotonically non-decreasing time in ms // or we will see time-warp warnings and os::javaTimeMillis() // does not guarantee monotonicity. jlong now = os::javaTimeNanos() / NANOSECS_PER_MILLISEC; update_time_of_last_gc(now); + + gch->trace_heap_after_gc(&gc_tracer); + gc_tracer.report_tenuring_threshold(tenuring_threshold()); + + _gc_timer->register_gc_end(os::elapsed_counter()); + + gc_tracer.report_gc_end(_gc_timer->gc_end(), _gc_timer->time_partitions()); } class RemoveForwardPointerClosure: public ObjectClosure { @@ -705,6 +730,7 @@ void DefNewGeneration::init_assuming_no_promotion_failure() { _promotion_failed = false; + _promotion_failed_info.reset(); from()->set_next_compaction_space(NULL); } @@ -726,7 +752,7 @@ } void DefNewGeneration::preserve_mark(oop obj, markOop m) { - assert(promotion_failed() && m->must_be_preserved_for_promotion_failure(obj), + assert(_promotion_failed && m->must_be_preserved_for_promotion_failure(obj), "Oversaving!"); _objs_with_preserved_marks.push(obj); _preserved_marks_of_objs.push(m); @@ -744,6 +770,7 @@ old->size()); } _promotion_failed = true; + _promotion_failed_info.register_copy_failure(old->size()); preserve_mark_if_necessary(old, old->mark()); // forward to self old->forward_to(old); @@ -962,6 +989,10 @@ from()->set_top_for_allocations(); } +void DefNewGeneration::ref_processor_init() { + Generation::ref_processor_init(); +} + void DefNewGeneration::update_counters() { if (UsePerfData) { diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/share/vm/memory/defNewGeneration.hpp --- a/hotspot/src/share/vm/memory/defNewGeneration.hpp Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/src/share/vm/memory/defNewGeneration.hpp Wed Jul 05 18:59:39 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2012, 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 @@ -28,12 +28,14 @@ #include "gc_implementation/shared/ageTable.hpp" #include "gc_implementation/shared/cSpaceCounters.hpp" #include "gc_implementation/shared/generationCounters.hpp" +#include "gc_implementation/shared/copyFailedInfo.hpp" #include "memory/generation.inline.hpp" #include "utilities/stack.hpp" class EdenSpace; class ContiguousSpace; class ScanClosure; +class STWGCTimer; // DefNewGeneration is a young generation containing eden, from- and // to-space. @@ -46,15 +48,17 @@ uint _tenuring_threshold; // Tenuring threshold for next collection. ageTable _age_table; // Size of object to pretenure in words; command line provides bytes - size_t _pretenure_size_threshold_words; + size_t _pretenure_size_threshold_words; ageTable* age_table() { return &_age_table; } + // Initialize state to optimistically assume no promotion failure will // happen. void init_assuming_no_promotion_failure(); // True iff a promotion has failed in the current collection. bool _promotion_failed; bool promotion_failed() { return _promotion_failed; } + PromotionFailedInfo _promotion_failed_info; // Handling promotion failure. A young generation collection // can fail if a live object cannot be copied out of its @@ -132,6 +136,8 @@ ContiguousSpace* _from_space; ContiguousSpace* _to_space; + STWGCTimer* _gc_timer; + enum SomeProtectedConstants { // Generations are GenGrain-aligned and have size that are multiples of // GenGrain. @@ -203,6 +209,8 @@ DefNewGeneration(ReservedSpace rs, size_t initial_byte_size, int level, const char* policy="Copy"); + virtual void ref_processor_init(); + virtual Generation::Name kind() { return Generation::DefNew; } // Accessing spaces diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/share/vm/memory/genCollectedHeap.cpp --- a/hotspot/src/share/vm/memory/genCollectedHeap.cpp Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/src/share/vm/memory/genCollectedHeap.cpp Wed Jul 05 18:59:39 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 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 @@ -28,6 +28,7 @@ #include "classfile/vmSymbols.hpp" #include "code/icBuffer.hpp" #include "gc_implementation/shared/collectorCounters.hpp" +#include "gc_implementation/shared/gcTraceTime.hpp" #include "gc_implementation/shared/vmGCOperations.hpp" #include "gc_interface/collectedHeap.inline.hpp" #include "memory/filemap.hpp" @@ -388,7 +389,7 @@ const char* gc_cause_prefix = complete ? "Full GC" : "GC"; gclog_or_tty->date_stamp(PrintGC && PrintGCDateStamps); TraceCPUTime tcpu(PrintGCDetails, true, gclog_or_tty); - TraceTime t(GCCauseString(gc_cause_prefix, gc_cause()), PrintGCDetails, false, gclog_or_tty); + GCTraceTime t(GCCauseString(gc_cause_prefix, gc_cause()), PrintGCDetails, false, NULL); gc_prologue(complete); increment_total_collections(complete); @@ -417,10 +418,11 @@ // The full_collections increment was missed above. increment_total_full_collections(); } - pre_full_gc_dump(); // do any pre full gc dumps + pre_full_gc_dump(NULL); // do any pre full gc dumps } // Timer for individual generations. Last argument is false: no CR - TraceTime t1(_gens[i]->short_name(), PrintGCDetails, false, gclog_or_tty); + // FIXME: We should try to start the timing earlier to cover more of the GC pause + GCTraceTime t1(_gens[i]->short_name(), PrintGCDetails, false, NULL); TraceCollectorStats tcs(_gens[i]->counters()); TraceMemoryManagerStats tmms(_gens[i]->kind(),gc_cause()); @@ -534,7 +536,8 @@ complete = complete || (max_level_collected == n_gens() - 1); if (complete) { // We did a "major" collection - post_full_gc_dump(); // do any post full gc dumps + // FIXME: See comment at pre_full_gc_dump call + post_full_gc_dump(NULL); // do any post full gc dumps } if (PrintGCDetails) { diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/share/vm/memory/genMarkSweep.cpp --- a/hotspot/src/share/vm/memory/genMarkSweep.cpp Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/src/share/vm/memory/genMarkSweep.cpp Wed Jul 05 18:59:39 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2012, 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 @@ -29,6 +29,10 @@ #include "classfile/vmSymbols.hpp" #include "code/codeCache.hpp" #include "code/icBuffer.hpp" +#include "gc_implementation/shared/gcHeapSummary.hpp" +#include "gc_implementation/shared/gcTimer.hpp" +#include "gc_implementation/shared/gcTrace.hpp" +#include "gc_implementation/shared/gcTraceTime.hpp" #include "gc_interface/collectedHeap.inline.hpp" #include "memory/genCollectedHeap.hpp" #include "memory/genMarkSweep.hpp" @@ -65,7 +69,9 @@ _ref_processor = rp; rp->setup_policy(clear_all_softrefs); - TraceTime t1(GCCauseString("Full GC", gch->gc_cause()), PrintGC && !PrintGCDetails, true, gclog_or_tty); + GCTraceTime t1(GCCauseString("Full GC", gch->gc_cause()), PrintGC && !PrintGCDetails, true, NULL); + + gch->trace_heap_before_gc(_gc_tracer); // When collecting the permanent generation Method*s may be moving, // so we either have to flush all bcp data or convert it into bci. @@ -155,6 +161,8 @@ // does not guarantee monotonicity. jlong now = os::javaTimeNanos() / NANOSECS_PER_MILLISEC; gch->update_time_of_last_gc(now); + + gch->trace_heap_after_gc(_gc_tracer); } void GenMarkSweep::allocate_stacks() { @@ -192,7 +200,7 @@ void GenMarkSweep::mark_sweep_phase1(int level, bool clear_all_softrefs) { // Recursively traverse all live objects and mark them - TraceTime tm("phase 1", PrintGC && Verbose, true, gclog_or_tty); + GCTraceTime tm("phase 1", PrintGC && Verbose, true, _gc_timer); trace(" 1"); GenCollectedHeap* gch = GenCollectedHeap::heap(); @@ -219,8 +227,10 @@ // Process reference objects found during marking { ref_processor()->setup_policy(clear_all_softrefs); - ref_processor()->process_discovered_references( - &is_alive, &keep_alive, &follow_stack_closure, NULL); + const ReferenceProcessorStats& stats = + ref_processor()->process_discovered_references( + &is_alive, &keep_alive, &follow_stack_closure, NULL, _gc_timer); + gc_tracer()->report_gc_reference_stats(stats); } // This is the point where the entire marking should have completed. @@ -240,6 +250,8 @@ // Clean up unreferenced symbols in symbol table. SymbolTable::unlink(); + + gc_tracer()->report_object_count_after_gc(&is_alive); } @@ -259,7 +271,7 @@ GenCollectedHeap* gch = GenCollectedHeap::heap(); - TraceTime tm("phase 2", PrintGC && Verbose, true, gclog_or_tty); + GCTraceTime tm("phase 2", PrintGC && Verbose, true, _gc_timer); trace("2"); gch->prepare_for_compaction(); @@ -276,7 +288,7 @@ GenCollectedHeap* gch = GenCollectedHeap::heap(); // Adjust the pointers to reflect the new locations - TraceTime tm("phase 3", PrintGC && Verbose, true, gclog_or_tty); + GCTraceTime tm("phase 3", PrintGC && Verbose, true, _gc_timer); trace("3"); // Need new claim bits for the pointer adjustment tracing. @@ -331,7 +343,7 @@ // to use a higher index (saved from phase2) when verifying perm_gen. GenCollectedHeap* gch = GenCollectedHeap::heap(); - TraceTime tm("phase 4", PrintGC && Verbose, true, gclog_or_tty); + GCTraceTime tm("phase 4", PrintGC && Verbose, true, _gc_timer); trace("4"); GenCompactClosure blk; diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/share/vm/memory/generation.cpp --- a/hotspot/src/share/vm/memory/generation.cpp Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/src/share/vm/memory/generation.cpp Wed Jul 05 18:59:39 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -23,6 +23,8 @@ */ #include "precompiled.hpp" +#include "gc_implementation/shared/gcTimer.hpp" +#include "gc_implementation/shared/gcTrace.hpp" #include "gc_implementation/shared/spaceDecorator.hpp" #include "gc_interface/collectedHeap.inline.hpp" #include "memory/allocation.inline.hpp" @@ -624,12 +626,26 @@ bool clear_all_soft_refs, size_t size, bool is_tlab) { + GenCollectedHeap* gch = GenCollectedHeap::heap(); + SpecializationStats::clear(); // Temporarily expand the span of our ref processor, so // refs discovery is over the entire heap, not just this generation ReferenceProcessorSpanMutator - x(ref_processor(), GenCollectedHeap::heap()->reserved_region()); + x(ref_processor(), gch->reserved_region()); + + STWGCTimer* gc_timer = GenMarkSweep::gc_timer(); + gc_timer->register_gc_start(os::elapsed_counter()); + + SerialOldTracer* gc_tracer = GenMarkSweep::gc_tracer(); + gc_tracer->report_gc_start(gch->gc_cause(), gc_timer->gc_start()); + GenMarkSweep::invoke_at_safepoint(_level, ref_processor(), clear_all_soft_refs); + + gc_timer->register_gc_end(os::elapsed_counter()); + + gc_tracer->report_gc_end(os::elapsed_counter(), gc_timer->time_partitions()); + SpecializationStats::print(); } diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/share/vm/memory/heapInspection.cpp --- a/hotspot/src/share/vm/memory/heapInspection.cpp Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/src/share/vm/memory/heapInspection.cpp Wed Jul 05 18:59:39 2017 +0200 @@ -95,7 +95,7 @@ } elt = elt->next(); } - elt = new KlassInfoEntry(k, list()); + elt = new (std::nothrow) KlassInfoEntry(k, list()); // We may be out of space to allocate the new entry. if (elt != NULL) { set_list(elt); @@ -127,13 +127,15 @@ _table->lookup(k); } -KlassInfoTable::KlassInfoTable(int size, HeapWord* ref, - bool need_class_stats) { +KlassInfoTable::KlassInfoTable(bool need_class_stats) { + _size_of_instances_in_words = 0; _size = 0; - _ref = ref; - _buckets = NEW_C_HEAP_ARRAY(KlassInfoBucket, size, mtInternal); + _ref = (HeapWord*) Universe::boolArrayKlassObj(); + _buckets = + (KlassInfoBucket*) AllocateHeap(sizeof(KlassInfoBucket) * _num_buckets, + mtInternal, 0, AllocFailStrategy::RETURN_NULL); if (_buckets != NULL) { - _size = size; + _size = _num_buckets; for (int index = 0; index < _size; index++) { _buckets[index].initialize(); } @@ -179,6 +181,7 @@ if (elt != NULL) { elt->set_count(elt->count() + 1); elt->set_words(elt->words() + obj->size()); + _size_of_instances_in_words += obj->size(); return true; } else { return false; @@ -192,14 +195,18 @@ } } +size_t KlassInfoTable::size_of_instances_in_words() const { + return _size_of_instances_in_words; +} + int KlassInfoHisto::sort_helper(KlassInfoEntry** e1, KlassInfoEntry** e2) { return (*e1)->compare(*e1,*e2); } -KlassInfoHisto::KlassInfoHisto(KlassInfoTable* cit, const char* title, int estimatedCount) : +KlassInfoHisto::KlassInfoHisto(KlassInfoTable* cit, const char* title) : _cit(cit), _title(title) { - _elements = new (ResourceObj::C_HEAP, mtInternal) GrowableArray(estimatedCount,true); + _elements = new (ResourceObj::C_HEAP, mtInternal) GrowableArray(_histo_initial_size, true); } KlassInfoHisto::~KlassInfoHisto() { @@ -444,25 +451,37 @@ private: KlassInfoTable* _cit; size_t _missed_count; + BoolObjectClosure* _filter; public: - RecordInstanceClosure(KlassInfoTable* cit) : - _cit(cit), _missed_count(0) {} + RecordInstanceClosure(KlassInfoTable* cit, BoolObjectClosure* filter) : + _cit(cit), _missed_count(0), _filter(filter) {} void do_object(oop obj) { - if (!_cit->record_instance(obj)) { - _missed_count++; + if (should_visit(obj)) { + if (!_cit->record_instance(obj)) { + _missed_count++; + } } } size_t missed_count() { return _missed_count; } + + private: + bool should_visit(oop obj) { + return _filter == NULL || _filter->do_object_b(obj); + } }; -void HeapInspection::heap_inspection(outputStream* st, bool need_prologue) { +size_t HeapInspection::populate_table(KlassInfoTable* cit, BoolObjectClosure *filter) { ResourceMark rm; - // Get some random number for ref (the hash key) - HeapWord* ref = (HeapWord*) Universe::boolArrayKlassObj(); - CollectedHeap* heap = Universe::heap(); - bool is_shared_heap = false; + + RecordInstanceClosure ric(cit, filter); + Universe::heap()->object_iterate(&ric); + return ric.missed_count(); +} + +void HeapInspection::heap_inspection(outputStream* st) { + ResourceMark rm; if (_print_help) { for (int c=0; cobject_iterate(&ric); - - // Report if certain classes are not counted because of - // running out of C-heap for the histogram. - size_t missed_count = ric.missed_count(); + size_t missed_count = populate_table(&cit); if (missed_count != 0) { st->print_cr("WARNING: Ran out of C-heap; undercounted " SIZE_FORMAT " total instances in data below", missed_count); } + // Sort and print klass instance info const char *title = "\n" " num #instances #bytes class name\n" "----------------------------------------------"; - KlassInfoHisto histo(&cit, title, KlassInfoHisto::histo_initial_size); + KlassInfoHisto histo(&cit, title); HistoClosure hc(&histo); + cit.iterate(&hc); + histo.sort(); histo.print_histo_on(st, _print_class_stats, _csv_format, _columns); } else { st->print_cr("WARNING: Ran out of C-heap; histogram not generated"); } st->flush(); - - if (need_prologue && is_shared_heap) { - SharedHeap* sh = (SharedHeap*)heap; - sh->gc_epilogue(false /* !full */); // release all acquired locks, etc. - } } class FindInstanceClosure : public ObjectClosure { diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/share/vm/memory/heapInspection.hpp --- a/hotspot/src/share/vm/memory/heapInspection.hpp Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/src/share/vm/memory/heapInspection.hpp Wed Jul 05 18:59:39 2017 +0200 @@ -26,6 +26,7 @@ #define SHARE_VM_MEMORY_HEAPINSPECTION_HPP #include "memory/allocation.inline.hpp" +#include "memory/klassInfoClosure.hpp" #include "oops/oop.inline.hpp" #include "oops/annotations.hpp" #include "utilities/macros.hpp" @@ -203,12 +204,6 @@ const char* name() const; }; -class KlassInfoClosure: public StackObj { - public: - // Called for each KlassInfoEntry. - virtual void do_cinfo(KlassInfoEntry* cie) = 0; -}; - class KlassInfoBucket: public CHeapObj { private: KlassInfoEntry* _list; @@ -224,6 +219,8 @@ class KlassInfoTable: public StackObj { private: int _size; + static const int _num_buckets = 20011; + size_t _size_of_instances_in_words; // An aligned reference address (typically the least // address in the perm gen) used for hashing klass @@ -242,21 +239,19 @@ }; public: - // Table size - enum { - cit_size = 20011 - }; - KlassInfoTable(int size, HeapWord* ref, bool need_class_stats); + KlassInfoTable(bool need_class_stats); ~KlassInfoTable(); bool record_instance(const oop obj); void iterate(KlassInfoClosure* cic); bool allocation_failed() { return _buckets == NULL; } + size_t size_of_instances_in_words() const; friend class KlassInfoHisto; }; class KlassInfoHisto : public StackObj { private: + static const int _histo_initial_size = 1000; KlassInfoTable *_cit; GrowableArray* _elements; GrowableArray* elements() const { return _elements; } @@ -334,11 +329,7 @@ } public: - enum { - histo_initial_size = 1000 - }; - KlassInfoHisto(KlassInfoTable* cit, const char* title, - int estimatedCount); + KlassInfoHisto(KlassInfoTable* cit, const char* title); ~KlassInfoHisto(); void add(KlassInfoEntry* cie); void print_histo_on(outputStream* st, bool print_class_stats, bool csv_format, const char *columns); @@ -347,6 +338,11 @@ #endif // INCLUDE_SERVICES +// These declarations are needed since teh declaration of KlassInfoTable and +// KlassInfoClosure are guarded by #if INLCUDE_SERVICES +class KlassInfoTable; +class KlassInfoClosure; + class HeapInspection : public StackObj { bool _csv_format; // "comma separated values" format for spreadsheet. bool _print_help; @@ -357,8 +353,11 @@ bool print_class_stats, const char *columns) : _csv_format(csv_format), _print_help(print_help), _print_class_stats(print_class_stats), _columns(columns) {} - void heap_inspection(outputStream* st, bool need_prologue) NOT_SERVICES_RETURN; + void heap_inspection(outputStream* st) NOT_SERVICES_RETURN; + size_t populate_table(KlassInfoTable* cit, BoolObjectClosure* filter = NULL) NOT_SERVICES_RETURN; static void find_instances_at_safepoint(Klass* k, GrowableArray* result) NOT_SERVICES_RETURN; + private: + void iterate_over_heap(KlassInfoTable* cit, BoolObjectClosure* filter = NULL); }; #endif // SHARE_VM_MEMORY_HEAPINSPECTION_HPP diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/share/vm/memory/klassInfoClosure.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/src/share/vm/memory/klassInfoClosure.hpp Wed Jul 05 18:59:39 2017 +0200 @@ -0,0 +1,36 @@ +/* + * 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. + * + */ + +#ifndef SHARE_VM_MEMORY_KLASSINFOCLOSURE_HPP +#define SHARE_VM_MEMORY_KLASSINFOCLOSURE_HPP + +class KlassInfoEntry; + +class KlassInfoClosure : public StackObj { + public: + // Called for each KlassInfoEntry. + virtual void do_cinfo(KlassInfoEntry* cie) = 0; +}; + +#endif // SHARE_VM_MEMORY_KLASSINFOCLOSURE_HPP diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/share/vm/memory/metaspace.hpp --- a/hotspot/src/share/vm/memory/metaspace.hpp Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/src/share/vm/memory/metaspace.hpp Wed Jul 05 18:59:39 2017 +0200 @@ -193,7 +193,10 @@ }; class MetaspaceAux : AllStatic { + static size_t free_chunks_total(Metaspace::MetadataType mdtype); + static size_t free_chunks_total_in_bytes(Metaspace::MetadataType mdtype); + public: // Statistics for class space and data space in metaspace. // These methods iterate over the classloader data graph @@ -205,10 +208,6 @@ // Iterates over the virtual space list. static size_t reserved_in_bytes(Metaspace::MetadataType mdtype); - static size_t free_chunks_total(Metaspace::MetadataType mdtype); - static size_t free_chunks_total_in_bytes(Metaspace::MetadataType mdtype); - - public: // Running sum of space in all Metachunks that has been // allocated to a Metaspace. This is used instead of // iterating over all the classloaders. One for each diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/share/vm/memory/oopFactory.hpp --- a/hotspot/src/share/vm/memory/oopFactory.hpp Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/src/share/vm/memory/oopFactory.hpp Wed Jul 05 18:59:39 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -27,6 +27,7 @@ #include "classfile/symbolTable.hpp" #include "classfile/systemDictionary.hpp" +#include "memory/referenceType.hpp" #include "memory/universe.hpp" #include "oops/objArrayKlass.hpp" #include "oops/oop.hpp" diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/share/vm/memory/referenceProcessor.cpp --- a/hotspot/src/share/vm/memory/referenceProcessor.cpp Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/src/share/vm/memory/referenceProcessor.cpp Wed Jul 05 18:59:39 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2012, 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 @@ -25,6 +25,8 @@ #include "precompiled.hpp" #include "classfile/javaClasses.hpp" #include "classfile/systemDictionary.hpp" +#include "gc_implementation/shared/gcTimer.hpp" +#include "gc_implementation/shared/gcTraceTime.hpp" #include "gc_interface/collectedHeap.hpp" #include "gc_interface/collectedHeap.inline.hpp" #include "memory/referencePolicy.hpp" @@ -180,11 +182,20 @@ // past clock value. } -void ReferenceProcessor::process_discovered_references( +size_t ReferenceProcessor::total_count(DiscoveredList lists[]) { + size_t total = 0; + for (uint i = 0; i < _max_num_q; ++i) { + total += lists[i].length(); + } + return total; +} + +ReferenceProcessorStats ReferenceProcessor::process_discovered_references( BoolObjectClosure* is_alive, OopClosure* keep_alive, VoidClosure* complete_gc, - AbstractRefProcTaskExecutor* task_executor) { + AbstractRefProcTaskExecutor* task_executor, + GCTimer* gc_timer) { NOT_PRODUCT(verify_ok_to_handle_reflists()); assert(!enqueuing_is_done(), "If here enqueuing should not be complete"); @@ -202,34 +213,43 @@ _soft_ref_timestamp_clock = java_lang_ref_SoftReference::clock(); bool trace_time = PrintGCDetails && PrintReferenceGC; + // Soft references + size_t soft_count = 0; { - TraceTime tt("SoftReference", trace_time, false, gclog_or_tty); - process_discovered_reflist(_discoveredSoftRefs, _current_soft_ref_policy, true, - is_alive, keep_alive, complete_gc, task_executor); + GCTraceTime tt("SoftReference", trace_time, false, gc_timer); + soft_count = + process_discovered_reflist(_discoveredSoftRefs, _current_soft_ref_policy, true, + is_alive, keep_alive, complete_gc, task_executor); } update_soft_ref_master_clock(); // Weak references + size_t weak_count = 0; { - TraceTime tt("WeakReference", trace_time, false, gclog_or_tty); - process_discovered_reflist(_discoveredWeakRefs, NULL, true, - is_alive, keep_alive, complete_gc, task_executor); + GCTraceTime tt("WeakReference", trace_time, false, gc_timer); + weak_count = + process_discovered_reflist(_discoveredWeakRefs, NULL, true, + is_alive, keep_alive, complete_gc, task_executor); } // Final references + size_t final_count = 0; { - TraceTime tt("FinalReference", trace_time, false, gclog_or_tty); - process_discovered_reflist(_discoveredFinalRefs, NULL, false, - is_alive, keep_alive, complete_gc, task_executor); + GCTraceTime tt("FinalReference", trace_time, false, gc_timer); + final_count = + process_discovered_reflist(_discoveredFinalRefs, NULL, false, + is_alive, keep_alive, complete_gc, task_executor); } // Phantom references + size_t phantom_count = 0; { - TraceTime tt("PhantomReference", trace_time, false, gclog_or_tty); - process_discovered_reflist(_discoveredPhantomRefs, NULL, false, - is_alive, keep_alive, complete_gc, task_executor); + GCTraceTime tt("PhantomReference", trace_time, false, gc_timer); + phantom_count = + process_discovered_reflist(_discoveredPhantomRefs, NULL, false, + is_alive, keep_alive, complete_gc, task_executor); } // Weak global JNI references. It would make more sense (semantically) to @@ -238,12 +258,14 @@ // thus use JNI weak references to circumvent the phantom references and // resurrect a "post-mortem" object. { - TraceTime tt("JNI Weak Reference", trace_time, false, gclog_or_tty); + GCTraceTime tt("JNI Weak Reference", trace_time, false, gc_timer); if (task_executor != NULL) { task_executor->set_single_threaded_mode(); } process_phaseJNI(is_alive, keep_alive, complete_gc); } + + return ReferenceProcessorStats(soft_count, weak_count, final_count, phantom_count); } #ifndef PRODUCT @@ -878,7 +900,7 @@ balance_queues(_discoveredPhantomRefs); } -void +size_t ReferenceProcessor::process_discovered_reflist( DiscoveredList refs_lists[], ReferencePolicy* policy, @@ -901,12 +923,11 @@ must_balance) { balance_queues(refs_lists); } + + size_t total_list_count = total_count(refs_lists); + if (PrintReferenceGC && PrintGCDetails) { - size_t total = 0; - for (uint i = 0; i < _max_num_q; ++i) { - total += refs_lists[i].length(); - } - gclog_or_tty->print(", %u refs", total); + gclog_or_tty->print(", %u refs", total_list_count); } // Phase 1 (soft refs only): @@ -951,6 +972,8 @@ is_alive, keep_alive, complete_gc); } } + + return total_list_count; } void ReferenceProcessor::clean_up_discovered_references() { @@ -1266,14 +1289,15 @@ BoolObjectClosure* is_alive, OopClosure* keep_alive, VoidClosure* complete_gc, - YieldClosure* yield) { + YieldClosure* yield, + GCTimer* gc_timer) { NOT_PRODUCT(verify_ok_to_handle_reflists()); // Soft references { - TraceTime tt("Preclean SoftReferences", PrintGCDetails && PrintReferenceGC, - false, gclog_or_tty); + GCTraceTime tt("Preclean SoftReferences", PrintGCDetails && PrintReferenceGC, + false, gc_timer); for (uint i = 0; i < _max_num_q; i++) { if (yield->should_return()) { return; @@ -1285,8 +1309,8 @@ // Weak references { - TraceTime tt("Preclean WeakReferences", PrintGCDetails && PrintReferenceGC, - false, gclog_or_tty); + GCTraceTime tt("Preclean WeakReferences", PrintGCDetails && PrintReferenceGC, + false, gc_timer); for (uint i = 0; i < _max_num_q; i++) { if (yield->should_return()) { return; @@ -1298,8 +1322,8 @@ // Final references { - TraceTime tt("Preclean FinalReferences", PrintGCDetails && PrintReferenceGC, - false, gclog_or_tty); + GCTraceTime tt("Preclean FinalReferences", PrintGCDetails && PrintReferenceGC, + false, gc_timer); for (uint i = 0; i < _max_num_q; i++) { if (yield->should_return()) { return; @@ -1311,8 +1335,8 @@ // Phantom references { - TraceTime tt("Preclean PhantomReferences", PrintGCDetails && PrintReferenceGC, - false, gclog_or_tty); + GCTraceTime tt("Preclean PhantomReferences", PrintGCDetails && PrintReferenceGC, + false, gc_timer); for (uint i = 0; i < _max_num_q; i++) { if (yield->should_return()) { return; diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/share/vm/memory/referenceProcessor.hpp --- a/hotspot/src/share/vm/memory/referenceProcessor.hpp Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/src/share/vm/memory/referenceProcessor.hpp Wed Jul 05 18:59:39 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2012, 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 @@ -26,8 +26,12 @@ #define SHARE_VM_MEMORY_REFERENCEPROCESSOR_HPP #include "memory/referencePolicy.hpp" +#include "memory/referenceProcessorStats.hpp" +#include "memory/referenceType.hpp" #include "oops/instanceRefKlass.hpp" +class GCTimer; + // ReferenceProcessor class encapsulates the per-"collector" processing // of java.lang.Reference objects for GC. The interface is useful for supporting // a generational abstraction, in particular when there are multiple @@ -204,6 +208,10 @@ }; class ReferenceProcessor : public CHeapObj { + + private: + size_t total_count(DiscoveredList lists[]); + protected: // Compatibility with pre-4965777 JDK's static bool _pending_list_uses_discovered_field; @@ -282,13 +290,13 @@ } // Process references with a certain reachability level. - void process_discovered_reflist(DiscoveredList refs_lists[], - ReferencePolicy* policy, - bool clear_referent, - BoolObjectClosure* is_alive, - OopClosure* keep_alive, - VoidClosure* complete_gc, - AbstractRefProcTaskExecutor* task_executor); + size_t process_discovered_reflist(DiscoveredList refs_lists[], + ReferencePolicy* policy, + bool clear_referent, + BoolObjectClosure* is_alive, + OopClosure* keep_alive, + VoidClosure* complete_gc, + AbstractRefProcTaskExecutor* task_executor); void process_phaseJNI(BoolObjectClosure* is_alive, OopClosure* keep_alive, @@ -349,7 +357,8 @@ void preclean_discovered_references(BoolObjectClosure* is_alive, OopClosure* keep_alive, VoidClosure* complete_gc, - YieldClosure* yield); + YieldClosure* yield, + GCTimer* gc_timer); // Delete entries in the discovered lists that have // either a null referent or are not active. Such @@ -500,12 +509,13 @@ bool discover_reference(oop obj, ReferenceType rt); // Process references found during GC (called by the garbage collector) - void process_discovered_references(BoolObjectClosure* is_alive, - OopClosure* keep_alive, - VoidClosure* complete_gc, - AbstractRefProcTaskExecutor* task_executor); + ReferenceProcessorStats + process_discovered_references(BoolObjectClosure* is_alive, + OopClosure* keep_alive, + VoidClosure* complete_gc, + AbstractRefProcTaskExecutor* task_executor, + GCTimer *gc_timer); - public: // Enqueue references at end of GC (called by the garbage collector) bool enqueue_discovered_references(AbstractRefProcTaskExecutor* task_executor = NULL); diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/share/vm/memory/referenceProcessorStats.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/src/share/vm/memory/referenceProcessorStats.hpp Wed Jul 05 18:59:39 2017 +0200 @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2012 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. + * + */ + +#ifndef SHARE_VM_MEMORY_REFERENCEPROCESSORSTATS_HPP +#define SHARE_VM_MEMORY_REFERENCEPROCESSORSTATS_HPP + +#include "utilities/globalDefinitions.hpp" + +class ReferenceProcessor; + +// ReferenceProcessorStats contains statistics about how many references that +// have been traversed when processing references during garbage collection. +class ReferenceProcessorStats { + size_t _soft_count; + size_t _weak_count; + size_t _final_count; + size_t _phantom_count; + + public: + ReferenceProcessorStats() : + _soft_count(0), + _weak_count(0), + _final_count(0), + _phantom_count(0) {} + + ReferenceProcessorStats(size_t soft_count, + size_t weak_count, + size_t final_count, + size_t phantom_count) : + _soft_count(soft_count), + _weak_count(weak_count), + _final_count(final_count), + _phantom_count(phantom_count) + {} + + size_t soft_count() const { + return _soft_count; + } + + size_t weak_count() const { + return _weak_count; + } + + size_t final_count() const { + return _final_count; + } + + size_t phantom_count() const { + return _phantom_count; + } +}; +#endif diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/share/vm/memory/referenceType.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/src/share/vm/memory/referenceType.hpp Wed Jul 05 18:59:39 2017 +0200 @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2012, 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. + * + */ + +#ifndef SHARE_VM_MEMORY_REFRERENCETYPE_HPP +#define SHARE_VM_MEMORY_REFRERENCETYPE_HPP + +#include "utilities/debug.hpp" + +// ReferenceType is used to distinguish between java/lang/ref/Reference subclasses + +enum ReferenceType { + REF_NONE, // Regular class + REF_OTHER, // Subclass of java/lang/ref/Reference, but not subclass of one of the classes below + REF_SOFT, // Subclass of java/lang/ref/SoftReference + REF_WEAK, // Subclass of java/lang/ref/WeakReference + REF_FINAL, // Subclass of java/lang/ref/FinalReference + REF_PHANTOM // Subclass of java/lang/ref/PhantomReference +}; + +#endif // SHARE_VM_MEMORY_REFRERENCETYPE_HPP diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/share/vm/memory/universe.cpp --- a/hotspot/src/share/vm/memory/universe.cpp Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/src/share/vm/memory/universe.cpp Wed Jul 05 18:59:39 2017 +0200 @@ -819,12 +819,14 @@ // keep the Universe::narrow_oop_base() set in Universe::reserve_heap() Universe::set_narrow_oop_shift(LogMinObjAlignmentInBytes); if (verbose) { - tty->print(", Compressed Oops with base: "PTR_FORMAT, Universe::narrow_oop_base()); + tty->print(", %s: "PTR_FORMAT, + narrow_oop_mode_to_string(HeapBasedNarrowOop), + Universe::narrow_oop_base()); } } else { Universe::set_narrow_oop_base(0); if (verbose) { - tty->print(", zero based Compressed Oops"); + tty->print(", %s", narrow_oop_mode_to_string(ZeroBasedNarrowOop)); } #ifdef _WIN64 if (!Universe::narrow_oop_use_implicit_null_checks()) { @@ -839,7 +841,7 @@ } else { Universe::set_narrow_oop_shift(0); if (verbose) { - tty->print(", 32-bits Oops"); + tty->print(", %s", narrow_oop_mode_to_string(UnscaledNarrowOop)); } } } @@ -946,6 +948,33 @@ } +const char* Universe::narrow_oop_mode_to_string(Universe::NARROW_OOP_MODE mode) { + switch (mode) { + case UnscaledNarrowOop: + return "32-bits Oops"; + case ZeroBasedNarrowOop: + return "zero based Compressed Oops"; + case HeapBasedNarrowOop: + return "Compressed Oops with base"; + } + + ShouldNotReachHere(); + return ""; +} + + +Universe::NARROW_OOP_MODE Universe::narrow_oop_mode() { + if (narrow_oop_base() != 0) { + return HeapBasedNarrowOop; + } + + if (narrow_oop_shift() != 0) { + return ZeroBasedNarrowOop; + } + + return UnscaledNarrowOop; +} + void universe2_init() { EXCEPTION_MARK; diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/share/vm/memory/universe.hpp --- a/hotspot/src/share/vm/memory/universe.hpp Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/src/share/vm/memory/universe.hpp Wed Jul 05 18:59:39 2017 +0200 @@ -253,19 +253,6 @@ return m; } - // Narrow Oop encoding mode: - // 0 - Use 32-bits oops without encoding when - // NarrowOopHeapBaseMin + heap_size < 4Gb - // 1 - Use zero based compressed oops with encoding when - // NarrowOopHeapBaseMin + heap_size < 32Gb - // 2 - Use compressed oops with heap base + encoding. - enum NARROW_OOP_MODE { - UnscaledNarrowOop = 0, - ZeroBasedNarrowOop = 1, - HeapBasedNarrowOop = 2 - }; - static char* preferred_heap_base(size_t heap_size, NARROW_OOP_MODE mode); - static char* preferred_metaspace_base(size_t heap_size, NARROW_OOP_MODE mode); static void set_narrow_oop_base(address base) { assert(UseCompressedOops, "no compressed oops?"); _narrow_oop._base = base; @@ -380,6 +367,21 @@ static CollectedHeap* heap() { return _collectedHeap; } // For UseCompressedOops + // Narrow Oop encoding mode: + // 0 - Use 32-bits oops without encoding when + // NarrowOopHeapBaseMin + heap_size < 4Gb + // 1 - Use zero based compressed oops with encoding when + // NarrowOopHeapBaseMin + heap_size < 32Gb + // 2 - Use compressed oops with heap base + encoding. + enum NARROW_OOP_MODE { + UnscaledNarrowOop = 0, + ZeroBasedNarrowOop = 1, + HeapBasedNarrowOop = 2 + }; + static NARROW_OOP_MODE narrow_oop_mode(); + static const char* narrow_oop_mode_to_string(NARROW_OOP_MODE mode); + static char* preferred_heap_base(size_t heap_size, NARROW_OOP_MODE mode); + static char* preferred_metaspace_base(size_t heap_size, NARROW_OOP_MODE mode); static address narrow_oop_base() { return _narrow_oop._base; } static bool is_narrow_oop_base(void* addr) { return (narrow_oop_base() == (address)addr); } static int narrow_oop_shift() { return _narrow_oop._shift; } diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/share/vm/oops/instanceKlass.hpp --- a/hotspot/src/share/vm/oops/instanceKlass.hpp Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/src/share/vm/oops/instanceKlass.hpp Wed Jul 05 18:59:39 2017 +0200 @@ -26,6 +26,7 @@ #define SHARE_VM_OOPS_INSTANCEKLASS_HPP #include "classfile/classLoaderData.hpp" +#include "memory/referenceType.hpp" #include "oops/annotations.hpp" #include "oops/constMethod.hpp" #include "oops/fieldInfo.hpp" @@ -37,6 +38,7 @@ #include "utilities/accessFlags.hpp" #include "utilities/bitMap.inline.hpp" #include "utilities/macros.hpp" +#include "trace/traceMacros.hpp" // An InstanceKlass is the VM level representation of a Java class. // It contains all information needed for at class at execution runtime. diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/share/vm/oops/klass.cpp --- a/hotspot/src/share/vm/oops/klass.cpp Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/src/share/vm/oops/klass.cpp Wed Jul 05 18:59:39 2017 +0200 @@ -37,6 +37,7 @@ #include "oops/klass.inline.hpp" #include "oops/oop.inline2.hpp" #include "runtime/atomic.hpp" +#include "trace/traceMacros.hpp" #include "utilities/stack.hpp" #include "utilities/macros.hpp" #if INCLUDE_ALL_GCS @@ -168,7 +169,7 @@ set_next_sibling(NULL); set_next_link(NULL); set_alloc_count(0); - TRACE_SET_KLASS_TRACE_ID(this, 0); + TRACE_INIT_ID(this); set_prototype_header(markOopDesc::prototype()); set_biased_lock_revocation_count(0); diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/share/vm/opto/compile.cpp --- a/hotspot/src/share/vm/opto/compile.cpp Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/src/share/vm/opto/compile.cpp Wed Jul 05 18:59:39 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -63,6 +63,7 @@ #include "runtime/signature.hpp" #include "runtime/stubRoutines.hpp" #include "runtime/timer.hpp" +#include "trace/tracing.hpp" #include "utilities/copy.hpp" #ifdef TARGET_ARCH_MODEL_x86_32 # include "adfiles/ad_x86_32.hpp" @@ -786,7 +787,7 @@ if (failing()) return; - print_method("Before RemoveUseless", 3); + print_method(PHASE_BEFORE_REMOVEUSELESS, 3); // Remove clutter produced by parsing. if (!failing()) { @@ -1801,9 +1802,9 @@ { ResourceMark rm; - print_method("Before StringOpts", 3); + print_method(PHASE_BEFORE_STRINGOPTS, 3); PhaseStringOpts pso(initial_gvn(), for_igvn()); - print_method("After StringOpts", 3); + print_method(PHASE_AFTER_STRINGOPTS, 3); } // now inline anything that we skipped the first time around @@ -1958,7 +1959,7 @@ NOT_PRODUCT( verify_graph_edges(); ) - print_method("After Parsing"); + print_method(PHASE_AFTER_PARSING); { // Iterative Global Value Numbering, including ideal transforms @@ -1969,7 +1970,7 @@ igvn.optimize(); } - print_method("Iter GVN 1", 2); + print_method(PHASE_ITER_GVN1, 2); if (failing()) return; @@ -1978,7 +1979,7 @@ inline_incrementally(igvn); } - print_method("Incremental Inline", 2); + print_method(PHASE_INCREMENTAL_INLINE, 2); if (failing()) return; @@ -1987,7 +1988,7 @@ // Inline valueOf() methods now. inline_boxing_calls(igvn); - print_method("Incremental Boxing Inline", 2); + print_method(PHASE_INCREMENTAL_BOXING_INLINE, 2); if (failing()) return; } @@ -2002,7 +2003,7 @@ // Cleanup graph (remove dead nodes). TracePhase t2("idealLoop", &_t_idealLoop, true); PhaseIdealLoop ideal_loop( igvn, false, true ); - if (major_progress()) print_method("PhaseIdealLoop before EA", 2); + if (major_progress()) print_method(PHASE_PHASEIDEAL_BEFORE_EA, 2); if (failing()) return; } ConnectionGraph::do_analysis(this, &igvn); @@ -2011,7 +2012,7 @@ // Optimize out fields loads from scalar replaceable allocations. igvn.optimize(); - print_method("Iter GVN after EA", 2); + print_method(PHASE_ITER_GVN_AFTER_EA, 2); if (failing()) return; @@ -2022,7 +2023,7 @@ igvn.set_delay_transform(false); igvn.optimize(); - print_method("Iter GVN after eliminating allocations and locks", 2); + print_method(PHASE_ITER_GVN_AFTER_ELIMINATION, 2); if (failing()) return; } @@ -2038,7 +2039,7 @@ TracePhase t2("idealLoop", &_t_idealLoop, true); PhaseIdealLoop ideal_loop( igvn, true ); loop_opts_cnt--; - if (major_progress()) print_method("PhaseIdealLoop 1", 2); + if (major_progress()) print_method(PHASE_PHASEIDEALLOOP1, 2); if (failing()) return; } // Loop opts pass if partial peeling occurred in previous pass @@ -2046,7 +2047,7 @@ TracePhase t3("idealLoop", &_t_idealLoop, true); PhaseIdealLoop ideal_loop( igvn, false ); loop_opts_cnt--; - if (major_progress()) print_method("PhaseIdealLoop 2", 2); + if (major_progress()) print_method(PHASE_PHASEIDEALLOOP2, 2); if (failing()) return; } // Loop opts pass for loop-unrolling before CCP @@ -2054,7 +2055,7 @@ TracePhase t4("idealLoop", &_t_idealLoop, true); PhaseIdealLoop ideal_loop( igvn, false ); loop_opts_cnt--; - if (major_progress()) print_method("PhaseIdealLoop 3", 2); + if (major_progress()) print_method(PHASE_PHASEIDEALLOOP3, 2); } if (!failing()) { // Verify that last round of loop opts produced a valid graph @@ -2071,7 +2072,7 @@ TracePhase t2("ccp", &_t_ccp, true); ccp.do_transform(); } - print_method("PhaseCPP 1", 2); + print_method(PHASE_CPP1, 2); assert( true, "Break here to ccp.dump_old2new_map()"); @@ -2082,7 +2083,7 @@ igvn.optimize(); } - print_method("Iter GVN 2", 2); + print_method(PHASE_ITER_GVN2, 2); if (failing()) return; @@ -2095,7 +2096,7 @@ assert( cnt++ < 40, "infinite cycle in loop optimization" ); PhaseIdealLoop ideal_loop( igvn, true); loop_opts_cnt--; - if (major_progress()) print_method("PhaseIdealLoop iterations", 2); + if (major_progress()) print_method(PHASE_PHASEIDEALLOOP_ITERATIONS, 2); if (failing()) return; } } @@ -2128,7 +2129,7 @@ } } - print_method("Optimize finished", 2); + print_method(PHASE_OPTIMIZE_FINISHED, 2); } @@ -2176,7 +2177,7 @@ cfg.GlobalCodeMotion(m,unique(),proj_list); if (failing()) return; - print_method("Global code motion", 2); + print_method(PHASE_GLOBAL_CODE_MOTION, 2); NOT_PRODUCT( verify_graph_edges(); ) @@ -2229,7 +2230,7 @@ Output(); } - print_method("Final Code"); + print_method(PHASE_FINAL_CODE); // He's dead, Jim. _cfg = (PhaseCFG*)0xdeadbeef; @@ -3316,8 +3317,16 @@ // Record the first failure reason. _failure_reason = reason; } + + EventCompilerFailure event; + if (event.should_commit()) { + event.set_compileID(Compile::compile_id()); + event.set_failure(reason); + event.commit(); + } + if (!C->failure_reason_is(C2Compiler::retry_no_subsuming_loads())) { - C->print_method(_failure_reason); + C->print_method(PHASE_FAILURE); } _root = NULL; // flush the graph, too } diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/share/vm/opto/compile.hpp --- a/hotspot/src/share/vm/opto/compile.hpp Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/src/share/vm/opto/compile.hpp Wed Jul 05 18:59:39 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -36,10 +36,12 @@ #include "libadt/vectset.hpp" #include "memory/resourceArea.hpp" #include "opto/idealGraphPrinter.hpp" +#include "opto/phasetype.hpp" #include "opto/phase.hpp" #include "opto/regmask.hpp" #include "runtime/deoptimization.hpp" #include "runtime/vmThread.hpp" +#include "trace/tracing.hpp" class Block; class Bundle; @@ -322,6 +324,7 @@ IdealGraphPrinter* _printer; #endif + // Node management uint _unique; // Counter for unique Node indices VectorSet _dead_node_list; // Set of dead nodes @@ -573,17 +576,43 @@ bool has_method_handle_invokes() const { return _has_method_handle_invokes; } void set_has_method_handle_invokes(bool z) { _has_method_handle_invokes = z; } + jlong _latest_stage_start_counter; + void begin_method() { #ifndef PRODUCT if (_printer) _printer->begin_method(this); #endif + C->_latest_stage_start_counter = os::elapsed_counter(); } - void print_method(const char * name, int level = 1) { + + void print_method(CompilerPhaseType cpt, int level = 1) { + EventCompilerPhase event(UNTIMED); + if (event.should_commit()) { + event.set_starttime(C->_latest_stage_start_counter); + event.set_endtime(os::elapsed_counter()); + event.set_phase((u1) cpt); + event.set_compileID(C->_compile_id); + event.set_phaseLevel(level); + event.commit(); + } + + #ifndef PRODUCT - if (_printer) _printer->print_method(this, name, level); + if (_printer) _printer->print_method(this, CompilerPhaseTypeHelper::to_string(cpt), level); #endif + C->_latest_stage_start_counter = os::elapsed_counter(); } - void end_method() { + + void end_method(int level = 1) { + EventCompilerPhase event(UNTIMED); + if (event.should_commit()) { + event.set_starttime(C->_latest_stage_start_counter); + event.set_endtime(os::elapsed_counter()); + event.set_phase((u1) PHASE_END); + event.set_compileID(C->_compile_id); + event.set_phaseLevel(level); + event.commit(); + } #ifndef PRODUCT if (_printer) _printer->end_method(); #endif diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/share/vm/opto/escape.cpp --- a/hotspot/src/share/vm/opto/escape.cpp Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/src/share/vm/opto/escape.cpp Wed Jul 05 18:59:39 2017 +0200 @@ -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 @@ -277,7 +277,7 @@ // scalar replaceable objects. split_unique_types(alloc_worklist); if (C->failing()) return false; - C->print_method("After Escape Analysis", 2); + C->print_method(PHASE_AFTER_EA, 2); #ifdef ASSERT } else if (Verbose && (PrintEscapeAnalysis || PrintEliminateAllocations)) { diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/share/vm/opto/library_call.cpp --- a/hotspot/src/share/vm/opto/library_call.cpp Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/src/share/vm/opto/library_call.cpp Wed Jul 05 18:59:39 2017 +0200 @@ -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 @@ -38,6 +38,7 @@ #include "opto/subnode.hpp" #include "prims/nativeLookup.hpp" #include "runtime/sharedRuntime.hpp" +#include "trace/traceMacros.hpp" class LibraryIntrinsic : public InlineCallGenerator { // Extend the set of intrinsics known to the runtime: diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/share/vm/opto/loopnode.cpp --- a/hotspot/src/share/vm/opto/loopnode.cpp Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/src/share/vm/opto/loopnode.cpp Wed Jul 05 18:59:39 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 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 @@ -440,7 +440,7 @@ // ---- SUCCESS! Found A Trip-Counted Loop! ----- // assert(x->Opcode() == Op_Loop, "regular loops only"); - C->print_method("Before CountedLoop", 3); + C->print_method(PHASE_BEFORE_CLOOPS, 3); Node *hook = new (C) Node(6); @@ -791,7 +791,7 @@ } #endif - C->print_method("After CountedLoop", 3); + C->print_method(PHASE_AFTER_CLOOPS, 3); return true; } @@ -2164,7 +2164,7 @@ // Split shared headers and insert loop landing pads. // Do not bother doing this on the Root loop of course. if( !_verify_me && !_verify_only && _ltree_root->_child ) { - C->print_method("Before beautify loops", 3); + C->print_method(PHASE_BEFORE_BEAUTIFY_LOOPS, 3); if( _ltree_root->_child->beautify_loops( this ) ) { // Re-build loop tree! _ltree_root->_child = NULL; @@ -2178,7 +2178,7 @@ // Reset loop nesting depth _ltree_root->set_nest( 0 ); - C->print_method("After beautify loops", 3); + C->print_method(PHASE_AFTER_BEAUTIFY_LOOPS, 3); } } diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/share/vm/opto/matcher.cpp --- a/hotspot/src/share/vm/opto/matcher.cpp Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/src/share/vm/opto/matcher.cpp Wed Jul 05 18:59:39 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -317,7 +317,7 @@ find_shared( C->root() ); find_shared( C->top() ); - C->print_method("Before Matching"); + C->print_method(PHASE_BEFORE_MATCHING); // Create new ideal node ConP #NULL even if it does exist in old space // to avoid false sharing if the corresponding mach node is not used. @@ -1848,7 +1848,7 @@ for( uint i=0; kid != NULL && i<2; kid = s->_kids[1], i++ ) { // binary tree int newrule; - if( i == 0 ) + if( i == 0) newrule = kid->_rule[_leftOp[rule]]; else newrule = kid->_rule[_rightOp[rule]]; diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/share/vm/opto/phasetype.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/src/share/vm/opto/phasetype.hpp Wed Jul 05 18:59:39 2017 +0200 @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2012, 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. + * + */ + +#ifndef SHARE_VM_OPTO_PHASETYPE_HPP +#define SHARE_VM_OPTO_PHASETYPE_HPP + +enum CompilerPhaseType { + PHASE_BEFORE_STRINGOPTS, + PHASE_AFTER_STRINGOPTS, + PHASE_BEFORE_REMOVEUSELESS, + PHASE_AFTER_PARSING, + PHASE_ITER_GVN1, + PHASE_PHASEIDEAL_BEFORE_EA, + PHASE_ITER_GVN_AFTER_EA, + PHASE_ITER_GVN_AFTER_ELIMINATION, + PHASE_PHASEIDEALLOOP1, + PHASE_PHASEIDEALLOOP2, + PHASE_PHASEIDEALLOOP3, + PHASE_CPP1, + PHASE_ITER_GVN2, + PHASE_PHASEIDEALLOOP_ITERATIONS, + PHASE_OPTIMIZE_FINISHED, + PHASE_GLOBAL_CODE_MOTION, + PHASE_FINAL_CODE, + PHASE_AFTER_EA, + PHASE_BEFORE_CLOOPS, + PHASE_AFTER_CLOOPS, + PHASE_BEFORE_BEAUTIFY_LOOPS, + PHASE_AFTER_BEAUTIFY_LOOPS, + PHASE_BEFORE_MATCHING, + PHASE_INCREMENTAL_INLINE, + PHASE_INCREMENTAL_BOXING_INLINE, + PHASE_END, + PHASE_FAILURE, + + PHASE_NUM_TYPES +}; + +class CompilerPhaseTypeHelper { + public: + static const char* to_string(CompilerPhaseType cpt) { + switch (cpt) { + case PHASE_BEFORE_STRINGOPTS: return "Before StringOpts"; + case PHASE_AFTER_STRINGOPTS: return "After StringOpts"; + case PHASE_BEFORE_REMOVEUSELESS: return "Before RemoveUseless"; + case PHASE_AFTER_PARSING: return "After Parsing"; + case PHASE_ITER_GVN1: return "Iter GVN 1"; + case PHASE_PHASEIDEAL_BEFORE_EA: return "PhaseIdealLoop before EA"; + case PHASE_ITER_GVN_AFTER_EA: return "Iter GVN after EA"; + case PHASE_ITER_GVN_AFTER_ELIMINATION: return "Iter GVN after eliminating allocations and locks"; + case PHASE_PHASEIDEALLOOP1: return "PhaseIdealLoop 1"; + case PHASE_PHASEIDEALLOOP2: return "PhaseIdealLoop 2"; + case PHASE_PHASEIDEALLOOP3: return "PhaseIdealLoop 3"; + case PHASE_CPP1: return "PhaseCPP 1"; + case PHASE_ITER_GVN2: return "Iter GVN 2"; + case PHASE_PHASEIDEALLOOP_ITERATIONS: return "PhaseIdealLoop iterations"; + case PHASE_OPTIMIZE_FINISHED: return "Optimize finished"; + case PHASE_GLOBAL_CODE_MOTION: return "Global code motion"; + case PHASE_FINAL_CODE: return "Final Code"; + case PHASE_AFTER_EA: return "After Escape Analysis"; + case PHASE_BEFORE_CLOOPS: return "Before CountedLoop"; + case PHASE_AFTER_CLOOPS: return "After CountedLoop"; + case PHASE_BEFORE_BEAUTIFY_LOOPS: return "Before beautify loops"; + case PHASE_AFTER_BEAUTIFY_LOOPS: return "After beautify loops"; + case PHASE_BEFORE_MATCHING: return "Before Matching"; + case PHASE_INCREMENTAL_INLINE: return "Incremental Inline"; + case PHASE_INCREMENTAL_BOXING_INLINE: return "Incremental Boxing Inline"; + case PHASE_END: return "End"; + case PHASE_FAILURE: return "Failure"; + default: + ShouldNotReachHere(); + return NULL; + } + } +}; + +#endif //SHARE_VM_OPTO_PHASETYPE_HPP diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/share/vm/precompiled/precompiled.hpp --- a/hotspot/src/share/vm/precompiled/precompiled.hpp Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/src/share/vm/precompiled/precompiled.hpp Wed Jul 05 18:59:39 2017 +0200 @@ -26,7 +26,6 @@ // or if the user passes USE_PRECOMPILED_HEADER=0 to the makefiles. #ifndef DONT_USE_PRECOMPILED_HEADER - # include "asm/assembler.hpp" # include "asm/assembler.inline.hpp" # include "asm/codeBuffer.hpp" diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/share/vm/prims/jni.cpp --- a/hotspot/src/share/vm/prims/jni.cpp Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/src/share/vm/prims/jni.cpp Wed Jul 05 18:59:39 2017 +0200 @@ -74,7 +74,6 @@ #include "runtime/vm_operations.hpp" #include "services/runtimeService.hpp" #include "trace/tracing.hpp" -#include "trace/traceEventTypes.hpp" #include "utilities/defaultStream.hpp" #include "utilities/dtrace.hpp" #include "utilities/events.hpp" @@ -5014,6 +5013,7 @@ #ifndef PRODUCT +#include "gc_implementation/shared/gcTimer.hpp" #include "gc_interface/collectedHeap.hpp" #if INCLUDE_ALL_GCS #include "gc_implementation/g1/heapRegionRemSet.hpp" @@ -5031,6 +5031,7 @@ if (ExecuteInternalVMTests) { tty->print_cr("Running internal VM tests"); run_unit_test(GlobalDefinitions::test_globals()); + run_unit_test(GCTimerAllTest::all()); run_unit_test(arrayOopDesc::test_max_array_length()); run_unit_test(CollectedHeap::test_is_in()); run_unit_test(QuickSort::test_quick_sort()); @@ -5131,9 +5132,11 @@ JvmtiExport::post_thread_start(thread); } - EVENT_BEGIN(TraceEventThreadStart, event); - EVENT_COMMIT(event, - EVENT_SET(event, javalangthread, java_lang_Thread::thread_id(thread->threadObj()))); + EventThreadStart event; + if (event.should_commit()) { + event.set_javalangthread(java_lang_Thread::thread_id(thread->threadObj())); + event.commit(); + } // Check if we should compile all classes on bootclasspath NOT_PRODUCT(if (CompileTheWorld) ClassLoader::compile_the_world();) @@ -5334,9 +5337,11 @@ JvmtiExport::post_thread_start(thread); } - EVENT_BEGIN(TraceEventThreadStart, event); - EVENT_COMMIT(event, - EVENT_SET(event, javalangthread, java_lang_Thread::thread_id(thread->threadObj()))); + EventThreadStart event; + if (event.should_commit()) { + event.set_javalangthread(java_lang_Thread::thread_id(thread->threadObj())); + event.commit(); + } *(JNIEnv**)penv = thread->jni_environment(); diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/share/vm/prims/jvm.cpp --- a/hotspot/src/share/vm/prims/jvm.cpp Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/src/share/vm/prims/jvm.cpp Wed Jul 05 18:59:39 2017 +0200 @@ -59,6 +59,7 @@ #include "services/attachListener.hpp" #include "services/management.hpp" #include "services/threadService.hpp" +#include "trace/tracing.hpp" #include "utilities/copy.hpp" #include "utilities/defaultStream.hpp" #include "utilities/dtrace.hpp" @@ -2999,6 +3000,8 @@ millis); #endif /* USDT2 */ + EventThreadSleep event; + if (millis == 0) { // When ConvertSleepToYield is on, this matches the classic VM implementation of // JVM_Sleep. Critical for similar threading behaviour (Win32) @@ -3019,6 +3022,10 @@ // An asynchronous exception (e.g., ThreadDeathException) could have been thrown on // us while we were sleeping. We do not overwrite those. if (!HAS_PENDING_EXCEPTION) { + if (event.should_commit()) { + event.set_time(millis); + event.commit(); + } #ifndef USDT2 HS_DTRACE_PROBE1(hotspot, thread__sleep__end,1); #else /* USDT2 */ @@ -3032,6 +3039,10 @@ } thread->osthread()->set_state(old_state); } + if (event.should_commit()) { + event.set_time(millis); + event.commit(); + } #ifndef USDT2 HS_DTRACE_PROBE1(hotspot, thread__sleep__end,0); #else /* USDT2 */ diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/share/vm/prims/jvmtiGen.java --- a/hotspot/src/share/vm/prims/jvmtiGen.java Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/src/share/vm/prims/jvmtiGen.java Wed Jul 05 18:59:39 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2005, 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 @@ -31,7 +31,6 @@ import org.xml.sax.SAXParseException; import org.w3c.dom.Document; import org.w3c.dom.DOMException; - // For write operation import javax.xml.transform.Transformer; import javax.xml.transform.TransformerException; @@ -129,6 +128,7 @@ factory.setNamespaceAware(true); factory.setValidating(true); + factory.setXIncludeAware(true); try { File datafile = new File(inFileName); diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/share/vm/prims/jvmtiImpl.cpp --- a/hotspot/src/share/vm/prims/jvmtiImpl.cpp Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/src/share/vm/prims/jvmtiImpl.cpp Wed Jul 05 18:59:39 2017 +0200 @@ -360,19 +360,14 @@ case CLEAR_BREAKPOINT: _breakpoints->clear_at_safepoint(*_bp); break; - case CLEAR_ALL_BREAKPOINT: - _breakpoints->clearall_at_safepoint(); - break; default: assert(false, "Unknown operation"); } } void VM_ChangeBreakpoints::oops_do(OopClosure* f) { - // This operation keeps breakpoints alive - if (_breakpoints != NULL) { - _breakpoints->oops_do(f); - } + // The JvmtiBreakpoints in _breakpoints will be visited via + // JvmtiExport::oops_do. if (_bp != NULL) { _bp->oops_do(f); } @@ -433,23 +428,13 @@ } } -void JvmtiBreakpoints::clearall_at_safepoint() { - assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint"); - - int len = _bps.length(); - for (int i=0; iparker(), (int) isAbsolute, time); #else /* USDT2 */ @@ -1218,6 +1220,13 @@ HOTSPOT_THREAD_PARK_END( (uintptr_t) thread->parker()); #endif /* USDT2 */ + if (event.should_commit()) { + oop obj = thread->current_park_blocker(); + event.set_klass(obj ? obj->klass() : NULL); + event.set_timeout(time); + event.set_address(obj ? (TYPE_ADDRESS) (uintptr_t) obj : 0); + event.commit(); + } UNSAFE_END UNSAFE_ENTRY(void, Unsafe_Unpark(JNIEnv *env, jobject unsafe, jobject jthread)) diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/share/vm/runtime/frame.hpp --- a/hotspot/src/share/vm/runtime/frame.hpp Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/src/share/vm/runtime/frame.hpp Wed Jul 05 18:59:39 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -134,6 +134,7 @@ bool is_interpreted_frame() const; bool is_java_frame() const; bool is_entry_frame() const; // Java frame called from C? + bool is_stub_frame() const; bool is_ignored_frame() const; bool is_native_frame() const; bool is_runtime_frame() const; diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/share/vm/runtime/frame.inline.hpp --- a/hotspot/src/share/vm/runtime/frame.inline.hpp Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/src/share/vm/runtime/frame.inline.hpp Wed Jul 05 18:59:39 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -79,6 +79,10 @@ return StubRoutines::returns_to_call_stub(pc()); } +inline bool frame::is_stub_frame() const { + return StubRoutines::is_stub_code(pc()) || (_cb != NULL && _cb->is_adapter_blob()); +} + inline bool frame::is_first_frame() const { return is_entry_frame() && entry_frame_is_first(); } diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/share/vm/runtime/globals.hpp --- a/hotspot/src/share/vm/runtime/globals.hpp Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/src/share/vm/runtime/globals.hpp Wed Jul 05 18:59:39 2017 +0200 @@ -2311,6 +2311,10 @@ "Print diagnostic message when GC is stalled" \ "by JNI critical section") \ \ + experimental(double, ObjectCountCutOffPercent, 0.5, \ + "The percentage of the used heap that the instances of a class " \ + "must occupy for the class to generate a trace event.") \ + \ /* GC log rotation setting */ \ \ product(bool, UseGCLogFileRotation, false, \ @@ -3688,7 +3692,13 @@ experimental(uintx, ArrayAllocatorMallocLimit, \ SOLARIS_ONLY(64*K) NOT_SOLARIS(max_uintx), \ "Allocation less than this value will be allocated " \ - "using malloc. Larger allocations will use mmap.") + "using malloc. Larger allocations will use mmap.") \ + \ + product(bool, EnableTracing, false, \ + "Enable event-based tracing") \ + product(bool, UseLockedTracing, false, \ + "Use locked-tracing when doing event-based tracing") + /* * Macros for factoring of globals diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/share/vm/runtime/java.cpp --- a/hotspot/src/share/vm/runtime/java.cpp Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/src/share/vm/runtime/java.cpp Wed Jul 05 18:59:39 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -60,7 +60,6 @@ #include "services/memReporter.hpp" #include "services/memTracker.hpp" #include "trace/tracing.hpp" -#include "trace/traceEventTypes.hpp" #include "utilities/dtrace.hpp" #include "utilities/globalDefinitions.hpp" #include "utilities/histogram.hpp" @@ -528,9 +527,12 @@ JvmtiExport::post_thread_end(thread); } - EVENT_BEGIN(TraceEventThreadEnd, event); - EVENT_COMMIT(event, - EVENT_SET(event, javalangthread, java_lang_Thread::thread_id(thread->threadObj()))); + + EventThreadEnd event; + if (event.should_commit()) { + event.set_javalangthread(java_lang_Thread::thread_id(thread->threadObj())); + event.commit(); + } // Always call even when there are not JVMTI environments yet, since environments // may be attached late and JVMTI must track phases of VM execution diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/share/vm/runtime/mutexLocker.cpp --- a/hotspot/src/share/vm/runtime/mutexLocker.cpp Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/src/share/vm/runtime/mutexLocker.cpp Wed Jul 05 18:59:39 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -270,13 +270,12 @@ def(MethodCompileQueue_lock , Monitor, nonleaf+4, true ); def(Debug2_lock , Mutex , nonleaf+4, true ); def(Debug3_lock , Mutex , nonleaf+4, true ); - def(ProfileVM_lock , Monitor, nonleaf+4, false); // used for profiling of the VMThread + def(ProfileVM_lock , Monitor, special, false); // used for profiling of the VMThread def(CompileThread_lock , Monitor, nonleaf+5, false ); - def(JfrQuery_lock , Monitor, nonleaf, true); // JFR locks, keep these in consecutive order - def(JfrMsg_lock , Monitor, nonleaf+2, true); - def(JfrBuffer_lock , Mutex, nonleaf+3, true); - def(JfrStream_lock , Mutex, nonleaf+4, true); + def(JfrMsg_lock , Monitor, leaf, true); + def(JfrBuffer_lock , Mutex, nonleaf+1, true); + def(JfrStream_lock , Mutex, nonleaf+2, true); def(PeriodicTask_lock , Monitor, nonleaf+5, true); } diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/share/vm/runtime/objectMonitor.cpp --- a/hotspot/src/share/vm/runtime/objectMonitor.cpp Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/src/share/vm/runtime/objectMonitor.cpp Wed Jul 05 18:59:39 2017 +0200 @@ -36,7 +36,10 @@ #include "runtime/stubRoutines.hpp" #include "runtime/thread.inline.hpp" #include "services/threadService.hpp" +#include "trace/tracing.hpp" +#include "trace/traceMacros.hpp" #include "utilities/dtrace.hpp" +#include "utilities/macros.hpp" #include "utilities/preserveException.hpp" #ifdef TARGET_OS_FAMILY_linux # include "os_linux.inline.hpp" @@ -371,6 +374,8 @@ // Ensure the object-monitor relationship remains stable while there's contention. Atomic::inc_ptr(&_count); + EventJavaMonitorEnter event; + { // Change java thread status to indicate blocked on monitor enter. JavaThreadBlockedOnMonitorEnterState jtbmes(jt, this); @@ -402,7 +407,7 @@ // _recursions = 0 ; _succ = NULL ; - exit (Self) ; + exit (false, Self) ; jt->java_suspend_self(); } @@ -435,6 +440,14 @@ if (JvmtiExport::should_post_monitor_contended_entered()) { JvmtiExport::post_monitor_contended_entered(jt, this); } + + if (event.should_commit()) { + event.set_klass(((oop)this->object())->klass()); + event.set_previousOwner((TYPE_JAVALANGTHREAD)_previous_owner_tid); + event.set_address((TYPE_ADDRESS)(uintptr_t)(this->object_addr())); + event.commit(); + } + if (ObjectMonitor::_sync_ContendedLockAttempts != NULL) { ObjectMonitor::_sync_ContendedLockAttempts->inc() ; } @@ -917,7 +930,7 @@ // Both impinge on OS scalability. Given that, at most one thread parked on // a monitor will use a timer. -void ATTR ObjectMonitor::exit(TRAPS) { +void ATTR ObjectMonitor::exit(bool not_suspended, TRAPS) { Thread * Self = THREAD ; if (THREAD != _owner) { if (THREAD->is_lock_owned((address) _owner)) { @@ -954,6 +967,14 @@ _Responsible = NULL ; } +#if INCLUDE_TRACE + // get the owner's thread id for the MonitorEnter event + // if it is enabled and the thread isn't suspended + if (not_suspended && Tracing::is_event_enabled(TraceJavaMonitorEnterEvent)) { + _previous_owner_tid = SharedRuntime::get_java_tid(Self); + } +#endif + for (;;) { assert (THREAD == _owner, "invariant") ; @@ -1343,7 +1364,7 @@ guarantee(Self == _owner, "complete_exit not owner"); intptr_t save = _recursions; // record the old recursion count _recursions = 0; // set the recursion level to be 0 - exit (Self) ; // exit the monitor + exit (true, Self) ; // exit the monitor guarantee (_owner != Self, "invariant"); return save; } @@ -1397,6 +1418,20 @@ for (v = *adr ; Atomic::cmpxchg (v + dx, adr, v) != v; v = *adr) ; return v ; } + +// helper method for posting a monitor wait event +void ObjectMonitor::post_monitor_wait_event(EventJavaMonitorWait* event, + jlong notifier_tid, + jlong timeout, + bool timedout) { + event->set_klass(((oop)this->object())->klass()); + event->set_timeout((TYPE_ULONG)timeout); + event->set_address((TYPE_ADDRESS)(uintptr_t)(this->object_addr())); + event->set_notifier((TYPE_OSTHREAD)notifier_tid); + event->set_timedOut((TYPE_BOOLEAN)timedout); + event->commit(); +} + // ----------------------------------------------------------------------------- // Wait/Notify/NotifyAll // @@ -1412,6 +1447,8 @@ // Throw IMSX or IEX. CHECK_OWNER(); + EventJavaMonitorWait event; + // check for a pending interrupt if (interruptible && Thread::is_interrupted(Self, true) && !HAS_PENDING_EXCEPTION) { // post monitor waited event. Note that this is past-tense, we are done waiting. @@ -1420,10 +1457,14 @@ // wait was not timed out due to thread interrupt. JvmtiExport::post_monitor_waited(jt, this, false); } + if (event.should_commit()) { + post_monitor_wait_event(&event, 0, millis, false); + } TEVENT (Wait - Throw IEX) ; THROW(vmSymbols::java_lang_InterruptedException()); return ; } + TEVENT (Wait) ; assert (Self->_Stalled == 0, "invariant") ; @@ -1455,7 +1496,7 @@ intptr_t save = _recursions; // record the old recursion count _waiters++; // increment the number of waiters _recursions = 0; // set the recursion level to be 1 - exit (Self) ; // exit the monitor + exit (true, Self) ; // exit the monitor guarantee (_owner != Self, "invariant") ; // As soon as the ObjectMonitor's ownership is dropped in the exit() @@ -1555,6 +1596,11 @@ if (JvmtiExport::should_post_monitor_waited()) { JvmtiExport::post_monitor_waited(jt, this, ret == OS_TIMEOUT); } + + if (event.should_commit()) { + post_monitor_wait_event(&event, node._notifier_tid, millis, ret == OS_TIMEOUT); + } + OrderAccess::fence() ; assert (Self->_Stalled != 0, "invariant") ; @@ -1634,6 +1680,8 @@ iterator->TState = ObjectWaiter::TS_ENTER ; } iterator->_notified = 1 ; + Thread * Self = THREAD; + iterator->_notifier_tid = Self->osthread()->thread_id(); ObjectWaiter * List = _EntryList ; if (List != NULL) { @@ -1758,6 +1806,8 @@ guarantee (iterator->TState == ObjectWaiter::TS_WAIT, "invariant") ; guarantee (iterator->_notified == 0, "invariant") ; iterator->_notified = 1 ; + Thread * Self = THREAD; + iterator->_notifier_tid = Self->osthread()->thread_id(); if (Policy != 4) { iterator->TState = ObjectWaiter::TS_ENTER ; } diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/share/vm/runtime/objectMonitor.hpp --- a/hotspot/src/share/vm/runtime/objectMonitor.hpp Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/src/share/vm/runtime/objectMonitor.hpp Wed Jul 05 18:59:39 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 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 @@ -29,7 +29,6 @@ #include "runtime/park.hpp" #include "runtime/perfData.hpp" - // ObjectWaiter serves as a "proxy" or surrogate thread. // TODO-FIXME: Eliminate ObjectWaiter and use the thread-specific // ParkEvent instead. Beware, however, that the JVMTI code @@ -43,6 +42,7 @@ ObjectWaiter * volatile _next; ObjectWaiter * volatile _prev; Thread* _thread; + jlong _notifier_tid; ParkEvent * _event; volatile int _notified ; volatile TStates TState ; @@ -55,6 +55,9 @@ void wait_reenter_end(ObjectMonitor *mon); }; +// forward declaration to avoid include tracing.hpp +class EventJavaMonitorWait; + // WARNING: // This is a very sensitive and fragile class. DO NOT make any // change unless you are fully aware of the underlying semantics. @@ -151,6 +154,7 @@ _SpinFreq = 0 ; _SpinClock = 0 ; OwnerIsThread = 0 ; + _previous_owner_tid = 0; } ~ObjectMonitor() { @@ -192,7 +196,7 @@ bool try_enter (TRAPS) ; void enter(TRAPS); - void exit(TRAPS); + void exit(bool not_suspended, TRAPS); void wait(jlong millis, bool interruptable, TRAPS); void notify(TRAPS); void notifyAll(TRAPS); @@ -218,6 +222,10 @@ void ctAsserts () ; void ExitEpilog (Thread * Self, ObjectWaiter * Wakee) ; bool ExitSuspendEquivalent (JavaThread * Self) ; + void post_monitor_wait_event(EventJavaMonitorWait * event, + jlong notifier_tid, + jlong timeout, + bool timedout); private: friend class ObjectSynchronizer; @@ -240,6 +248,7 @@ protected: // protected for jvmtiRawMonitor void * volatile _owner; // pointer to owning thread OR BasicLock + volatile jlong _previous_owner_tid; // thread id of the previous owner of the monitor volatile intptr_t _recursions; // recursion count, 0 for first entry private: int OwnerIsThread ; // _owner is (Thread *) vs SP/BasicLock diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/share/vm/runtime/os.cpp --- a/hotspot/src/share/vm/runtime/os.cpp Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/src/share/vm/runtime/os.cpp Wed Jul 05 18:59:39 2017 +0200 @@ -265,8 +265,7 @@ VMThread::execute(&op1); Universe::print_heap_at_SIGBREAK(); if (PrintClassHistogram) { - VM_GC_HeapInspection op1(gclog_or_tty, true /* force full GC before heap inspection */, - true /* need_prologue */); + VM_GC_HeapInspection op1(gclog_or_tty, true /* force full GC before heap inspection */); VMThread::execute(&op1); } if (JvmtiExport::should_post_data_dump()) { @@ -1444,11 +1443,16 @@ return (int) i; } +void os::SuspendedThreadTask::run() { + assert(Threads_lock->owned_by_self() || (_thread == VMThread::vm_thread()), "must have threads lock to call this"); + internal_do_task(); + _done = true; +} + bool os::create_stack_guard_pages(char* addr, size_t bytes) { return os::pd_create_stack_guard_pages(addr, bytes); } - char* os::reserve_memory(size_t bytes, char* addr, size_t alignment_hint) { char* result = pd_reserve_memory(bytes, addr, alignment_hint); if (result != NULL) { @@ -1551,3 +1555,19 @@ pd_realign_memory(addr, bytes, alignment_hint); } +#ifndef TARGET_OS_FAMILY_windows +/* try to switch state from state "from" to state "to" + * returns the state set after the method is complete + */ +os::SuspendResume::State os::SuspendResume::switch_state(os::SuspendResume::State from, + os::SuspendResume::State to) +{ + os::SuspendResume::State result = + (os::SuspendResume::State) Atomic::cmpxchg((jint) to, (jint *) &_state, (jint) from); + if (result == from) { + // success + return to; + } + return result; +} +#endif diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/share/vm/runtime/os.hpp --- a/hotspot/src/share/vm/runtime/os.hpp Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/src/share/vm/runtime/os.hpp Wed Jul 05 18:59:39 2017 +0200 @@ -781,6 +781,104 @@ // ResumeThread call) static void pause(); + class SuspendedThreadTaskContext { + public: + SuspendedThreadTaskContext(Thread* thread, void *ucontext) : _thread(thread), _ucontext(ucontext) {} + Thread* thread() const { return _thread; } + void* ucontext() const { return _ucontext; } + private: + Thread* _thread; + void* _ucontext; + }; + + class SuspendedThreadTask { + public: + SuspendedThreadTask(Thread* thread) : _thread(thread), _done(false) {} + virtual ~SuspendedThreadTask() {} + void run(); + bool is_done() { return _done; } + virtual void do_task(const SuspendedThreadTaskContext& context) = 0; + protected: + private: + void internal_do_task(); + Thread* _thread; + bool _done; + }; + +#ifndef TARGET_OS_FAMILY_windows + // Suspend/resume support + // Protocol: + // + // a thread starts in SR_RUNNING + // + // SR_RUNNING can go to + // * SR_SUSPEND_REQUEST when the WatcherThread wants to suspend it + // SR_SUSPEND_REQUEST can go to + // * SR_RUNNING if WatcherThread decides it waited for SR_SUSPENDED too long (timeout) + // * SR_SUSPENDED if the stopped thread receives the signal and switches state + // SR_SUSPENDED can go to + // * SR_WAKEUP_REQUEST when the WatcherThread has done the work and wants to resume + // SR_WAKEUP_REQUEST can go to + // * SR_RUNNING when the stopped thread receives the signal + // * SR_WAKEUP_REQUEST on timeout (resend the signal and try again) + class SuspendResume { + public: + enum State { + SR_RUNNING, + SR_SUSPEND_REQUEST, + SR_SUSPENDED, + SR_WAKEUP_REQUEST + }; + + private: + volatile State _state; + + private: + /* try to switch state from state "from" to state "to" + * returns the state set after the method is complete + */ + State switch_state(State from, State to); + + public: + SuspendResume() : _state(SR_RUNNING) { } + + State state() const { return _state; } + + State request_suspend() { + return switch_state(SR_RUNNING, SR_SUSPEND_REQUEST); + } + + State cancel_suspend() { + return switch_state(SR_SUSPEND_REQUEST, SR_RUNNING); + } + + State suspended() { + return switch_state(SR_SUSPEND_REQUEST, SR_SUSPENDED); + } + + State request_wakeup() { + return switch_state(SR_SUSPENDED, SR_WAKEUP_REQUEST); + } + + State running() { + return switch_state(SR_WAKEUP_REQUEST, SR_RUNNING); + } + + bool is_running() const { + return _state == SR_RUNNING; + } + + bool is_suspend_request() const { + return _state == SR_SUSPEND_REQUEST; + } + + bool is_suspended() const { + return _state == SR_SUSPENDED; + } + }; +#endif + + protected: static long _rand_seed; // seed for random number generator static int _processor_count; // number of processors diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/share/vm/runtime/perfData.cpp --- a/hotspot/src/share/vm/runtime/perfData.cpp Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/src/share/vm/runtime/perfData.cpp Wed Jul 05 18:59:39 2017 +0200 @@ -323,6 +323,10 @@ } } +PerfData* PerfDataManager::find_by_name(const char* name) { + return _all->find_by_name(name); +} + PerfDataList* PerfDataManager::all() { MutexLocker ml(PerfDataManager_lock); diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/share/vm/runtime/perfData.hpp --- a/hotspot/src/share/vm/runtime/perfData.hpp Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/src/share/vm/runtime/perfData.hpp Wed Jul 05 18:59:39 2017 +0200 @@ -693,6 +693,9 @@ // the given name. static bool exists(const char* name) { return _all->contains(name); } + // method to search for a instrumentation object by name + static PerfData* find_by_name(const char* name); + // method to map a CounterNS enumeration to a namespace string static const char* ns_to_string(CounterNS ns) { return _name_spaces[ns]; diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/share/vm/runtime/stubRoutines.hpp --- a/hotspot/src/share/vm/runtime/stubRoutines.hpp Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/src/share/vm/runtime/stubRoutines.hpp Wed Jul 05 18:59:39 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -223,6 +223,8 @@ static void initialize1(); // must happen before universe::genesis static void initialize2(); // must happen after universe::genesis + static bool is_stub_code(address addr) { return contains(addr); } + static bool contains(address addr) { return (_code1 != NULL && _code1->blob_contains(addr)) || diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/share/vm/runtime/sweeper.cpp --- a/hotspot/src/share/vm/runtime/sweeper.cpp Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/src/share/vm/runtime/sweeper.cpp Wed Jul 05 18:59:39 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -36,6 +36,7 @@ #include "runtime/os.hpp" #include "runtime/sweeper.hpp" #include "runtime/vm_operations.hpp" +#include "trace/tracing.hpp" #include "utilities/events.hpp" #include "utilities/xmlstream.hpp" @@ -130,6 +131,9 @@ long NMethodSweeper::_traversals = 0; // No. of stack traversals performed nmethod* NMethodSweeper::_current = NULL; // Current nmethod int NMethodSweeper::_seen = 0 ; // No. of nmethods we have currently processed in current pass of CodeCache +int NMethodSweeper::_flushed_count = 0; // Nof. nmethods flushed in current sweep +int NMethodSweeper::_zombified_count = 0; // Nof. nmethods made zombie in current sweep +int NMethodSweeper::_marked_count = 0; // Nof. nmethods marked for reclaim in current sweep volatile int NMethodSweeper::_invocations = 0; // No. of invocations left until we are completed with this pass volatile int NMethodSweeper::_sweep_started = 0; // Whether a sweep is in progress. @@ -143,6 +147,15 @@ int NMethodSweeper::_dead_compile_ids = 0; long NMethodSweeper::_last_flush_traversal_id = 0; +int NMethodSweeper::_number_of_flushes = 0; // Total of full traversals caused by full cache +int NMethodSweeper::_total_nof_methods_reclaimed = 0; +jlong NMethodSweeper::_total_time_sweeping = 0; +jlong NMethodSweeper::_total_time_this_sweep = 0; +jlong NMethodSweeper::_peak_sweep_time = 0; +jlong NMethodSweeper::_peak_sweep_fraction_time = 0; +jlong NMethodSweeper::_total_disconnect_time = 0; +jlong NMethodSweeper::_peak_disconnect_time = 0; + class MarkActivationClosure: public CodeBlobClosure { public: virtual void do_code_blob(CodeBlob* cb) { @@ -176,6 +189,8 @@ _invocations = NmethodSweepFraction; _current = CodeCache::first_nmethod(); _traversals += 1; + _total_time_this_sweep = 0; + if (PrintMethodFlushing) { tty->print_cr("### Sweep: stack traversal %d", _traversals); } @@ -229,12 +244,13 @@ } void NMethodSweeper::sweep_code_cache() { -#ifdef ASSERT - jlong sweep_start; - if (PrintMethodFlushing) { - sweep_start = os::javaTimeMillis(); - } -#endif + + jlong sweep_start_counter = os::elapsed_counter(); + + _flushed_count = 0; + _zombified_count = 0; + _marked_count = 0; + if (PrintMethodFlushing && Verbose) { tty->print_cr("### Sweep at %d out of %d. Invocations left: %d", _seen, CodeCache::nof_nmethods(), _invocations); } @@ -302,14 +318,34 @@ } } + jlong sweep_end_counter = os::elapsed_counter(); + jlong sweep_time = sweep_end_counter - sweep_start_counter; + _total_time_sweeping += sweep_time; + _total_time_this_sweep += sweep_time; + _peak_sweep_fraction_time = MAX2(sweep_time, _peak_sweep_fraction_time); + _total_nof_methods_reclaimed += _flushed_count; + + EventSweepCodeCache event(UNTIMED); + if (event.should_commit()) { + event.set_starttime(sweep_start_counter); + event.set_endtime(sweep_end_counter); + event.set_sweepIndex(_traversals); + event.set_sweepFractionIndex(NmethodSweepFraction - _invocations + 1); + event.set_sweptCount(todo); + event.set_flushedCount(_flushed_count); + event.set_markedCount(_marked_count); + event.set_zombifiedCount(_zombified_count); + event.commit(); + } + #ifdef ASSERT if(PrintMethodFlushing) { - jlong sweep_end = os::javaTimeMillis(); - tty->print_cr("### sweeper: sweep time(%d): " INT64_FORMAT, _invocations, sweep_end - sweep_start); + tty->print_cr("### sweeper: sweep time(%d): " INT64_FORMAT, _invocations, (jlong)sweep_time); } #endif if (_invocations == 1) { + _peak_sweep_time = MAX2(_peak_sweep_time, _total_time_this_sweep); log_sweep("finished"); } @@ -388,12 +424,14 @@ tty->print_cr("### Nmethod %3d/" PTR_FORMAT " (marked for reclamation) being flushed", nm->compile_id(), nm); } release_nmethod(nm); + _flushed_count++; } else { if (PrintMethodFlushing && Verbose) { tty->print_cr("### Nmethod %3d/" PTR_FORMAT " (zombie) being marked for reclamation", nm->compile_id(), nm); } nm->mark_for_reclamation(); _resweep = true; + _marked_count++; SWEEP(nm); } } else if (nm->is_not_entrant()) { @@ -405,6 +443,7 @@ } nm->make_zombie(); _resweep = true; + _zombified_count++; SWEEP(nm); } else { // Still alive, clean up its inline caches @@ -420,13 +459,16 @@ // Unloaded code, just make it a zombie if (PrintMethodFlushing && Verbose) tty->print_cr("### Nmethod %3d/" PTR_FORMAT " (unloaded) being made zombie", nm->compile_id(), nm); + if (nm->is_osr_method()) { SWEEP(nm); // No inline caches will ever point to osr methods, so we can just remove it release_nmethod(nm); + _flushed_count++; } else { nm->make_zombie(); _resweep = true; + _zombified_count++; SWEEP(nm); } } else { @@ -484,7 +526,7 @@ // If there was a race in detecting full code cache, only run // one vm op for it or keep the compiler shut off - debug_only(jlong start = os::javaTimeMillis();) + jlong disconnect_start_counter = os::elapsed_counter(); // Traverse the code cache trying to dump the oldest nmethods int curr_max_comp_id = CompileBroker::get_compilation_id(); @@ -541,13 +583,28 @@ _last_full_flush_time = os::javaTimeMillis(); } + jlong disconnect_end_counter = os::elapsed_counter(); + jlong disconnect_time = disconnect_end_counter - disconnect_start_counter; + _total_disconnect_time += disconnect_time; + _peak_disconnect_time = MAX2(disconnect_time, _peak_disconnect_time); + + EventCleanCodeCache event(UNTIMED); + if (event.should_commit()) { + event.set_starttime(disconnect_start_counter); + event.set_endtime(disconnect_end_counter); + event.set_disconnectedCount(disconnected); + event.set_madeNonEntrantCount(made_not_entrant); + event.commit(); + } + _number_of_flushes++; + // After two more traversals the sweeper will get rid of unrestored nmethods _last_flush_traversal_id = _traversals; _resweep = true; #ifdef ASSERT - jlong end = os::javaTimeMillis(); + if(PrintMethodFlushing && Verbose) { - tty->print_cr("### sweeper: unload time: " INT64_FORMAT, end-start); + tty->print_cr("### sweeper: unload time: " INT64_FORMAT, (jlong)disconnect_time); } #endif } diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/share/vm/runtime/sweeper.hpp --- a/hotspot/src/share/vm/runtime/sweeper.hpp Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/src/share/vm/runtime/sweeper.hpp Wed Jul 05 18:59:39 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -31,9 +31,12 @@ // class NMethodSweeper : public AllStatic { - static long _traversals; // Stack traversal count - static nmethod* _current; // Current nmethod - static int _seen; // Nof. nmethod we have currently processed in current pass of CodeCache + static long _traversals; // Stack scan count, also sweep ID. + static nmethod* _current; // Current nmethod + static int _seen; // Nof. nmethod we have currently processed in current pass of CodeCache + static int _flushed_count; // Nof. nmethods flushed in current sweep + static int _zombified_count; // Nof. nmethods made zombie in current sweep + static int _marked_count; // Nof. nmethods marked for reclaim in current sweep static volatile int _invocations; // No. of invocations left until we are completed with this pass static volatile int _sweep_started; // Flag to control conc sweeper @@ -53,6 +56,16 @@ static int _highest_marked; // highest compile id dumped at last emergency unloading static int _dead_compile_ids; // number of compile ids that where not in the cache last flush + // Stat counters + static int _number_of_flushes; // Total of full traversals caused by full cache + static int _total_nof_methods_reclaimed; // Accumulated nof methods flushed + static jlong _total_time_sweeping; // Accumulated time sweeping + static jlong _total_time_this_sweep; // Total time this sweep + static jlong _peak_sweep_time; // Peak time for a full sweep + static jlong _peak_sweep_fraction_time; // Peak time sweeping one fraction + static jlong _total_disconnect_time; // Total time cleaning code mem + static jlong _peak_disconnect_time; // Peak time cleaning code mem + static void process_nmethod(nmethod *nm); static void release_nmethod(nmethod* nm); @@ -60,7 +73,14 @@ static bool sweep_in_progress(); public: - static long traversal_count() { return _traversals; } + static long traversal_count() { return _traversals; } + static int number_of_flushes() { return _number_of_flushes; } + static int total_nof_methods_reclaimed() { return _total_nof_methods_reclaimed; } + static jlong total_time_sweeping() { return _total_time_sweeping; } + static jlong peak_sweep_time() { return _peak_sweep_time; } + static jlong peak_sweep_fraction_time() { return _peak_sweep_fraction_time; } + static jlong total_disconnect_time() { return _total_disconnect_time; } + static jlong peak_disconnect_time() { return _peak_disconnect_time; } #ifdef ASSERT // Keep track of sweeper activity in the ring buffer diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/share/vm/runtime/synchronizer.cpp --- a/hotspot/src/share/vm/runtime/synchronizer.cpp Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/src/share/vm/runtime/synchronizer.cpp Wed Jul 05 18:59:39 2017 +0200 @@ -213,7 +213,7 @@ } } - ObjectSynchronizer::inflate(THREAD, object)->exit (THREAD) ; + ObjectSynchronizer::inflate(THREAD, object)->exit (true, THREAD) ; } // ----------------------------------------------------------------------------- @@ -343,7 +343,7 @@ // If this thread has locked the object, exit the monitor. Note: can't use // monitor->check(CHECK); must exit even if an exception is pending. if (monitor->check(THREAD)) { - monitor->exit(THREAD); + monitor->exit(true, THREAD); } } diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/share/vm/runtime/task.cpp --- a/hotspot/src/share/vm/runtime/task.cpp Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/src/share/vm/runtime/task.cpp Wed Jul 05 18:59:39 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -114,9 +114,11 @@ disenroll(); } +/* enroll could be called from a JavaThread, so we have to check for + * safepoint when taking the lock to avoid deadlocking */ void PeriodicTask::enroll() { MutexLockerEx ml(PeriodicTask_lock->owned_by_self() ? - NULL : PeriodicTask_lock, Mutex::_no_safepoint_check_flag); + NULL : PeriodicTask_lock); if (_num_tasks == PeriodicTask::max_tasks) { fatal("Overflow in PeriodicTask table"); @@ -131,9 +133,11 @@ } } +/* disenroll could be called from a JavaThread, so we have to check for + * safepoint when taking the lock to avoid deadlocking */ void PeriodicTask::disenroll() { MutexLockerEx ml(PeriodicTask_lock->owned_by_self() ? - NULL : PeriodicTask_lock, Mutex::_no_safepoint_check_flag); + NULL : PeriodicTask_lock); int index; for(index = 0; index < _num_tasks && _tasks[index] != this; index++) diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/share/vm/runtime/thread.cpp --- a/hotspot/src/share/vm/runtime/thread.cpp Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/src/share/vm/runtime/thread.cpp Wed Jul 05 18:59:39 2017 +0200 @@ -77,7 +77,8 @@ #include "services/management.hpp" #include "services/memTracker.hpp" #include "services/threadService.hpp" -#include "trace/traceEventTypes.hpp" +#include "trace/tracing.hpp" +#include "trace/traceMacros.hpp" #include "utilities/defaultStream.hpp" #include "utilities/dtrace.hpp" #include "utilities/events.hpp" @@ -238,7 +239,6 @@ CHECK_UNHANDLED_OOPS_ONLY(_gc_locked_out_count = 0;) _jvmti_env_iteration_count = 0; set_allocated_bytes(0); - set_trace_buffer(NULL); _vm_operation_started_count = 0; _vm_operation_completed_count = 0; _current_pending_monitor = NULL; @@ -1659,9 +1659,11 @@ JvmtiExport::post_thread_start(this); } - EVENT_BEGIN(TraceEventThreadStart, event); - EVENT_COMMIT(event, - EVENT_SET(event, javalangthread, java_lang_Thread::thread_id(this->threadObj()))); + EventThreadStart event; + if (event.should_commit()) { + event.set_javalangthread(java_lang_Thread::thread_id(this->threadObj())); + event.commit(); + } // We call another function to do the rest so we are sure that the stack addresses used // from there will be lower than the stack base just computed @@ -1791,9 +1793,11 @@ // Called before the java thread exit since we want to read info // from java_lang_Thread object - EVENT_BEGIN(TraceEventThreadEnd, event); - EVENT_COMMIT(event, - EVENT_SET(event, javalangthread, java_lang_Thread::thread_id(this->threadObj()))); + EventThreadEnd event; + if (event.should_commit()) { + event.set_javalangthread(java_lang_Thread::thread_id(this->threadObj())); + event.commit(); + } // Call after last event on thread EVENT_THREAD_EXIT(this); @@ -3648,8 +3652,8 @@ // Notify JVMTI agents that VM initialization is complete - nop if no agents. JvmtiExport::post_vm_initialized(); - if (!TRACE_START()) { - vm_exit_during_initialization(Handle(THREAD, PENDING_EXCEPTION)); + if (TRACE_START() != JNI_OK) { + vm_exit_during_initialization("Failed to start tracing backend."); } if (CleanChunkPoolAsync) { diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/share/vm/runtime/thread.hpp --- a/hotspot/src/share/vm/runtime/thread.hpp Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/src/share/vm/runtime/thread.hpp Wed Jul 05 18:59:39 2017 +0200 @@ -47,7 +47,8 @@ #include "services/memRecorder.hpp" #endif // INCLUDE_NMT -#include "trace/tracing.hpp" +#include "trace/traceBackend.hpp" +#include "trace/traceMacros.hpp" #include "utilities/exceptions.hpp" #include "utilities/top.hpp" #if INCLUDE_ALL_GCS @@ -258,7 +259,7 @@ jlong _allocated_bytes; // Cumulative number of bytes allocated on // the Java heap - TRACE_BUFFER _trace_buffer; // Thread-local buffer for tracing + TRACE_DATA _trace_data; // Thread-local data for tracing int _vm_operation_started_count; // VM_Operation support int _vm_operation_completed_count; // VM_Operation support @@ -449,8 +450,7 @@ return allocated_bytes; } - TRACE_BUFFER trace_buffer() { return _trace_buffer; } - void set_trace_buffer(TRACE_BUFFER buf) { _trace_buffer = buf; } + TRACE_DATA* trace_data() { return &_trace_data; } // VM operation support int vm_operation_ticket() { return ++_vm_operation_started_count; } diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/share/vm/runtime/timer.cpp --- a/hotspot/src/share/vm/runtime/timer.cpp Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/src/share/vm/runtime/timer.cpp Wed Jul 05 18:59:39 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -39,6 +39,11 @@ # include "os_bsd.inline.hpp" #endif +double TimeHelper::counter_to_seconds(jlong counter) { + double count = (double) counter; + double freq = (double) os::elapsed_frequency(); + return counter/freq; +} void elapsedTimer::add(elapsedTimer t) { _counter += t._counter; @@ -59,9 +64,7 @@ } double elapsedTimer::seconds() const { - double count = (double) _counter; - double freq = (double) os::elapsed_frequency(); - return count/freq; + return TimeHelper::counter_to_seconds(_counter); } jlong elapsedTimer::milliseconds() const { @@ -90,9 +93,7 @@ double TimeStamp::seconds() const { assert(is_updated(), "must not be clear"); jlong new_count = os::elapsed_counter(); - double count = (double) new_count - _counter; - double freq = (double) os::elapsed_frequency(); - return count/freq; + return TimeHelper::counter_to_seconds(new_count - _counter); } jlong TimeStamp::milliseconds() const { @@ -110,19 +111,15 @@ } TraceTime::TraceTime(const char* title, - bool doit, - bool print_cr, - outputStream* logfile) { + bool doit) { _active = doit; _verbose = true; - _print_cr = print_cr; - _logfile = (logfile != NULL) ? logfile : tty; if (_active) { _accum = NULL; - _logfile->stamp(PrintGCTimeStamps); - _logfile->print("[%s", title); - _logfile->flush(); + tty->stamp(PrintGCTimeStamps); + tty->print("[%s", title); + tty->flush(); _t.start(); } } @@ -130,17 +127,14 @@ TraceTime::TraceTime(const char* title, elapsedTimer* accumulator, bool doit, - bool verbose, - outputStream* logfile) { + bool verbose) { _active = doit; _verbose = verbose; - _print_cr = true; - _logfile = (logfile != NULL) ? logfile : tty; if (_active) { if (_verbose) { - _logfile->stamp(PrintGCTimeStamps); - _logfile->print("[%s", title); - _logfile->flush(); + tty->stamp(PrintGCTimeStamps); + tty->print("[%s", title); + tty->flush(); } _accum = accumulator; _t.start(); @@ -152,12 +146,8 @@ _t.stop(); if (_accum!=NULL) _accum->add(_t); if (_verbose) { - if (_print_cr) { - _logfile->print_cr(", %3.7f secs]", _t.seconds()); - } else { - _logfile->print(", %3.7f secs]", _t.seconds()); - } - _logfile->flush(); + tty->print_cr(", %3.7f secs]", _t.seconds()); + tty->flush(); } } } diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/share/vm/runtime/timer.hpp --- a/hotspot/src/share/vm/runtime/timer.hpp Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/src/share/vm/runtime/timer.hpp Wed Jul 05 18:59:39 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -82,21 +82,16 @@ private: bool _active; // do timing bool _verbose; // report every timing - bool _print_cr; // add a CR to the end of the timer report elapsedTimer _t; // timer elapsedTimer* _accum; // accumulator - outputStream* _logfile; // output log file public: - // Constuctors + // Constructors TraceTime(const char* title, - bool doit = true, - bool print_cr = true, - outputStream *logfile = NULL); + bool doit = true); TraceTime(const char* title, elapsedTimer* accumulator, bool doit = true, - bool verbose = false, - outputStream *logfile = NULL ); + bool verbose = false); ~TraceTime(); // Accessors @@ -125,4 +120,9 @@ ~TraceCPUTime(); }; +class TimeHelper { + public: + static double counter_to_seconds(jlong counter); +}; + #endif // SHARE_VM_RUNTIME_TIMER_HPP diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/share/vm/runtime/vmStructs.cpp --- a/hotspot/src/share/vm/runtime/vmStructs.cpp Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/src/share/vm/runtime/vmStructs.cpp Wed Jul 05 18:59:39 2017 +0200 @@ -60,6 +60,7 @@ #include "memory/generationSpec.hpp" #include "memory/heap.hpp" #include "memory/metablock.hpp" +#include "memory/referenceType.hpp" #include "memory/space.hpp" #include "memory/tenuredGeneration.hpp" #include "memory/universe.hpp" diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/share/vm/runtime/vmThread.cpp --- a/hotspot/src/share/vm/runtime/vmThread.cpp Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/src/share/vm/runtime/vmThread.cpp Wed Jul 05 18:59:39 2017 +0200 @@ -35,6 +35,7 @@ #include "runtime/vmThread.hpp" #include "runtime/vm_operations.hpp" #include "services/runtimeService.hpp" +#include "trace/tracing.hpp" #include "utilities/dtrace.hpp" #include "utilities/events.hpp" #include "utilities/xmlstream.hpp" @@ -365,7 +366,23 @@ (char *) op->name(), strlen(op->name()), op->evaluation_mode()); #endif /* USDT2 */ + + EventExecuteVMOperation event; + op->evaluate(); + + if (event.should_commit()) { + bool is_concurrent = op->evaluate_concurrently(); + event.set_operation(op->type()); + event.set_safepoint(op->evaluate_at_safepoint()); + event.set_blocking(!is_concurrent); + // Only write caller thread information for non-concurrent vm operations. + // For concurrent vm operations, the thread id is set to 0 indicating thread is unknown. + // This is because the caller thread could have exited already. + event.set_caller(is_concurrent ? 0 : op->calling_thread()->osthread()->thread_id()); + event.commit(); + } + #ifndef USDT2 HS_DTRACE_PROBE3(hotspot, vmops__end, op->name(), strlen(op->name()), op->evaluation_mode()); @@ -601,7 +618,7 @@ { VMOperationQueue_lock->lock_without_safepoint_check(); bool ok = _vm_queue->add(op); - op->set_timestamp(os::javaTimeMillis()); + op->set_timestamp(os::javaTimeMillis()); VMOperationQueue_lock->notify(); VMOperationQueue_lock->unlock(); // VM_Operation got skipped diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/share/vm/runtime/vm_operations.cpp --- a/hotspot/src/share/vm/runtime/vm_operations.cpp Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/src/share/vm/runtime/vm_operations.cpp Wed Jul 05 18:59:39 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -37,6 +37,7 @@ #include "runtime/thread.inline.hpp" #include "runtime/vm_operations.hpp" #include "services/threadService.hpp" +#include "trace/tracing.hpp" #define VM_OP_NAME_INITIALIZE(name) #name, @@ -62,19 +63,21 @@ } } +const char* VM_Operation::mode_to_string(Mode mode) { + switch(mode) { + case _safepoint : return "safepoint"; + case _no_safepoint : return "no safepoint"; + case _concurrent : return "concurrent"; + case _async_safepoint: return "async safepoint"; + default : return "unknown"; + } +} // Called by fatal error handler. void VM_Operation::print_on_error(outputStream* st) const { st->print("VM_Operation (" PTR_FORMAT "): ", this); st->print("%s", name()); - const char* mode; - switch(evaluation_mode()) { - case _safepoint : mode = "safepoint"; break; - case _no_safepoint : mode = "no safepoint"; break; - case _concurrent : mode = "concurrent"; break; - case _async_safepoint: mode = "async safepoint"; break; - default : mode = "unknown"; break; - } + const char* mode = mode_to_string(evaluation_mode()); st->print(", mode: %s", mode); if (calling_thread()) { diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/share/vm/runtime/vm_operations.hpp --- a/hotspot/src/share/vm/runtime/vm_operations.hpp Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/src/share/vm/runtime/vm_operations.hpp Wed Jul 05 18:59:39 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -178,6 +178,8 @@ evaluation_mode() == _async_safepoint; } + static const char* mode_to_string(Mode mode); + // Debugging void print_on_error(outputStream* st) const; const char* name() const { return _names[type()]; } diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/share/vm/services/attachListener.cpp --- a/hotspot/src/share/vm/services/attachListener.cpp Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/src/share/vm/services/attachListener.cpp Wed Jul 05 18:59:39 2017 +0200 @@ -227,7 +227,7 @@ } live_objects_only = strcmp(arg0, "-live") == 0; } - VM_GC_HeapInspection heapop(out, live_objects_only /* request full gc */, true /* need_prologue */); + VM_GC_HeapInspection heapop(out, live_objects_only /* request full gc */); VMThread::execute(&heapop); return JNI_OK; } diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/share/vm/services/diagnosticArgument.cpp --- a/hotspot/src/share/vm/services/diagnosticArgument.cpp Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/src/share/vm/services/diagnosticArgument.cpp Wed Jul 05 18:59:39 2017 +0200 @@ -24,6 +24,7 @@ #include "precompiled.hpp" #include "memory/allocation.inline.hpp" +#include "memory/resourceArea.hpp" #include "runtime/thread.hpp" #include "services/diagnosticArgument.hpp" @@ -86,9 +87,18 @@ template <> void DCmdArgument::parse_value(const char* str, size_t len, TRAPS) { - if (str == NULL || sscanf(str, JLONG_FORMAT, &_value) != 1) { - THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), - "Integer parsing error in diagnostic command arguments\n"); + int scanned = -1; + if (str == NULL + || sscanf(str, JLONG_FORMAT"%n", &_value, &scanned) != 1 + || (size_t)scanned != len) + { + ResourceMark rm; + + char* buf = NEW_RESOURCE_ARRAY(char, len + 1); + strncpy(buf, str, len); + buf[len] = '\0'; + Exceptions::fthrow(THREAD_AND_LOCATION, vmSymbols::java_lang_IllegalArgumentException(), + "Integer parsing error in command argument '%s'. Could not parse: %s.", _name, buf); } } @@ -96,7 +106,7 @@ if (has_default()) { this->parse_value(_default_string, strlen(_default_string), THREAD); if (HAS_PENDING_EXCEPTION) { - fatal("Default string must be parsable"); + fatal("Default string must be parseable"); } } else { set_value(0); @@ -116,8 +126,13 @@ } else if (len == strlen("false") && strncasecmp(str, "false", len) == 0) { set_value(false); } else { - THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), - "Boolean parsing error in diagnostic command arguments"); + ResourceMark rm; + + char* buf = NEW_RESOURCE_ARRAY(char, len + 1); + strncpy(buf, str, len); + buf[len] = '\0'; + Exceptions::fthrow(THREAD_AND_LOCATION, vmSymbols::java_lang_IllegalArgumentException(), + "Boolean parsing error in command argument '%s'. Could not parse: %s.", _name, buf); } } } @@ -168,7 +183,7 @@ size_t len, TRAPS) { if (str == NULL) { THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), - "Integer parsing error nanotime value: syntax error"); + "Integer parsing error nanotime value: syntax error, value is null"); } int argc = sscanf(str, JLONG_FORMAT, &_value._time); diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/share/vm/services/diagnosticCommand.cpp --- a/hotspot/src/share/vm/services/diagnosticCommand.cpp Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/src/share/vm/services/diagnosticCommand.cpp Wed Jul 05 18:59:39 2017 +0200 @@ -320,8 +320,7 @@ void ClassHistogramDCmd::execute(DCmdSource source, TRAPS) { VM_GC_HeapInspection heapop(output(), - !_all.value() /* request full gc if false */, - true /* need_prologue */); + !_all.value() /* request full gc if false */); VMThread::execute(&heapop); } @@ -361,8 +360,7 @@ } VM_GC_HeapInspection heapop(output(), - true, /* request_full_gc */ - true /* need_prologue */); + true /* request_full_gc */); heapop.set_csv_format(_csv.value()); heapop.set_print_help(_help.value()); heapop.set_print_class_stats(true); diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/share/vm/services/memBaseline.cpp --- a/hotspot/src/share/vm/services/memBaseline.cpp Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/src/share/vm/services/memBaseline.cpp Wed Jul 05 18:59:39 2017 +0200 @@ -41,6 +41,7 @@ {mtOther, "Other"}, {mtSymbol, "Symbol"}, {mtNMT, "Memory Tracking"}, + {mtTracing, "Tracing"}, {mtChunk, "Pooled Free Chunks"}, {mtClassShared,"Shared spaces for classes"}, {mtTest, "Test"}, diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/share/vm/trace/noTraceBackend.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/src/share/vm/trace/noTraceBackend.hpp Wed Jul 05 18:59:39 2017 +0200 @@ -0,0 +1,48 @@ +/* + * 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. + * + */ +#ifndef SHARE_VM_TRACE_NOTRACEBACKEND_HPP +#define SHARE_VM_TRACE_NOTRACEBACKEND_HPP + +#include "prims/jni.h" + +typedef jlong TracingTime; +typedef jlong RelativeTracingTime; + +class NoTraceBackend { +public: + static TracingTime time() { + return 0; + } +}; + +class TraceThreadData { +public: + TraceThreadData() {} +}; + +typedef NoTraceBackend Tracing; + +#endif + + diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/share/vm/trace/trace.dtd --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/src/share/vm/trace/trace.dtd Wed Jul 05 18:59:39 2017 +0200 @@ -0,0 +1,86 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/share/vm/trace/trace.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/src/share/vm/trace/trace.xml Wed Jul 05 18:59:39 2017 +0200 @@ -0,0 +1,367 @@ + + + + + +%xinclude; +]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/share/vm/trace/traceBackend.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/src/share/vm/trace/traceBackend.hpp Wed Jul 05 18:59:39 2017 +0200 @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2012, 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. + * + */ +#ifndef SHARE_VM_TRACE_TRACEBACKEND_HPP +#define SHARE_VM_TRACE_TRACEBACKEND_HPP + +#include "utilities/macros.hpp" + +#if INCLUDE_TRACE + +#include "runtime/globals.hpp" +#include "runtime/os.hpp" +#include "trace/traceTime.hpp" +#include "tracefiles/traceEventIds.hpp" + +class TraceBackend { +public: + static bool enabled(void) { + return EnableTracing; + } + + static bool is_event_enabled(TraceEventId id) { + return enabled(); + } + + static TracingTime time() { + return os::elapsed_counter(); + } + + static TracingTime time_adjustment(jlong time) { + return time; + } + + static void on_unloading_classes(void) { + } +}; + +class TraceThreadData { +public: + TraceThreadData() {} +}; + +typedef TraceBackend Tracing; + +#else /* INCLUDE_TRACE */ + +#include "trace/noTraceBackend.hpp" + +#endif /* INCLUDE_TRACE */ +#endif /* SHARE_VM_TRACE_TRACEBACKEND_HPP */ diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/share/vm/trace/traceDataTypes.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/src/share/vm/trace/traceDataTypes.hpp Wed Jul 05 18:59:39 2017 +0200 @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2012, 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. + * + */ + +#ifndef SHARE_VM_TRACE_TRACEDATATYPES_HPP +#define SHARE_VM_TRACE_TRACEDATATYPES_HPP + +#include + +#include "utilities/globalDefinitions.hpp" + +enum { + CONTENT_TYPE_NONE = 0, + CONTENT_TYPE_BYTES = 1, + CONTENT_TYPE_EPOCHMILLIS = 2, + CONTENT_TYPE_MILLIS = 3, + CONTENT_TYPE_NANOS = 4, + CONTENT_TYPE_TICKS = 5, + CONTENT_TYPE_ADDRESS = 6, + + CONTENT_TYPE_OSTHREAD, + CONTENT_TYPE_JAVALANGTHREAD, + CONTENT_TYPE_STACKTRACE, + CONTENT_TYPE_CLASS, + CONTENT_TYPE_PERCENTAGE, + + JVM_CONTENT_TYPES_START = 30, + JVM_CONTENT_TYPES_END = 100 +}; + +enum ReservedEvent { + EVENT_PRODUCERS, + EVENT_CHECKPOINT, + EVENT_BUFFERLOST, + + NUM_RESERVED_EVENTS +}; + +typedef enum ReservedEvent ReservedEvent; + +typedef u8 classid; +typedef u8 stacktraceid; +typedef u8 methodid; +typedef u8 fieldid; + +#endif // SHARE_VM_TRACE_TRACEDATATYPES_HPP + diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/share/vm/trace/traceEvent.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/src/share/vm/trace/traceEvent.hpp Wed Jul 05 18:59:39 2017 +0200 @@ -0,0 +1,150 @@ +/* + * Copyright (c) 2012, 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. + * + */ + +#ifndef SHARE_VM_TRACE_TRACEEVENT_HPP +#define SHARE_VM_TRACE_TRACEEVENT_HPP + +enum EventStartTime { + UNTIMED, + TIMED +}; + +#include "utilities/macros.hpp" + +#if INCLUDE_TRACE + +#include "trace/traceBackend.hpp" +#include "trace/tracing.hpp" +#include "tracefiles/traceEventIds.hpp" +#include "tracefiles/traceTypes.hpp" + +template +class TraceEvent : public StackObj { + protected: + jlong _startTime; + jlong _endTime; + + private: + bool _started; +#ifdef ASSERT + bool _committed; + bool _cancelled; + protected: + bool _ignore_check; +#endif + + public: + TraceEvent(EventStartTime timing=TIMED) : + _startTime(0), + _endTime(0), + _started(false) +#ifdef ASSERT + , + _committed(false), + _cancelled(false), + _ignore_check(false) +#endif + { + if (T::is_enabled()) { + _started = true; + if (timing == TIMED && !T::isInstant) { + static_cast(this)->set_starttime(Tracing::time()); + } + } + } + + static bool is_enabled() { + return Tracing::is_event_enabled(T::eventId); + } + + bool should_commit() { + return _started; + } + + void ignoreCheck() { + DEBUG_ONLY(_ignore_check = true); + } + + void commit() { + if (!should_commit()) { + cancel(); + return; + } + if (_endTime == 0) { + static_cast(this)->set_endtime(Tracing::time()); + } + if (static_cast(this)->should_write()) { + static_cast(this)->writeEvent(); + } + set_commited(); + } + + void set_starttime(jlong time) { + _startTime = time; + } + + void set_endtime(jlong time) { + _endTime = time; + } + + TraceEventId id() const { + return T::eventId; + } + + bool is_instant() const { + return T::isInstant; + } + + bool is_requestable() const { + return T::isRequestable; + } + + bool has_thread() const { + return T::hasThread; + } + + bool has_stacktrace() const { + return T::hasStackTrace; + } + + void cancel() { + assert(!_committed && !_cancelled, "event was already committed/cancelled"); + DEBUG_ONLY(_cancelled = true); + } + + void set_commited() { + assert(!_committed, "event has already been committed"); + DEBUG_ONLY(_committed = true); + } + + ~TraceEvent() { + if (_started) { + assert(_ignore_check || _committed || _cancelled, "event was not committed/cancelled"); + } + } +}; + +#endif /* INCLUDE_TRACE */ + +#endif /* SHARE_VM_TRACE_TRACEEVENT_HPP */ diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/share/vm/trace/traceEventClasses.xsl --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/src/share/vm/trace/traceEventClasses.xsl Wed Jul 05 18:59:39 2017 +0200 @@ -0,0 +1,246 @@ + + + + + + + + + + +#ifndef TRACEFILES_TRACEEVENTCLASSES_HPP +#define TRACEFILES_TRACEEVENTCLASSES_HPP + +// On purpose outside the INCLUDE_TRACE +// Some parts of traceEvent.hpp are used outside of +// INCLUDE_TRACE + +#include "memory/resourceArea.hpp" +#include "tracefiles/traceTypes.hpp" +#include "trace/traceEvent.hpp" +#include "utilities/macros.hpp" + +#if INCLUDE_TRACE + + +#include "trace/traceStream.hpp" +#include "utilities/ostream.hpp" + + + + +#else + +class TraceEvent { +public: + TraceEvent() {} + void set_starttime(jlong time) const {} + void set_endtime(jlong time) const {} + bool should_commit() const { return false; } + void commit() const {} +}; + + + + +#endif + +#endif + + + +struct TraceStruct +{ +private: + +public: + + + void writeStruct(TraceStream& ts) { + + } +}; + + + + +struct TraceStruct +{ +public: + +}; + + + + + +{ + public: + + + + + +}; + + + + + + +{ + public: + static const bool hasThread = ; + static const bool hasStackTrace = ; + static const bool isInstant = ; + static const bool isRequestable = ; + static const TraceEventId eventId = ; + + private: + + + void writeEventContent(void) { + TraceStream ts(*tty); + ts.print(": ["); + + ts.print("]\n"); + } + + public: + + + bool should_write(void) { + return true; + } + + + + + void writeEvent(void) { + ResourceMark rm; + if (UseLockedTracing) { + ttyLocker lock; + writeEventContent(); + } else { + writeEventContent(); + } + } +}; + + + + + + + + + + + + + + + + + + + + + + + + + +#if INCLUDE_TRACE + +#else + +#endif + + + +#if INCLUDE_TRACE + +#else + +#endif + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ts.print(", "); + + + + + + + + + ts.print(", "); + + + + + diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/share/vm/trace/traceEventIds.xsl --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/src/share/vm/trace/traceEventIds.xsl Wed Jul 05 18:59:39 2017 +0200 @@ -0,0 +1,74 @@ + + + + + + + + + + +#ifndef TRACEFILES_JFREVENTIDS_HPP +#define TRACEFILES_JFREVENTIDS_HPP + +#include "utilities/macros.hpp" + +#if INCLUDE_TRACE + +#include "trace/traceDataTypes.hpp" + +/** + * Enum of the event types in the JVM + */ +enum TraceEventId { + _traceeventbase = (NUM_RESERVED_EVENTS-1), // Make sure we start at right index. + + // Events -> enum entry + + + + MaxTraceEventId +}; + +/** + * Struct types in the JVM + */ +enum TraceStructId { + + + + + + + MaxTraceStructId +}; + +typedef enum TraceEventId TraceEventId; +typedef enum TraceStructId TraceStructId; + +#endif +#endif + + + diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/share/vm/trace/traceEventTypes.hpp --- a/hotspot/src/share/vm/trace/traceEventTypes.hpp Thu Jun 13 09:49:19 2013 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,30 +0,0 @@ -/* - * Copyright (c) 1997, 2012, 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. - * - */ - -#ifndef SHARE_VM_TRACE_TRACE_EVENT_TYPES_HPP -#define SHARE_VM_TRACE_TRACE_EVENT_TYPES_HPP - -/* Empty, just a placeholder for tracing events */ - -#endif diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/share/vm/trace/traceMacros.hpp --- a/hotspot/src/share/vm/trace/traceMacros.hpp Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/src/share/vm/trace/traceMacros.hpp Wed Jul 05 18:59:39 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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,22 +25,14 @@ #ifndef SHARE_VM_TRACE_TRACE_MACRO_HPP #define SHARE_VM_TRACE_TRACE_MACRO_HPP -#define EVENT_BEGIN(type, name) -#define EVENT_SET(name, field, value) -#define EVENT_COMMIT(name, ...) -#define EVENT_STARTED(name, time) -#define EVENT_ENDED(name, time) #define EVENT_THREAD_EXIT(thread) -#define TRACE_ENABLED 0 - #define TRACE_INIT_ID(k) -#define TRACE_BUFFER void* +#define TRACE_DATA TraceThreadData -#define TRACE_START() true -#define TRACE_INITIALIZE() 0 +#define TRACE_START() JNI_OK +#define TRACE_INITIALIZE() JNI_OK -#define TRACE_SET_KLASS_TRACE_ID(x1, x2) do { } while (0) #define TRACE_DEFINE_KLASS_METHODS typedef int ___IGNORED_hs_trace_type1 #define TRACE_DEFINE_KLASS_TRACE_ID typedef int ___IGNORED_hs_trace_type2 #define TRACE_DEFINE_OFFSET typedef int ___IGNORED_hs_trace_type3 diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/share/vm/trace/traceStream.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/src/share/vm/trace/traceStream.hpp Wed Jul 05 18:59:39 2017 +0200 @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2012, 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. + * + */ + +#ifndef SHARE_VM_TRACE_TRACESTREAM_HPP +#define SHARE_VM_TRACE_TRACESTREAM_HPP + +#include "utilities/macros.hpp" + +#if INCLUDE_TRACE + +#include "oops/klass.hpp" +#include "oops/method.hpp" +#include "oops/symbol.hpp" +#include "utilities/ostream.hpp" + +class TraceStream : public StackObj { + private: + outputStream& _st; + + public: + TraceStream(outputStream& stream): _st(stream) {} + + void print_val(const char* label, u1 val) { + _st.print("%s = "UINT32_FORMAT, label, val); + } + + void print_val(const char* label, u2 val) { + _st.print("%s = "UINT32_FORMAT, label, val); + } + + void print_val(const char* label, s2 val) { + _st.print("%s = "INT32_FORMAT, label, val); + } + + void print_val(const char* label, u4 val) { + _st.print("%s = "UINT32_FORMAT, label, val); + } + + void print_val(const char* label, s4 val) { + _st.print("%s = "INT32_FORMAT, label, val); + } + + void print_val(const char* label, u8 val) { + _st.print("%s = "UINT64_FORMAT, label, val); + } + + void print_val(const char* label, s8 val) { + _st.print("%s = "INT64_FORMAT, label, val); + } + + void print_val(const char* label, bool val) { + _st.print("%s = %s", label, val ? "true" : "false"); + } + + void print_val(const char* label, float val) { + _st.print("%s = %f", label, val); + } + + void print_val(const char* label, double val) { + _st.print("%s = %f", label, val); + } + + // Caller is machine generated code located in traceEventClasses.hpp + // Event::writeEvent() (pseudocode) contains the + // necessary ResourceMark for the resource allocations below. + // See traceEventClasses.xsl for details. + void print_val(const char* label, const Klass* const val) { + const char* description = "NULL"; + if (val != NULL) { + Symbol* name = val->name(); + if (name != NULL) { + description = name->as_C_string(); + } + } + _st.print("%s = %s", label, description); + } + + // Caller is machine generated code located in traceEventClasses.hpp + // Event::writeEvent() (pseudocode) contains the + // necessary ResourceMark for the resource allocations below. + // See traceEventClasses.xsl for details. + void print_val(const char* label, const Method* const val) { + const char* description = "NULL"; + if (val != NULL) { + description = val->name_and_sig_as_C_string(); + } + _st.print("%s = %s", label, description); + } + + void print_val(const char* label, const char* val) { + _st.print("%s = '%s'", label, val); + } + + void print(const char* val) { + _st.print(val); + } +}; + +#endif /* INCLUDE_TRACE */ +#endif /* SHARE_VM_TRACE_TRACESTREAM_HPP */ diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/share/vm/trace/traceTime.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/src/share/vm/trace/traceTime.hpp Wed Jul 05 18:59:39 2017 +0200 @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2012, 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. + * + */ + +#ifndef SHARE_VM_TRACE_TRACETIME_HPP +#define SHARE_VM_TRACE_TRACETIME_HPP + +#include "prims/jni.h" + +typedef jlong TracingTime; +typedef jlong RelativeTracingTime; + +#endif diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/share/vm/trace/traceTypes.xsl --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/src/share/vm/trace/traceTypes.xsl Wed Jul 05 18:59:39 2017 +0200 @@ -0,0 +1,72 @@ + + + + + + + + + + +#ifndef TRACEFILES_JFRTYPES_HPP +#define TRACEFILES_JFRTYPES_HPP + +#include "trace/traceDataTypes.hpp" +#include "utilities/globalDefinitions.hpp" +#include "oops/symbol.hpp" + +enum JVMContentType { + _not_a_content_type = (JVM_CONTENT_TYPES_START - 1), + + + + + NUM_JVM_CONTENT_TYPES +}; + + +enum JVMEventRelations { + JVM_REL_NOT_AVAILABLE = 0, + + + + + NUM_EVENT_RELATIONS +}; + +/** + * Create typedefs for the JRA types: + * typedef s8 TYPE_LONG; + * typedef s4 TYPE_INTEGER; + * typedef const char * TYPE_STRING; + * ... + */ + +typedef TYPE_; + + +#endif // JFRFILES_JFRTYPES_HPP + + + diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/share/vm/trace/tracetypes.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/src/share/vm/trace/tracetypes.xml Wed Jul 05 18:59:39 2017 +0200 @@ -0,0 +1,368 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/share/vm/trace/tracing.hpp --- a/hotspot/src/share/vm/trace/tracing.hpp Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/src/share/vm/trace/tracing.hpp Wed Jul 05 18:59:39 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ #ifndef SHARE_VM_TRACE_TRACING_HPP #define SHARE_VM_TRACE_TRACING_HPP -#include "trace/traceMacros.hpp" +#include "tracefiles/traceEventClasses.hpp" +#include "tracefiles/traceEventIds.hpp" #endif diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/share/vm/trace/xinclude.mod --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/src/share/vm/trace/xinclude.mod Wed Jul 05 18:59:39 2017 +0200 @@ -0,0 +1,61 @@ + + + + + + + + + diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/share/vm/trace/xsl_util.xsl --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/src/share/vm/trace/xsl_util.xsl Wed Jul 05 18:59:39 2017 +0200 @@ -0,0 +1,78 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + " + + + + /* AUTOMATICALLY GENERATED FILE - DO NOT EDIT */ + + + + + + + + + + + + + + + + + + + + + + + + diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/share/vm/utilities/globalDefinitions.hpp --- a/hotspot/src/share/vm/utilities/globalDefinitions.hpp Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/src/share/vm/utilities/globalDefinitions.hpp Wed Jul 05 18:59:39 2017 +0200 @@ -763,18 +763,6 @@ TosState as_TosState(BasicType type); -// ReferenceType is used to distinguish between java/lang/ref/Reference subclasses - -enum ReferenceType { - REF_NONE, // Regular class - REF_OTHER, // Subclass of java/lang/ref/Reference, but not subclass of one of the classes below - REF_SOFT, // Subclass of java/lang/ref/SoftReference - REF_WEAK, // Subclass of java/lang/ref/WeakReference - REF_FINAL, // Subclass of java/lang/ref/FinalReference - REF_PHANTOM // Subclass of java/lang/ref/PhantomReference -}; - - // JavaThreadState keeps track of which part of the code a thread is executing in. This // information is needed by the safepoint code. // diff -r 41b9fc8961f6 -r f1a01fb5f958 hotspot/src/share/vm/utilities/macros.hpp --- a/hotspot/src/share/vm/utilities/macros.hpp Thu Jun 13 09:49:19 2013 -0700 +++ b/hotspot/src/share/vm/utilities/macros.hpp Wed Jul 05 18:59:39 2017 +0200 @@ -160,6 +160,10 @@ #define NOT_NMT_RETURN_(code) { return code; } #endif // INCLUDE_NMT +#ifndef INCLUDE_TRACE +#define INCLUDE_TRACE 1 +#endif // INCLUDE_TRACE + // COMPILER1 variant #ifdef COMPILER1 #ifdef COMPILER2 diff -r 41b9fc8961f6 -r f1a01fb5f958 jaxp/.hgtags --- a/jaxp/.hgtags Thu Jun 13 09:49:19 2013 -0700 +++ b/jaxp/.hgtags Wed Jul 05 18:59:39 2017 +0200 @@ -215,3 +215,4 @@ e3065fb07877c7e96e8b93416fe2ab9a4c9eb2a5 jdk8-b91 1ab5d8d6eab81e65c6c3cf21739474cd67a0e7cf jdk8-b92 d583a491d63c49eeda4869525048075da1cb596e jdk8-b93 +c84658e1740df64931005a9bc4c8ecef38eb47c3 jdk8-b94 diff -r 41b9fc8961f6 -r f1a01fb5f958 jaxws/.hgtags --- a/jaxws/.hgtags Thu Jun 13 09:49:19 2013 -0700 +++ b/jaxws/.hgtags Wed Jul 05 18:59:39 2017 +0200 @@ -215,3 +215,4 @@ 0bb1a9fa56b037d072efdaae5f5b73a0f23c966c jdk8-b91 a0f604766ca14818e2a7b1558cc399499caabf75 jdk8-b92 7386eca865e1f7216637cdf8dcf3f5d5c255f208 jdk8-b93 +254c53fd97ab24942043adcfa5c1a0a38a3b274e jdk8-b94 diff -r 41b9fc8961f6 -r f1a01fb5f958 jdk/.hgtags --- a/jdk/.hgtags Thu Jun 13 09:49:19 2013 -0700 +++ b/jdk/.hgtags Wed Jul 05 18:59:39 2017 +0200 @@ -215,3 +215,4 @@ 169451cf0cc53bde5af24f9820ea3f35ec4b4df4 jdk8-b91 a2a2a91075ad85becbe10a39d7fd04ef9bea8df5 jdk8-b92 691d6c6cd332d98b0f0221445a73906776f31f72 jdk8-b93 +51479fa56b7c4363c6d87c2e8b898d8185cf4b22 jdk8-b94 diff -r 41b9fc8961f6 -r f1a01fb5f958 jdk/make/com/oracle/jfr/Makefile --- a/jdk/make/com/oracle/jfr/Makefile Thu Jun 13 09:49:19 2013 -0700 +++ b/jdk/make/com/oracle/jfr/Makefile Wed Jul 05 18:59:39 2017 +0200 @@ -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 @@ -42,6 +42,11 @@ AUTO_FILES_JAVA_DIRS = com/oracle/jrockit/jfr oracle/jrockit/jfr +JFC_XSD = oracle/jrockit/jfr/settings/jfc.xsd +JFC_XSD_SRC = $(CLOSED_SHARE_SRC)/classes/$(JFC_XSD) +JFC_XSD_FILE = $(CLASSDESTDIR)/$(JFC_XSD) + + # Find C source files # vpath %.c $(CLOSED_SHARE_SRC)/native/oracle/jfr @@ -59,15 +64,17 @@ $(RM) -r $(CLASSDESTDIR)/com/oracle/jrockit/jfr $(RM) -r $(CLASSDESTDIR)/oracle/jrockit/jfr - -# Copy pre-shipped .jfs files +# Copy pre-shipped .jfc files JFR_LIBDIR = $(LIBDIR)/jfr -JFR_SRCDIR = $(CLOSED_SHARE_SRC)/lib/jfr +JFC_SRCDIR = $(CLOSED_SHARE_SRC)/classes/oracle/jrockit/jfr/settings -$(JFR_LIBDIR)/%.jfs: $(JFR_SRCDIR)/%.jfs +$(JFR_LIBDIR)/%.jfc: $(JFC_SRCDIR)/%.jfc $(install-file) -JFS_FILES := $(subst $(JFR_SRCDIR),$(JFR_LIBDIR),$(wildcard $(JFR_SRCDIR)/*.jfs)) +JFC_FILES := $(subst $(JFC_SRCDIR),$(JFR_LIBDIR),$(wildcard $(JFC_SRCDIR)/*.jfc)) -all build : $(JFS_FILES) +$(JFC_XSD_FILE) : $(JFC_XSD_SRC) + $(install-file) +all build : $(JFC_FILES) $(JFC_XSD_FILE) + diff -r 41b9fc8961f6 -r f1a01fb5f958 jdk/makefiles/CompileNativeLibraries.gmk --- a/jdk/makefiles/CompileNativeLibraries.gmk Thu Jun 13 09:49:19 2013 -0700 +++ b/jdk/makefiles/CompileNativeLibraries.gmk Wed Jul 05 18:59:39 2017 +0200 @@ -2055,7 +2055,7 @@ ifeq ($(OPENJDK_TARGET_OS), windows) BUILD_LIBJLI_FILES += java_md.c \ - cmdtoargs.c + cmdtoargs.c # Staticically link with c runtime on windows. LIBJLI_CFLAGS:=$(filter-out -MD,$(LIBJLI_CFLAGS)) else ifneq ($(OPENJDK_TARGET_OS), macosx) @@ -2916,7 +2916,7 @@ PLATFORM_API_LinuxOS_ALSA_Ports.c,\ LANG:=C,\ OPTIMIZATION:=LOW, \ - CFLAGS:=$(CFLAGS_JDKLIB) \ + CFLAGS:=$(CFLAGS_JDKLIB) $(ALSA_CFLAGS) \ $(LIBJSOUND_CFLAGS) \ -DUSE_DAUDIO=TRUE \ -DUSE_PORTS=TRUE \ @@ -2925,7 +2925,7 @@ MAPFILE:=$(JDK_TOPDIR)/makefiles/mapfiles/libjsoundalsa/mapfile-vers, \ LDFLAGS:=$(LDFLAGS_JDKLIB)\ $(call SET_SHARED_LIBRARY_ORIGIN),\ - LDFLAGS_SUFFIX:=-lasound -ljava -ljvm,\ + LDFLAGS_SUFFIX:=$(ALSA_LIBS) -ljava -ljvm,\ OBJECT_DIR:=$(JDK_OUTPUTDIR)/objs/libjsoundalsa,\ DEBUG_SYMBOLS:=$(DEBUG_ALL_BINARIES))) diff -r 41b9fc8961f6 -r f1a01fb5f958 jdk/makefiles/CopyFiles.gmk --- a/jdk/makefiles/CopyFiles.gmk Thu Jun 13 09:49:19 2013 -0700 +++ b/jdk/makefiles/CopyFiles.gmk Wed Jul 05 18:59:39 2017 +0200 @@ -200,7 +200,7 @@ ifdef OPENJDK ICCPROFILE_SRC_DIR := $(JDK_TOPDIR)/src/share/lib/cmm/lcms -else +else ICCPROFILE_SRC_DIR := $(JDK_TOPDIR)/src/closed/share/lib/cmm/kcms endif @@ -217,29 +217,29 @@ #make sure freetype dll will be available at runtime as well as link time # -#NB: Default freetype build system uses -h linker option and -# result .so contains hardcoded library name that is later -# used for adding dependencies to other objects +#NB: Default freetype build system uses -h linker option and +# result .so contains hardcoded library name that is later +# used for adding dependencies to other objects # (e.g. libfontmanager.so). -# +# # It is not obvious how to extract that hardcoded name (libfreetype.so.6) # without overcomplicating logic here. # To workaround this we hardcode .6 suffix for now. # # Note that .so.6 library will not be found by System.loadLibrary() -# but fortunately we need to load FreeType library explicitly -# on windows only +# but fortunately we need to load FreeType library explicitly +# on windows only # #TODO: rework this to avoid hardcoding library name in the makefile # ifdef OPENJDK ifeq ($(OPENJDK_TARGET_OS), windows) FREETYPE_LIB = $(JDK_OUTPUTDIR)/bin/$(call SHARED_LIBRARY,freetype) - else + else ifeq ($(USING_SYSTEM_FT_LIB), false) FREETYPE_LIB = $(JDK_OUTPUTDIR)/lib$(OPENJDK_TARGET_CPU_LIBDIR)/$(call SHARED_LIBRARY,freetype).6 endif - endif + endif $(FREETYPE_LIB): $(FREETYPE2_LIB_PATH)/$(call SHARED_LIBRARY,freetype) $(CP) $(FREETYPE2_LIB_PATH)/$(call SHARED_LIBRARY,freetype) $@ @@ -537,3 +537,22 @@ COPY_FILES += $(JDK_OUTPUTDIR)/lib/sound.properties ########################################################################################## + +ifndef OPENJDK +ifeq ($(ENABLE_JFR), true) + +JFR_CONFIGURATION_DIR_SRC := $(JDK_TOPDIR)/src/closed/share/classes/oracle/jrockit/jfr/settings/ +JFR_CONFIGURATION_DIR_DST := $(LIBDIR)/jfr/ + +JFR_SRC_FILES = $(wildcard $(JFR_CONFIGURATION_DIR_SRC)/*.jfc) +JFR_TARGET_FILES = $(subst $(JFR_CONFIGURATION_DIR_SRC),$(JFR_CONFIGURATION_DIR_DST),$(JFR_SRC_FILES)) + +$(JFR_CONFIGURATION_DIR_DST)/%.jfc : $(JFR_CONFIGURATION_DIR_SRC)/%.jfc + $(call install-file) + +COPY_FILES += $(JFR_TARGET_FILES) + +endif +endif + +########################################################################################## diff -r 41b9fc8961f6 -r f1a01fb5f958 jdk/makefiles/CopyIntoClasses.gmk --- a/jdk/makefiles/CopyIntoClasses.gmk Thu Jun 13 09:49:19 2013 -0700 +++ b/jdk/makefiles/CopyIntoClasses.gmk Wed Jul 05 18:59:39 2017 +0200 @@ -42,7 +42,7 @@ $(JSTAT_RESOURCEDIR)/jstat_options \ $(JSTAT_RESOURCEDIR)/jstat_unsupported_options -# Extra jhat files +# Extra jhat files JHAT_RESOURCEDIR = $(JDK_TOPDIR)/src/share/classes/com/sun/tools/hat/resources COPY_FILES += \ $(JHAT_RESOURCEDIR)/hat.js \ @@ -53,7 +53,7 @@ JRUNSCRIPT_RESOURCEDIR = $(JDK_TOPDIR)/src/share/classes/com/sun/tools/script/shell COPY_FILES += \ $(JRUNSCRIPT_RESOURCEDIR)/init.js \ - $(JRUNSCRIPT_RESOURCEDIR)/messages.properties + $(JRUNSCRIPT_RESOURCEDIR)/messages.properties # Extra jvmstat files COPY_FILES += \ @@ -91,6 +91,12 @@ $(SWING_PLAF_WINDOWS_RESOURCES_DIR_CLOSED)/icons/JavaCup32.png endif +ifndef OPENJDK + JFR_CONFIGURATION_DIR_CLOSED = $(JDK_TOPDIR)/src/closed/share/classes/oracle/jrockit/jfr/settings + COPY_FILES += \ + $(JFR_CONFIGURATION_DIR_CLOSED)/jfc.xsd +endif + SWING_PLAF_BASIC_RESOURCES_DIR = $(JDK_TOPDIR)/src/share/classes/javax/swing/plaf/basic COPY_FILES += \ $(wildcard $(SWING_PLAF_BASIC_RESOURCES_DIR)/icons/*.png) @@ -154,7 +160,7 @@ # Copy the META-INF/services configuration files that are scattered around the source tree # into classes/META-INF/services. Be aware that META-INF directories that are located at a # source root (.../classes/META-INF) are automatically copied verbatim by the -# SetupJavaCompilation macro. +# SetupJavaCompilation macro. # # Any other META-INF/services configuration file is found here and platform specific comments # are uncommented and the configuration file is stored in the output META-INF directory. @@ -207,7 +213,7 @@ # Eval the newly created rules to incorporate them into the make tree. define addto_meta-inf_services $1 - echo $(LOG_INFO) Installing META-INF/services/$$(@F) + echo $(LOG_INFO) Installing META-INF/services/$$(@F) $(CAT) $$< | $(SED) -e "s/^#\[$(OPENJDK_TARGET_OS)\]//" > $$@ endef $(foreach i,$(META-INF_RULES_SERVICES),$(eval $(call addto_meta-inf_services,$i))) diff -r 41b9fc8961f6 -r f1a01fb5f958 jdk/makefiles/CreateJars.gmk --- a/jdk/makefiles/CreateJars.gmk Thu Jun 13 09:49:19 2013 -0700 +++ b/jdk/makefiles/CreateJars.gmk Wed Jul 05 18:59:39 2017 +0200 @@ -426,6 +426,7 @@ ifeq ($(ENABLE_JFR), true) $(eval $(call SetupArchive,BUILD_JFR_JAR,,\ SRCS:=$(JDK_OUTPUTDIR)/classes,\ + SUFFIXES:=.class .jfc .xsd,\ INCLUDES:=com/oracle/jrockit/jfr \ oracle/jrockit/jfr,\ JAR:=$(IMAGES_OUTPUTDIR)/lib/jfr.jar,\ diff -r 41b9fc8961f6 -r f1a01fb5f958 jdk/makefiles/mapfiles/libjfr/mapfile-vers --- a/jdk/makefiles/mapfiles/libjfr/mapfile-vers Thu Jun 13 09:49:19 2013 -0700 +++ b/jdk/makefiles/mapfiles/libjfr/mapfile-vers Wed Jul 05 18:59:39 2017 +0200 @@ -1,5 +1,5 @@ # -# Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. # ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. # @@ -17,7 +17,7 @@ Java_oracle_jrockit_jfr_VMJFR_addConstPool; Java_oracle_jrockit_jfr_VMJFR_removeConstPool; Java_oracle_jrockit_jfr_VMJFR_storeConstPool; - Java_oracle_jrockit_jfr_VMJFR_classID; + Java_oracle_jrockit_jfr_VMJFR_classID0; Java_oracle_jrockit_jfr_VMJFR_stackTraceID; Java_oracle_jrockit_jfr_VMJFR_threadID; Java_oracle_jrockit_jfr_VMJFR_rotate; @@ -33,7 +33,8 @@ Java_oracle_jrockit_jfr_VMJFR_setPeriod; Java_oracle_jrockit_jfr_VMJFR_getPeriod; Java_oracle_jrockit_jfr_VMJFR_descriptors; - JNI_OnLoad; + Java_oracle_jrockit_jfr_VMJFR_redefineClass0; + JNI_OnLoad; local: *; }; diff -r 41b9fc8961f6 -r f1a01fb5f958 jdk/makefiles/mapfiles/libjli/mapfile-vers --- a/jdk/makefiles/mapfiles/libjli/mapfile-vers Thu Jun 13 09:49:19 2013 -0700 +++ b/jdk/makefiles/mapfiles/libjli/mapfile-vers Wed Jul 05 18:59:39 2017 +0200 @@ -36,6 +36,7 @@ JLI_ReportExceptionDescription; JLI_GetStdArgs; JLI_GetStdArgc; + local: *; }; diff -r 41b9fc8961f6 -r f1a01fb5f958 jdk/src/share/lib/security/java.security-linux --- a/jdk/src/share/lib/security/java.security-linux Thu Jun 13 09:49:19 2013 -0700 +++ b/jdk/src/share/lib/security/java.security-linux Wed Jul 05 18:59:39 2017 +0200 @@ -202,6 +202,7 @@ com.sun.org.glassfish.,\ com.oracle.xmlns.internal.,\ com.oracle.webservices.internal.,\ + oracle.jrockit.jfr.,\ jdk.internal.,\ jdk.nashorn.internal.,\ jdk.nashorn.tools. @@ -243,6 +244,7 @@ com.sun.org.glassfish.,\ com.oracle.xmlns.internal.,\ com.oracle.webservices.internal.,\ + oracle.jrockit.jfr.,\ jdk.internal.,\ jdk.nashorn.internal.,\ jdk.nashorn.tools. diff -r 41b9fc8961f6 -r f1a01fb5f958 jdk/src/share/lib/security/java.security-macosx --- a/jdk/src/share/lib/security/java.security-macosx Thu Jun 13 09:49:19 2013 -0700 +++ b/jdk/src/share/lib/security/java.security-macosx Wed Jul 05 18:59:39 2017 +0200 @@ -206,7 +206,8 @@ jdk.internal.,\ jdk.nashorn.internal.,\ jdk.nashorn.tools.,\ - apple. + apple.,\ + oracle.jrockit.jfr. # # List of comma-separated packages that start with or equal this string @@ -247,7 +248,8 @@ jdk.internal.,\ jdk.nashorn.internal.,\ jdk.nashorn.tools.,\ - apple. + apple.,\ + oracle.jrockit.jfr. # # Determines whether this properties file can be appended to diff -r 41b9fc8961f6 -r f1a01fb5f958 jdk/src/share/lib/security/java.security-solaris --- a/jdk/src/share/lib/security/java.security-solaris Thu Jun 13 09:49:19 2013 -0700 +++ b/jdk/src/share/lib/security/java.security-solaris Wed Jul 05 18:59:39 2017 +0200 @@ -204,6 +204,7 @@ com.sun.org.glassfish.,\ com.oracle.xmlns.internal.,\ com.oracle.webservices.internal.,\ + oracle.jrockit.jfr.,\ jdk.internal.,\ jdk.nashorn.internal.,\ jdk.nashorn.tools. @@ -244,6 +245,7 @@ com.sun.org.glassfish.,\ com.oracle.xmlns.internal.,\ com.oracle.webservices.internal.,\ + oracle.jrockit.jfr.,\ jdk.internal.,\ jdk.nashorn.internal.,\ jdk.nashorn.tools. diff -r 41b9fc8961f6 -r f1a01fb5f958 jdk/src/share/lib/security/java.security-windows --- a/jdk/src/share/lib/security/java.security-windows Thu Jun 13 09:49:19 2013 -0700 +++ b/jdk/src/share/lib/security/java.security-windows Wed Jul 05 18:59:39 2017 +0200 @@ -203,6 +203,7 @@ com.sun.org.glassfish.,\ com.oracle.xmlns.internal.,\ com.oracle.webservices.internal.,\ + oracle.jrockit.jfr.,\ jdk.internal.,\ jdk.nashorn.internal.,\ jdk.nashorn.tools.,\ @@ -244,6 +245,7 @@ com.sun.org.glassfish.,\ com.oracle.xmlns.internal.,\ com.oracle.webservices.internal.,\ + oracle.jrockit.jfr.,\ jdk.internal.,\ jdk.nashorn.internal.,\ jdk.nashorn.tools.,\ diff -r 41b9fc8961f6 -r f1a01fb5f958 nashorn/.hgtags --- a/nashorn/.hgtags Thu Jun 13 09:49:19 2013 -0700 +++ b/nashorn/.hgtags Wed Jul 05 18:59:39 2017 +0200 @@ -203,3 +203,4 @@ 6b9f4120380091b8b1751a825b9f84bf1be224fe jdk8-b91 dee23cce5235b594a96d3361b65eacc97bd5a583 jdk8-b92 ddbf41575a2bdb12ccb9f91e169018bf04073038 jdk8-b93 +d92b756bc73966f1bfd111f44f3216cea3bba129 jdk8-b94