Mercurial > hg > icedtea7-forest > hotspot
changeset 4510:3295faa5b5cc hs24-b40
Merge
author | amurillo |
---|---|
date | Thu, 11 Apr 2013 22:44:41 -0700 |
parents | 0e7cb4f6dcb7 (current diff) 7097a4e746c1 (diff) |
children | 3e88170d8be2 |
files | .hgtags make/bsd/makefiles/wb.make make/linux/makefiles/wb.make make/solaris/makefiles/wb.make make/windows/makefiles/wb.make make/windows/projectfiles/kernel/Makefile make/windows/projectfiles/kernel/vm.def make/windows/projectfiles/kernel/vm.dsw src/share/tools/whitebox/sun/hotspot/WhiteBox.java src/share/tools/whitebox/sun/hotspot/parser/DiagnosticCommand.java |
diffstat | 100 files changed, 1575 insertions(+), 769 deletions(-) [+] |
line wrap: on
line diff
--- a/.hgtags Wed Apr 10 10:29:50 2013 -0700 +++ b/.hgtags Thu Apr 11 22:44:41 2013 -0700 @@ -465,3 +465,4 @@ 5e622bdc713e05a6a9f8dca35cf4c5887d4d3e4a jdk7u14-b19 94e094f461041abe877c1f4aaa22f72e252f5512 jdk7u14-b19 c23596bfe3b8a21076f8454a3cd6606ee7e928a5 jdk7u14-b20 +d6cf0e0eee29e173b8446455991e22249da0e860 hs24-b39
--- a/agent/src/share/classes/sun/jvm/hotspot/debugger/linux/amd64/LinuxAMD64CFrame.java Wed Apr 10 10:29:50 2013 -0700 +++ b/agent/src/share/classes/sun/jvm/hotspot/debugger/linux/amd64/LinuxAMD64CFrame.java Thu Apr 11 22:44:41 2013 -0700 @@ -60,8 +60,13 @@ return null; } + // Check alignment of rbp + if ( dbg.getAddressValue(rbp) % ADDRESS_SIZE != 0) { + return null; + } + Address nextRBP = rbp.getAddressAt( 0 * ADDRESS_SIZE); - if (nextRBP == null) { + if (nextRBP == null || nextRBP.lessThanOrEqual(rbp)) { return null; } Address nextPC = rbp.getAddressAt( 1 * ADDRESS_SIZE);
--- a/agent/src/share/classes/sun/jvm/hotspot/debugger/linux/x86/LinuxX86CFrame.java Wed Apr 10 10:29:50 2013 -0700 +++ b/agent/src/share/classes/sun/jvm/hotspot/debugger/linux/x86/LinuxX86CFrame.java Thu Apr 11 22:44:41 2013 -0700 @@ -61,8 +61,13 @@ return null; } + // Check alignment of ebp + if ( dbg.getAddressValue(ebp) % ADDRESS_SIZE != 0) { + return null; + } + Address nextEBP = ebp.getAddressAt( 0 * ADDRESS_SIZE); - if (nextEBP == null) { + if (nextEBP == null || nextEBP.lessThanOrEqual(ebp)) { return null; } Address nextPC = ebp.getAddressAt( 1 * ADDRESS_SIZE);
--- a/make/Makefile Wed Apr 10 10:29:50 2013 -0700 +++ b/make/Makefile Thu Apr 11 22:44:41 2013 -0700 @@ -393,9 +393,6 @@ $(EXPORT_LIB_DIR)/%.jar: $(GEN_DIR)/%.jar $(install-file) -$(EXPORT_JRE_LIB_DIR)/%.jar: $(GEN_DIR)/%.jar - $(install-file) - # Include files (jvmti.h, jvmticmlr.h, jni.h, $(JDK_INCLUDE_SUBDIR)/jni_md.h, jmm.h, jfr.h) $(EXPORT_INCLUDE_DIR)/%: $(GEN_DIR)/jvmtifiles/% $(install-file)
--- a/make/bsd/makefiles/defs.make Wed Apr 10 10:29:50 2013 -0700 +++ b/make/bsd/makefiles/defs.make Thu Apr 11 22:44:41 2013 -0700 @@ -156,8 +156,6 @@ EXPORT_SERVER_DIR = $(EXPORT_JRE_LIB_ARCH_DIR)/server EXPORT_CLIENT_DIR = $(EXPORT_JRE_LIB_ARCH_DIR)/client -EXPORT_LIST += $(EXPORT_JRE_LIB_DIR)/wb.jar - ifeq ($(findstring true, $(JVM_VARIANT_SERVER) $(JVM_VARIANT_ZERO) $(JVM_VARIANT_ZEROSHARK)), true) EXPORT_LIST += $(EXPORT_SERVER_DIR)/Xusage.txt EXPORT_LIST += $(EXPORT_SERVER_DIR)/libjvm.$(LIBRARY_SUFFIX)
--- a/make/bsd/makefiles/vm.make Wed Apr 10 10:29:50 2013 -0700 +++ b/make/bsd/makefiles/vm.make Thu Apr 11 22:44:41 2013 -0700 @@ -335,9 +335,6 @@ # Serviceability agent include $(MAKEFILES_DIR)/saproc.make -# Whitebox testing API -include $(MAKEFILES_DIR)/wb.make - #---------------------------------------------------------------------- ifeq ($(OS_VENDOR), Darwin) @@ -345,10 +342,10 @@ dsymutil $(LIBJVM) # no libjvm_db for macosx -build: $(LIBJVM) $(LAUNCHER) $(LIBJSIG) $(BUILDLIBSAPROC) dtraceCheck $(LIBJVM).dSYM $(WB_JAR) +build: $(LIBJVM) $(LAUNCHER) $(LIBJSIG) $(BUILDLIBSAPROC) dtraceCheck $(LIBJVM).dSYM echo "Doing vm.make build:" else -build: $(LIBJVM) $(LAUNCHER) $(LIBJSIG) $(LIBJVM_DB) $(BUILDLIBSAPROC) $(WB_JAR) +build: $(LIBJVM) $(LAUNCHER) $(LIBJSIG) $(LIBJVM_DB) $(BUILDLIBSAPROC) endif install: install_jvm install_jsig install_saproc
--- a/make/bsd/makefiles/wb.make Wed Apr 10 10:29:50 2013 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,46 +0,0 @@ -# -# 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. -# -# - -# Rules to build whitebox testing library, used by vm.make -WB = wb - -WBSRCDIR = $(GAMMADIR)/src/share/tools/whitebox - -WB_JAR = $(GENERATED)/$(WB).jar - -WB_JAVA_SRCS = $(shell find $(WBSRCDIR) -name '*.java') -WB_JAVA_CLASSDIR = $(GENERATED)/wb/classes - -WB_JAVA_CLASSES = $(patsubst $(WBSRCDIR)/%,$(WB_JAVA_CLASSDIR)/%, \ - $(patsubst %.java,%.class,$(WB_JAVA_SRCS))) - -$(WB_JAVA_CLASSDIR)/%.class: $(WBSRCDIR)/%.java $(WB_JAVA_CLASSDIR) - $(REMOTE) $(COMPILE.JAVAC) -sourcepath $(WBSRCDIR) -nowarn -d $(WB_JAVA_CLASSDIR) $< - -$(WB_JAR): $(WB_JAVA_CLASSES) - $(QUIETLY) $(REMOTE) $(RUN.JAR) cf $@ -C $(WB_JAVA_CLASSDIR)/ . - -$(WB_JAVA_CLASSDIR): - $(QUIETLY) mkdir -p $@ -
--- a/make/hotspot_version Wed Apr 10 10:29:50 2013 -0700 +++ b/make/hotspot_version Thu Apr 11 22:44:41 2013 -0700 @@ -35,7 +35,7 @@ HS_MAJOR_VER=24 HS_MINOR_VER=0 -HS_BUILD_NUMBER=38 +HS_BUILD_NUMBER=40 JDK_MAJOR_VER=1 JDK_MINOR_VER=7
--- a/make/linux/makefiles/defs.make Wed Apr 10 10:29:50 2013 -0700 +++ b/make/linux/makefiles/defs.make Thu Apr 11 22:44:41 2013 -0700 @@ -251,8 +251,6 @@ EXPORT_SERVER_DIR = $(EXPORT_JRE_LIB_ARCH_DIR)/server EXPORT_CLIENT_DIR = $(EXPORT_JRE_LIB_ARCH_DIR)/client -EXPORT_LIST += $(EXPORT_JRE_LIB_DIR)/wb.jar - ifeq ($(findstring true, $(JVM_VARIANT_SERVER) $(JVM_VARIANT_ZERO) $(JVM_VARIANT_ZEROSHARK)), true) EXPORT_LIST += $(EXPORT_SERVER_DIR)/Xusage.txt EXPORT_LIST += $(EXPORT_SERVER_DIR)/libjvm.$(LIBRARY_SUFFIX)
--- a/make/linux/makefiles/vm.make Wed Apr 10 10:29:50 2013 -0700 +++ b/make/linux/makefiles/vm.make Thu Apr 11 22:44:41 2013 -0700 @@ -377,12 +377,9 @@ # Serviceability agent include $(MAKEFILES_DIR)/saproc.make -# Whitebox testing API -include $(MAKEFILES_DIR)/wb.make - #---------------------------------------------------------------------- -build: $(LIBJVM) $(LAUNCHER) $(LIBJSIG) $(LIBJVM_DB) $(BUILDLIBSAPROC) dtraceCheck $(WB_JAR) +build: $(LIBJVM) $(LAUNCHER) $(LIBJSIG) $(LIBJVM_DB) $(BUILDLIBSAPROC) dtraceCheck install: install_jvm install_jsig install_saproc
--- a/make/linux/makefiles/wb.make Wed Apr 10 10:29:50 2013 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,46 +0,0 @@ -# -# 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. -# -# - -# Rules to build whitebox testing library, used by vm.make -WB = wb - -WBSRCDIR = $(GAMMADIR)/src/share/tools/whitebox - -WB_JAR = $(GENERATED)/$(WB).jar - -WB_JAVA_SRCS = $(shell find $(WBSRCDIR) -name '*.java') -WB_JAVA_CLASSDIR = $(GENERATED)/wb/classes - -WB_JAVA_CLASSES = $(patsubst $(WBSRCDIR)/%,$(WB_JAVA_CLASSDIR)/%, \ - $(patsubst %.java,%.class,$(WB_JAVA_SRCS))) - -$(WB_JAVA_CLASSDIR)/%.class: $(WBSRCDIR)/%.java $(WB_JAVA_CLASSDIR) - $(REMOTE) $(COMPILE.JAVAC) -sourcepath $(WBSRCDIR) -nowarn -d $(WB_JAVA_CLASSDIR) $< - -$(WB_JAR): $(WB_JAVA_CLASSES) - $(QUIETLY) $(REMOTE) $(RUN.JAR) cf $@ -C $(WB_JAVA_CLASSDIR)/ . - -$(WB_JAVA_CLASSDIR): - $(QUIETLY) mkdir -p $@ -
--- a/make/solaris/makefiles/defs.make Wed Apr 10 10:29:50 2013 -0700 +++ b/make/solaris/makefiles/defs.make Thu Apr 11 22:44:41 2013 -0700 @@ -187,8 +187,6 @@ endif endif -EXPORT_LIST += $(EXPORT_JRE_LIB_DIR)/wb.jar - EXPORT_SERVER_DIR = $(EXPORT_JRE_LIB_ARCH_DIR)/server EXPORT_CLIENT_DIR = $(EXPORT_JRE_LIB_ARCH_DIR)/client
--- a/make/solaris/makefiles/vm.make Wed Apr 10 10:29:50 2013 -0700 +++ b/make/solaris/makefiles/vm.make Thu Apr 11 22:44:41 2013 -0700 @@ -352,12 +352,9 @@ # Serviceability agent include $(MAKEFILES_DIR)/saproc.make -# Whitebox testing API -include $(MAKEFILES_DIR)/wb.make - #---------------------------------------------------------------------- -build: $(LIBJVM) $(LAUNCHER) $(LIBJSIG) $(LIBJVM_DB) $(LIBJVM_DTRACE) $(BUILDLIBSAPROC) dtraceCheck $(WB_JAR) +build: $(LIBJVM) $(LAUNCHER) $(LIBJSIG) $(LIBJVM_DB) $(LIBJVM_DTRACE) $(BUILDLIBSAPROC) dtraceCheck install: install_jvm install_jsig install_saproc
--- a/make/solaris/makefiles/wb.make Wed Apr 10 10:29:50 2013 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,46 +0,0 @@ -# -# 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. -# - -# Rules to build whitebox testing library, used by vm.make - -WB = wb - -WBSRCDIR = $(GAMMADIR)/src/share/tools/whitebox - -WB_JAR = $(GENERATED)/$(WB).jar - -WB_JAVA_SRCS = $(shell find $(WBSRCDIR) -name '*.java') -WB_JAVA_CLASSDIR = $(GENERATED)/wb/classes - -WB_JAVA_CLASSES = $(patsubst $(WBSRCDIR)/%,$(WB_JAVA_CLASSDIR)/%, \ - $(patsubst %.java,%.class,$(WB_JAVA_SRCS))) - -$(WB_JAVA_CLASSDIR)/%.class: $(WBSRCDIR)/%.java $(WB_JAVA_CLASSDIR) - $(REMOTE) $(COMPILE.JAVAC) -sourcepath $(WBSRCDIR) -nowarn -d $(WB_JAVA_CLASSDIR) $< - -$(WB_JAR): $(WB_JAVA_CLASSES) - $(QUIETLY) $(REMOTE) $(RUN.JAR) cf $@ -C $(WB_JAVA_CLASSDIR)/ . - -$(WB_JAVA_CLASSDIR): - $(QUIETLY) mkdir -p $@ -
--- a/make/windows/build.make Wed Apr 10 10:29:50 2013 -0700 +++ b/make/windows/build.make Thu Apr 11 22:44:41 2013 -0700 @@ -110,8 +110,6 @@ !endif !elseif "$(Variant)" == "tiered" VARIANT_TEXT=Tiered -!elseif "$(Variant)" == "kernel" -VARIANT_TEXT=Kernel !endif ######################################################################### @@ -198,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 @@ -284,6 +288,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) >> $@ @@ -310,9 +315,9 @@ checks: checkVariant checkWorkSpace checkSA checkVariant: - @ if "$(Variant)"=="" echo Need to specify "Variant=[tiered|compiler2|compiler1|kernel|core]" && false - @ if "$(Variant)" NEQ "tiered" if "$(Variant)" NEQ "compiler2" if "$(Variant)" NEQ "compiler1" if "$(Variant)" NEQ "kernel" if "$(Variant)" NEQ "core" \ - echo Need to specify "Variant=[tiered|compiler2|compiler1|kernel|core]" && false + @ if "$(Variant)"=="" echo Need to specify "Variant=[tiered|compiler2|compiler1|core]" && false + @ if "$(Variant)" NEQ "tiered" if "$(Variant)" NEQ "compiler2" if "$(Variant)" NEQ "compiler1" if "$(Variant)" NEQ "core" \ + echo Need to specify "Variant=[tiered|compiler2|compiler1|core]" && false checkWorkSpace: @ if "$(WorkSpace)"=="" echo Need to specify "WorkSpace=..." && false
--- a/make/windows/create.bat Wed Apr 10 10:29:50 2013 -0700 +++ b/make/windows/create.bat Thu Apr 11 22:44:41 2013 -0700 @@ -148,7 +148,7 @@ REM This is now safe to do. :copyfiles -for /D %%i in (compiler1, compiler2, tiered, core, kernel) do ( +for /D %%i in (compiler1, compiler2, tiered, core) do ( if NOT EXIST %HotSpotBuildSpace%\%%i\generated mkdir %HotSpotBuildSpace%\%%i\generated copy %HotSpotWorkSpace%\make\windows\projectfiles\%%i\* %HotSpotBuildSpace%\%%i\generated > NUL ) @@ -156,7 +156,7 @@ REM force regneration of ProjectFile if exist %ProjectFile% del %ProjectFile% -for /D %%i in (compiler1, compiler2, tiered, core, kernel) do ( +for /D %%i in (compiler1, compiler2, tiered, core) do ( echo -- %%i -- echo # Generated file! > %HotSpotBuildSpace%\%%i\local.make echo # Changing a variable below and then deleting %ProjectFile% will cause >> %HotSpotBuildSpace%\%%i\local.make
--- a/make/windows/makefiles/compile.make Wed Apr 10 10:29:50 2013 -0700 +++ b/make/windows/makefiles/compile.make Thu Apr 11 22:44:41 2013 -0700 @@ -221,13 +221,6 @@ !endif !endif -# Compile for space above time. -!if "$(Variant)" == "kernel" -PRODUCT_OPT_OPTION = /O1 /Oy- -FASTDEBUG_OPT_OPTION = /O1 /Oy- -DEBUG_OPT_OPTION = /Od -!endif - # If NO_OPTIMIZATIONS is defined in the environment, turn everything off !ifdef NO_OPTIMIZATIONS PRODUCT_OPT_OPTION = $(DEBUG_OPT_OPTION)
--- a/make/windows/makefiles/debug.make Wed Apr 10 10:29:50 2013 -0700 +++ b/make/windows/makefiles/debug.make Thu Apr 11 22:44:41 2013 -0700 @@ -33,7 +33,7 @@ BUILD_PCH_FILE=_build_pch_file.obj !endif -default:: $(BUILD_PCH_FILE) $(AOUT) launcher checkAndBuildSA wb +default:: $(BUILD_PCH_FILE) $(AOUT) launcher checkAndBuildSA !include ../local.make !include compile.make @@ -72,4 +72,3 @@ !include $(WorkSpace)/make/windows/makefiles/shared.make !include $(WorkSpace)/make/windows/makefiles/sa.make !include $(WorkSpace)/make/windows/makefiles/launcher.make -!include $(WorkSpace)/make/windows/makefiles/wb.make
--- a/make/windows/makefiles/defs.make Wed Apr 10 10:29:50 2013 -0700 +++ b/make/windows/makefiles/defs.make Thu Apr 11 22:44:41 2013 -0700 @@ -277,8 +277,6 @@ endif endif -EXPORT_LIST += $(EXPORT_JRE_LIB_DIR)/wb.jar - ifeq ($(BUILD_WIN_SA), 1) EXPORT_LIST += $(EXPORT_JRE_BIN_DIR)/sawindbg.$(LIBRARY_SUFFIX) ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1)
--- a/make/windows/makefiles/fastdebug.make Wed Apr 10 10:29:50 2013 -0700 +++ b/make/windows/makefiles/fastdebug.make Thu Apr 11 22:44:41 2013 -0700 @@ -33,7 +33,7 @@ BUILD_PCH_FILE=_build_pch_file.obj !endif -default:: $(BUILD_PCH_FILE) $(AOUT) launcher checkAndBuildSA wb +default:: $(BUILD_PCH_FILE) $(AOUT) launcher checkAndBuildSA !include ../local.make !include compile.make @@ -71,4 +71,3 @@ !include $(WorkSpace)/make/windows/makefiles/shared.make !include $(WorkSpace)/make/windows/makefiles/sa.make !include $(WorkSpace)/make/windows/makefiles/launcher.make -!include $(WorkSpace)/make/windows/makefiles/wb.make
--- a/make/windows/makefiles/product.make Wed Apr 10 10:29:50 2013 -0700 +++ b/make/windows/makefiles/product.make Thu Apr 11 22:44:41 2013 -0700 @@ -32,7 +32,7 @@ BUILD_PCH_FILE=_build_pch_file.obj !endif -default:: $(BUILD_PCH_FILE) $(AOUT) launcher checkAndBuildSA wb +default:: $(BUILD_PCH_FILE) $(AOUT) launcher checkAndBuildSA !include ../local.make !include compile.make @@ -51,13 +51,6 @@ # Force resources to be rebuilt every time $(Res_Files): FORCE -# Kernel doesn't need exported vtbl symbols. -!if "$(Variant)" == "kernel" -$(AOUT): $(Res_Files) $(Obj_Files) - $(LD) @<< - $(LD_FLAGS) /out:$@ /implib:$*.lib $(Obj_Files) $(Res_Files) -<< -!else vm.def: $(Obj_Files) sh $(WorkSpace)/make/windows/build_vm_def.sh @@ -65,7 +58,6 @@ $(LD) @<< $(LD_FLAGS) /out:$@ /implib:$*.lib /def:vm.def $(Obj_Files) $(Res_Files) << -!endif !if "$(MT)" != "" # The previous link command created a .manifest file that we want to # insert into the linked artifact so we do not need to track it @@ -82,4 +74,3 @@ !include $(WorkSpace)/make/windows/makefiles/shared.make !include $(WorkSpace)/make/windows/makefiles/sa.make !include $(WorkSpace)/make/windows/makefiles/launcher.make -!include $(WorkSpace)/make/windows/makefiles/wb.make
--- a/make/windows/makefiles/trace.make Wed Apr 10 10:29:50 2013 -0700 +++ b/make/windows/makefiles/trace.make Thu Apr 11 22:44:41 2013 -0700 @@ -116,8 +116,6 @@ # ######################################################################### cleanall : -!if "$(INCLUDE_TRACE)" == "1" rm $(TraceGeneratedFiles) -!endif
--- a/make/windows/makefiles/wb.make Wed Apr 10 10:29:50 2013 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,54 +0,0 @@ -# -# 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. -# -# - -# This makefile is used to build the whitebox testing lib -# and compile the tests which use it - -!include $(WorkSpace)/make/windows/makefiles/rules.make - -WBSRCDIR = $(WorkSpace)/src/share/tools/whitebox - -# turn GENERATED into a windows path to get sane dependencies -WB_CLASSES=$(GENERATED:/=\)\wb\classes -WB_JAR=$(GENERATED:/=\)\wb.jar - -# call recursive make to do wildcard expansion -.SUFFIXES : .java .class -wb_java_srcs: $(WorkSpace)\src\share\tools\whitebox\sun\hotspot\*.java $(WB_CLASSES) - $(MAKE) -f $(WorkSpace)\make\windows\makefiles\$(BUILD_FLAVOR).make $(**:.java=.class) - - -{$(WorkSpace)\src\share\tools\whitebox\sun\hotspot}.java.class:: - $(COMPILE_JAVAC) -sourcepath $(WBSRCDIR) -d $(WB_CLASSES) $< - -$(WB_JAR): wb_java_srcs - $(RUN_JAR) cf $@ -C $(WB_CLASSES) . - -# turn $@ to a unix path because mkdir in PATH is cygwin/mks mkdir -$(WB_CLASSES): - mkdir -p $(@:\=/) - -# main target to build wb -wb: $(WB_JAR) -
--- a/make/windows/projectfiles/common/Makefile Wed Apr 10 10:29:50 2013 -0700 +++ b/make/windows/projectfiles/common/Makefile Thu Apr 11 22:44:41 2013 -0700 @@ -45,12 +45,11 @@ !endif !endif -!ifndef OPENJDK -!if exist($(WorkSpace)\src\closed) -OPENJDK=false -!else -OPENJDK=true -!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
--- a/make/windows/projectfiles/kernel/Makefile Wed Apr 10 10:29:50 2013 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,27 +0,0 @@ -# -# Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. -# 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 ../local.make - -!include $(HOTSPOTWORKSPACE)/make/windows/projectfiles/common/Makefile
--- a/make/windows/projectfiles/kernel/vm.def Wed Apr 10 10:29:50 2013 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,7 +0,0 @@ -; -; This .DEF file is a placeholder for one which is automatically -; generated during the build process. See -; make\windows\build_vm_def.sh and -; make\windows\makefiles\projectcreator.make (esp. the "-prelink" -; options). -;
--- a/make/windows/projectfiles/kernel/vm.dsw Wed Apr 10 10:29:50 2013 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,29 +0,0 @@ -Microsoft Developer Studio Workspace File, Format Version 6.00 -# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! - -############################################################################### - -Project: "vm"=.\vm.dsp - Package Owner=<4> - -Package=<5> -{{{ -}}} - -Package=<4> -{{{ -}}} - -############################################################################### - -Global: - -Package=<5> -{{{ -}}} - -Package=<3> -{{{ -}}} - -############################################################################### -
--- a/src/os/linux/vm/globals_linux.hpp Wed Apr 10 10:29:50 2013 -0700 +++ b/src/os/linux/vm/globals_linux.hpp Thu Apr 11 22:44:41 2013 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2011, 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 @@ -40,6 +40,9 @@ product(bool, UseHugeTLBFS, false, \ "Use MAP_HUGETLB for large pages") \ \ + product(bool, LoadExecStackDllInVMThread, true, \ + "Load DLLs with executable-stack attribute in the VM Thread") \ + \ product(bool, UseSHM, false, \ "Use SYSV shared memory for large pages")
--- a/src/os/linux/vm/os_linux.cpp Wed Apr 10 10:29:50 2013 -0700 +++ b/src/os/linux/vm/os_linux.cpp Thu Apr 11 22:44:41 2013 -0700 @@ -43,6 +43,7 @@ #include "runtime/extendedPC.hpp" #include "runtime/globals.hpp" #include "runtime/interfaceSupport.hpp" +#include "runtime/init.hpp" #include "runtime/java.hpp" #include "runtime/javaCalls.hpp" #include "runtime/mutexLocker.hpp" @@ -61,6 +62,7 @@ #include "utilities/decoder.hpp" #include "utilities/defaultStream.hpp" #include "utilities/events.hpp" +#include "utilities/elfFile.hpp" #include "utilities/growableArray.hpp" #include "utilities/vmError.hpp" #ifdef TARGET_ARCH_x86 @@ -1816,20 +1818,101 @@ // in case of error it checks if .dll/.so was built for the // same architecture as Hotspot is running on + +// Remember the stack's state. The Linux dynamic linker will change +// the stack to 'executable' at most once, so we must safepoint only once. +bool os::Linux::_stack_is_executable = false; + +// VM operation that loads a library. This is necessary if stack protection +// of the Java stacks can be lost during loading the library. If we +// do not stop the Java threads, they can stack overflow before the stacks +// are protected again. +class VM_LinuxDllLoad: public VM_Operation { + private: + const char *_filename; + char *_ebuf; + int _ebuflen; + void *_lib; + public: + VM_LinuxDllLoad(const char *fn, char *ebuf, int ebuflen) : + _filename(fn), _ebuf(ebuf), _ebuflen(ebuflen), _lib(NULL) {} + VMOp_Type type() const { return VMOp_LinuxDllLoad; } + void doit() { + _lib = os::Linux::dll_load_in_vmthread(_filename, _ebuf, _ebuflen); + os::Linux::_stack_is_executable = true; + } + void* loaded_library() { return _lib; } +}; + void * os::dll_load(const char *filename, char *ebuf, int ebuflen) { - void * result= ::dlopen(filename, RTLD_LAZY); + void * result = NULL; + bool load_attempted = false; + + // Check whether the library to load might change execution rights + // of the stack. If they are changed, the protection of the stack + // guard pages will be lost. We need a safepoint to fix this. + // + // See Linux man page execstack(8) for more info. + if (os::uses_stack_guard_pages() && !os::Linux::_stack_is_executable) { + ElfFile ef(filename); + if (!ef.specifies_noexecstack()) { + if (!is_init_completed()) { + os::Linux::_stack_is_executable = true; + // This is OK - No Java threads have been created yet, and hence no + // stack guard pages to fix. + // + // This should happen only when you are building JDK7 using a very + // old version of JDK6 (e.g., with JPRT) and running test_gamma. + // + // Dynamic loader will make all stacks executable after + // this function returns, and will not do that again. + assert(Threads::first() == NULL, "no Java threads should exist yet."); + } else { + warning("You have loaded library %s which might have disabled stack guard. " + "The VM will try to fix the stack guard now.\n" + "It's highly recommended that you fix the library with " + "'execstack -c <libfile>', or link it with '-z noexecstack'.", + filename); + + assert(Thread::current()->is_Java_thread(), "must be Java thread"); + JavaThread *jt = JavaThread::current(); + if (jt->thread_state() != _thread_in_native) { + // This happens when a compiler thread tries to load a hsdis-<arch>.so file + // that requires ExecStack. Cannot enter safe point. Let's give up. + warning("Unable to fix stack guard. Giving up."); + } else { + if (!LoadExecStackDllInVMThread) { + // This is for the case where the DLL has an static + // constructor function that executes JNI code. We cannot + // load such DLLs in the VMThread. + result = os::Linux::dlopen_helper(filename, ebuf, ebuflen); + } + + ThreadInVMfromNative tiv(jt); + debug_only(VMNativeEntryWrapper vew;) + + VM_LinuxDllLoad op(filename, ebuf, ebuflen); + VMThread::execute(&op); + if (LoadExecStackDllInVMThread) { + result = op.loaded_library(); + } + load_attempted = true; + } + } + } + } + + if (!load_attempted) { + result = os::Linux::dlopen_helper(filename, ebuf, ebuflen); + } + if (result != NULL) { // Successful loading return result; } Elf32_Ehdr elf_head; - - // Read system error message into ebuf - // It may or may not be overwritten below - ::strncpy(ebuf, ::dlerror(), ebuflen-1); - ebuf[ebuflen-1]='\0'; int diag_msg_max_length=ebuflen-strlen(ebuf); char* diag_msg_buf=ebuf+strlen(ebuf); @@ -1972,6 +2055,47 @@ return NULL; } +void * os::Linux::dlopen_helper(const char *filename, char *ebuf, int ebuflen) { + void * result = ::dlopen(filename, RTLD_LAZY); + if (result == NULL) { + ::strncpy(ebuf, ::dlerror(), ebuflen - 1); + ebuf[ebuflen-1] = '\0'; + } + return result; +} + +void * os::Linux::dll_load_in_vmthread(const char *filename, char *ebuf, int ebuflen) { + void * result = NULL; + if (LoadExecStackDllInVMThread) { + result = dlopen_helper(filename, ebuf, ebuflen); + } + + // Since 7019808, libjvm.so is linked with -noexecstack. If the VM loads a + // library that requires an executable stack, or which does not have this + // stack attribute set, dlopen changes the stack attribute to executable. The + // read protection of the guard pages gets lost. + // + // Need to check _stack_is_executable again as multiple VM_LinuxDllLoad + // may have been queued at the same time. + + if (!_stack_is_executable) { + JavaThread *jt = Threads::first(); + + while (jt) { + if (!jt->stack_guard_zone_unused() && // Stack not yet fully initialized + jt->stack_yellow_zone_enabled()) { // No pending stack overflow exceptions + if (!os::guard_memory((char *) jt->stack_red_zone_base() - jt->stack_red_zone_size(), + jt->stack_yellow_zone_size() + jt->stack_red_zone_size())) { + warning("Attempt to reguard stack yellow zone failed."); + } + } + jt = jt->next(); + } + } + + return result; +} + /* * glibc-2.0 libdl is not MT safe. If you are building with any glibc, * chances are you might want to run the generated bits against glibc-2.0
--- a/src/os/linux/vm/os_linux.hpp Wed Apr 10 10:29:50 2013 -0700 +++ b/src/os/linux/vm/os_linux.hpp Thu Apr 11 22:44:41 2013 -0700 @@ -94,6 +94,10 @@ static void print_libversion_info(outputStream* st); public: + static bool _stack_is_executable; + static void *dlopen_helper(const char *name, char *ebuf, int ebuflen); + static void *dll_load_in_vmthread(const char *name, char *ebuf, int ebuflen); + static void init_thread_fpu_state(); static int get_fpu_control_word(); static void set_fpu_control_word(int fpu_control);
--- a/src/os_cpu/linux_sparc/vm/os_linux_sparc.cpp Wed Apr 10 10:29:50 2013 -0700 +++ b/src/os_cpu/linux_sparc/vm/os_linux_sparc.cpp Thu Apr 11 22:44:41 2013 -0700 @@ -410,6 +410,11 @@ // to handle_unexpected_exception way down below. thread->disable_stack_red_zone(); tty->print_raw_cr("An irrecoverable stack overflow has occurred."); + + // This is a likely cause, but hard to verify. Let's just print + // it as a hint. + tty->print_raw_cr("Please check if any of your loaded .so files has " + "enabled executable stack (see man page execstack(8))"); } else { // Accessing stack address below sp may cause SEGV if current // thread has MAP_GROWSDOWN stack. This should only happen when
--- a/src/os_cpu/linux_x86/vm/os_linux_x86.cpp Wed Apr 10 10:29:50 2013 -0700 +++ b/src/os_cpu/linux_x86/vm/os_linux_x86.cpp Thu Apr 11 22:44:41 2013 -0700 @@ -306,6 +306,11 @@ // to handle_unexpected_exception way down below. thread->disable_stack_red_zone(); tty->print_raw_cr("An irrecoverable stack overflow has occurred."); + + // This is a likely cause, but hard to verify. Let's just print + // it as a hint. + tty->print_raw_cr("Please check if any of your loaded .so files has " + "enabled executable stack (see man page execstack(8))"); } else { // Accessing stack address below sp may cause SEGV if current // thread has MAP_GROWSDOWN stack. This should only happen when
--- a/src/share/tools/ProjectCreator/BuildConfig.java Wed Apr 10 10:29:50 2013 -0700 +++ b/src/share/tools/ProjectCreator/BuildConfig.java Thu Apr 11 22:44:41 2013 -0700 @@ -568,36 +568,6 @@ } } -class KernelDebugConfig extends GenericDebugConfig { - String getOptFlag() { - return getCI().getNoOptFlag(); - } - - KernelDebugConfig() { - initNames("kernel", "debug", "jvm.dll"); - init(getIncludes(), getDefines()); - } -} - - -class KernelFastDebugConfig extends GenericDebugConfig { - String getOptFlag() { - return getCI().getOptFlag(); - } - - KernelFastDebugConfig() { - initNames("kernel", "fastdebug", "jvm.dll"); - init(getIncludes(), getDefines()); - } -} - - -class KernelProductConfig extends ProductConfig { - KernelProductConfig() { - initNames("kernel", "product", "jvm.dll"); - init(getIncludes(), getDefines()); - } -} abstract class CompilerInterface { abstract Vector getBaseCompilerFlags(Vector defines, Vector includes, String outDir);
--- a/src/share/tools/ProjectCreator/WinGammaPlatform.java Wed Apr 10 10:29:50 2013 -0700 +++ b/src/share/tools/ProjectCreator/WinGammaPlatform.java Thu Apr 11 22:44:41 2013 -0700 @@ -564,12 +564,6 @@ allConfigs.add(new CoreFastDebugConfig()); allConfigs.add(new CoreProductConfig()); - if (platform.equals("Win32")) { - allConfigs.add(new KernelDebugConfig()); - allConfigs.add(new KernelFastDebugConfig()); - allConfigs.add(new KernelProductConfig()); - } - return allConfigs; }
--- a/src/share/tools/whitebox/sun/hotspot/WhiteBox.java Wed Apr 10 10:29:50 2013 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,77 +0,0 @@ -/* - * 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. - * - */ - -package sun.hotspot; -import java.security.BasicPermission; -import sun.hotspot.parser.DiagnosticCommand; - -public class WhiteBox { - - @SuppressWarnings("serial") - public static class WhiteBoxPermission extends BasicPermission { - public WhiteBoxPermission(String s) { - super(s); - } - } - - private WhiteBox() {} - private static final WhiteBox instance = new WhiteBox(); - private static native void registerNatives(); - - /** - * Returns the singleton WhiteBox instance. - * - * The returned WhiteBox object should be carefully guarded - * by the caller, since it can be used to read and write data - * at arbitrary memory addresses. It must never be passed to - * untrusted code. - */ - public synchronized static WhiteBox getWhiteBox() { - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - sm.checkPermission(new WhiteBoxPermission("getInstance")); - } - return instance; - } - - static { - registerNatives(); - } - - // Memory - public native long getObjectAddress(Object o); - public native int getHeapOopSize(); - - // G1 - public native boolean g1InConcurrentMark(); - public native boolean g1IsHumongous(Object o); - public native long g1NumFreeRegions(); - public native int g1RegionSize(); - public native Object[] parseCommandLine(String commandline, DiagnosticCommand[] args); - - // NMT - public native boolean NMTAllocTest(); - public native boolean NMTFreeTestMemory(); - public native boolean NMTWaitForDataMerge(); -}
--- a/src/share/tools/whitebox/sun/hotspot/parser/DiagnosticCommand.java Wed Apr 10 10:29:50 2013 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,43 +0,0 @@ -package sun.hotspot.parser; - -public class DiagnosticCommand { - - public enum DiagnosticArgumentType { - JLONG, BOOLEAN, STRING, NANOTIME, STRINGARRAY, MEMORYSIZE - } - - private String name; - private String desc; - private DiagnosticArgumentType type; - private boolean mandatory; - private String defaultValue; - - public DiagnosticCommand(String name, String desc, DiagnosticArgumentType type, - boolean mandatory, String defaultValue) { - this.name = name; - this.desc = desc; - this.type = type; - this.mandatory = mandatory; - this.defaultValue = defaultValue; - } - - public String getName() { - return name; - } - - public String getDesc() { - return desc; - } - - public DiagnosticArgumentType getType() { - return type; - } - - public boolean isMandatory() { - return mandatory; - } - - public String getDefaultValue() { - return defaultValue; - } -}
--- a/src/share/vm/c1/c1_FrameMap.cpp Wed Apr 10 10:29:50 2013 -0700 +++ b/src/share/vm/c1/c1_FrameMap.cpp Thu Apr 11 22:44:41 2013 -0700 @@ -308,27 +308,6 @@ return sp_offset_for_monitor_base(index) + in_ByteSize(BasicObjectLock::obj_offset_in_bytes()); } -void FrameMap::print_frame_layout() const { - int svar; - tty->print_cr("#####################################"); - tty->print_cr("Frame size in words %d", framesize()); - - if( _num_monitors > 0) { - tty->print_cr("monitor [0]:%d | [%2d]:%d", - in_bytes(sp_offset_for_monitor_base(0)), - in_bytes(sp_offset_for_monitor_base(_num_monitors))); - } - if( _num_spills > 0) { - svar = _num_spills - 1; - if(svar == 0) - tty->print_cr("spill [0]:%d", in_bytes(sp_offset_for_spill(0))); - else - tty->print_cr("spill [0]:%d | [%2d]:%d", in_bytes(sp_offset_for_spill(0)), - svar, - in_bytes(sp_offset_for_spill(svar))); - } -} - // For OopMaps, map a local variable or spill index to an VMReg. // This is the offset from sp() in the frame of the slot for the index,
--- a/src/share/vm/c1/c1_FrameMap.hpp Wed Apr 10 10:29:50 2013 -0700 +++ b/src/share/vm/c1/c1_FrameMap.hpp Thu Apr 11 22:44:41 2013 -0700 @@ -222,8 +222,6 @@ return make_new_address(sp_offset_for_monitor_object(monitor_index)); } - void print_frame_layout() const; - // Creates Location describing desired slot and returns it via pointer // to Location object. Returns true if the stack frame offset was legal // (as defined by Location::legal_offset_in_bytes()), false otherwise.
--- a/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp Wed Apr 10 10:29:50 2013 -0700 +++ b/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp Thu Apr 11 22:44:41 2013 -0700 @@ -1695,6 +1695,24 @@ } } +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. @@ -1852,14 +1870,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(); } if (should_compact) { @@ -2193,6 +2205,7 @@ } else { assert(_collectorState == Idling, "Should be idling before start."); _collectorState = InitialMarking; + register_gc_start(GCCause::_cms_concurrent_mark); // Reset the expansion cause, now that we are about to begin // a new cycle. clear_expansion_cause(); @@ -2359,6 +2372,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" @@ -2414,6 +2428,12 @@ } } +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()); @@ -2422,12 +2442,24 @@ 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_perm_gen_summary = gch->create_perm_gen_summary(); +} + +void CMSCollector::report_heap_summary(GCWhen::Type when) { + _gc_tracer_cm->report_gc_heap_summary(when, _last_heap_summary, _last_perm_gen_summary); +} + void CMSCollector::collect_in_foreground(bool clear_all_soft_refs) { assert(_foregroundGCIsActive && !_foregroundGCShouldWait, "Foreground collector should be waiting, not executing"); @@ -2461,7 +2493,7 @@ } switch (_collectorState) { case InitialMarking: - register_gc_start(GenCollectedHeap::heap()->gc_cause()); + register_foreground_gc_start(GenCollectedHeap::heap()->gc_cause()); init_mark_was_synchronous = true; // fact to be exploited in re-mark checkpointRootsInitial(false); assert(_collectorState == Marking, "Collector state should have changed" @@ -2514,6 +2546,7 @@ gclog_or_tty->print("Verify before reset: "); Universe::verify(); } + save_heap_summary(); reset(false); assert(_collectorState == Idling, "Collector state should " "have changed"); @@ -3498,6 +3531,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"); @@ -5052,6 +5088,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
--- a/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp Wed Apr 10 10:29:50 2013 -0700 +++ b/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp Thu Apr 11 22:44:41 2013 -0700 @@ -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" @@ -615,8 +617,15 @@ ConcurrentGCTimer* _gc_timer_cm; bool _cms_start_registered; + + GCHeapSummary _last_heap_summary; + PermGenSummary _last_perm_gen_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) @@ -842,6 +851,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);
--- a/src/share/vm/gc_implementation/concurrentMarkSweep/vmCMSOperations.cpp Wed Apr 10 10:29:50 2013 -0700 +++ b/src/share/vm/gc_implementation/concurrentMarkSweep/vmCMSOperations.cpp Thu Apr 11 22:44:41 2013 -0700 @@ -145,7 +145,6 @@ ); #endif /* USDT2 */ - _collector->register_gc_start(GCCause::_cms_concurrent_mark); _collector->_gc_timer_cm->register_gc_pause_start("Initial Mark", os::elapsed_counter()); GenCollectedHeap* gch = GenCollectedHeap::heap(); @@ -195,6 +194,7 @@ VM_CMS_Operation::verify_after_gc(); + _collector->save_heap_summary(); _collector->_gc_timer_cm->register_gc_pause_end(os::elapsed_counter()); #ifndef USDT2
--- a/src/share/vm/gc_implementation/g1/concurrentMark.cpp Wed Apr 10 10:29:50 2013 -0700 +++ b/src/share/vm/gc_implementation/g1/concurrentMark.cpp Thu Apr 11 22:44:41 2013 -0700 @@ -1202,6 +1202,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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/vm/gc_implementation/g1/evacuationInfo.hpp Thu Apr 11 22:44:41 2013 -0700 @@ -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
--- a/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Wed Apr 10 10:29:50 2013 -0700 +++ b/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Thu Apr 11 22:44:41 2013 -0700 @@ -81,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). @@ -462,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(); @@ -552,7 +552,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); @@ -627,7 +627,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) { @@ -692,7 +692,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. @@ -866,7 +866,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; /* we'll return */; try_count += 1) { unsigned int gc_count_before; @@ -996,7 +996,7 @@ GC_locker::stall_until_clear(); } - // 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 @@ -1114,7 +1114,7 @@ GC_locker::stall_until_clear(); } - // 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 @@ -1423,7 +1423,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(); @@ -2059,7 +2059,7 @@ } // 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()); @@ -2494,7 +2494,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(); } @@ -3074,7 +3074,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(); @@ -3833,6 +3833,8 @@ // 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. @@ -3954,7 +3956,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 @@ -3990,10 +3992,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 @@ -4005,7 +4007,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(); @@ -4082,7 +4084,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 */, @@ -4095,7 +4097,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(); @@ -4170,8 +4172,9 @@ // 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()); } @@ -4231,7 +4234,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(); @@ -4246,7 +4249,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() && @@ -4263,10 +4266,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 @@ -5209,7 +5215,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 perm 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)) { @@ -5379,7 +5385,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. @@ -5508,7 +5514,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 @@ -5629,7 +5635,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"); @@ -5646,13 +5652,13 @@ // 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); @@ -5740,7 +5746,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(); concurrent_g1_refine()->clear_hot_cache(); @@ -5760,7 +5766,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. @@ -5982,7 +5988,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"); @@ -6068,10 +6074,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();
--- a/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp Wed Apr 10 10:29:50 2013 -0700 +++ b/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp Thu Apr 11 22:44:41 2013 -0700 @@ -26,6 +26,7 @@ #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" @@ -330,10 +331,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. @@ -786,7 +787,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; @@ -814,7 +815,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. @@ -1174,7 +1175,7 @@ // 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; }
--- a/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp Wed Apr 10 10:29:50 2013 -0700 +++ b/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp Thu Apr 11 22:44:41 2013 -0700 @@ -911,7 +911,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"); @@ -951,6 +951,9 @@ (double)surviving_bytes/ (double)_collection_set_bytes_used_before; + 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 @@ -1842,7 +1845,7 @@ return true; } -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(); @@ -2024,6 +2027,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) {
--- a/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp Wed Apr 10 10:29:50 2013 -0700 +++ b/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp Thu Apr 11 22:44:41 2013 -0700 @@ -681,7 +681,7 @@ void record_concurrent_pause(); - void record_collection_pause_end(double pause_time); + void record_collection_pause_end(double pause_time, EvacuationInfo& evacuation_info); void print_heap_transition(); void print_detailed_heap_transition(); @@ -709,7 +709,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. @@ -861,6 +861,7 @@ ageTable _survivors_age_table; public: + uint tenuring_threshold() const { return _tenuring_threshold; } inline GCAllocPurpose evacuation_destination(HeapRegion* src_region, int age, size_t word_sz) {
--- a/src/share/vm/gc_implementation/g1/g1MarkSweep.cpp Wed Apr 10 10:29:50 2013 -0700 +++ b/src/share/vm/gc_implementation/g1/g1MarkSweep.cpp Thu Apr 11 22:44:41 2013 -0700 @@ -206,6 +206,8 @@ G1CollectedHeap* g1h = G1CollectedHeap::heap(); gclog_or_tty->print_cr("]"); } + + gc_tracer()->report_object_count_after_gc(&GenMarkSweep::is_alive); } class G1PrepareCompactClosure: public HeapRegionClosure {
--- a/src/share/vm/gc_implementation/parNew/parCardTableModRefBS.cpp Wed Apr 10 10:29:50 2013 -0700 +++ b/src/share/vm/gc_implementation/parNew/parCardTableModRefBS.cpp Thu Apr 11 22:44:41 2013 -0700 @@ -373,6 +373,8 @@ " does not exceed used.end() = " PTR_FORMAT "," " yet last_chunk_index_to_check " INTPTR_FORMAT " exceeds last_chunk_index " INTPTR_FORMAT, + last_block, last_block + last_block_size, + used.end(), last_chunk_index_to_check, last_chunk_index)); assert(sp->used_region().end() > used.end(), err_msg("Expansion did not happen: "
--- a/src/share/vm/gc_implementation/parNew/parNewGeneration.cpp Wed Apr 10 10:29:50 2013 -0700 +++ b/src/share/vm/gc_implementation/parNew/parNewGeneration.cpp Thu Apr 11 22:44:41 2013 -0700 @@ -1098,6 +1098,7 @@ 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());
--- a/src/share/vm/gc_implementation/parallelScavenge/psMarkSweep.cpp Wed Apr 10 10:29:50 2013 -0700 +++ b/src/share/vm/gc_implementation/parallelScavenge/psMarkSweep.cpp Thu Apr 11 22:44:41 2013 -0700 @@ -566,6 +566,7 @@ SymbolTable::unlink(); assert(_marking_stack.is_empty(), "stack should be empty by now"); + _gc_tracer->report_object_count_after_gc(is_alive_closure()); }
--- a/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp Wed Apr 10 10:29:50 2013 -0700 +++ b/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp Thu Apr 11 22:44:41 2013 -0700 @@ -2443,6 +2443,7 @@ SymbolTable::unlink(); assert(cm->marking_stacks_empty(), "marking stacks should be empty"); + _gc_tracer.report_object_count_after_gc(is_alive_closure()); } // This should be moved to the shared markSweep code!
--- a/src/share/vm/gc_implementation/parallelScavenge/psScavenge.cpp Wed Apr 10 10:29:50 2013 -0700 +++ b/src/share/vm/gc_implementation/parallelScavenge/psScavenge.cpp Thu Apr 11 22:44:41 2013 -0700 @@ -668,6 +668,7 @@ 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();
--- a/src/share/vm/gc_implementation/shared/gcHeapSummary.hpp Wed Apr 10 10:29:50 2013 -0700 +++ b/src/share/vm/gc_implementation/shared/gcHeapSummary.hpp Thu Apr 11 22:44:41 2013 -0700 @@ -32,6 +32,8 @@ 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) { } @@ -47,6 +49,8 @@ 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) { } @@ -70,6 +74,8 @@ size_t _used; public: + GCHeapSummary() : + _heap(), _used(0) { } GCHeapSummary(VirtualSpaceSummary& heap_space, size_t used) : _heap(heap_space), _used(used) { } @@ -108,6 +114,8 @@ SpaceSummary _object_space; public: + PermGenSummary() : + _perm_space(), _object_space() { } PermGenSummary(const VirtualSpaceSummary& perm_space, const SpaceSummary& object_space) : _perm_space(perm_space), _object_space(object_space) { }
--- a/src/share/vm/gc_implementation/shared/gcTrace.cpp Wed Apr 10 10:29:50 2013 -0700 +++ b/src/share/vm/gc_implementation/shared/gcTrace.cpp Thu Apr 11 22:44:41 2013 -0700 @@ -27,9 +27,15 @@ #include "gc_implementation/shared/gcTimer.hpp" #include "gc_implementation/shared/gcTrace.hpp" #include "gc_implementation/shared/copyFailedInfo.hpp" +#include "memory/heapInspection.hpp" +#include "memory/iterator.hpp" #include "memory/referenceProcessorStats.hpp" #include "utilities/globalDefinitions.hpp" +#ifndef SERIALGC +#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?") @@ -85,6 +91,29 @@ send_reference_stats_event(REF_PHANTOM, rps.phantom_count()); } +class ObjectCountEventSenderClosure : public KlassInfoClosure { + GCTracer* _gc_tracer; + public: + ObjectCountEventSenderClosure(GCTracer* gc_tracer) : _gc_tracer(gc_tracer) {} + private: + void do_cinfo(KlassInfoEntry* entry) { + _gc_tracer->send_object_count_after_gc_event(entry->klass(), entry->count(), + entry->words() * BytesPerWord); + } +}; + +void GCTracer::report_object_count_after_gc(BoolObjectClosure *is_alive_cl) { + if (should_send_object_count_after_gc_event()) { + ResourceMark rm; + + KlassInfoTable cit(HeapInspection::start_of_perm_gen()); + if (!cit.allocation_failed()) { + ObjectCountEventSenderClosure event_sender(this); + HeapInspection::instance_inspection(&cit, &event_sender, false, is_alive_cl); + } + } +} + void GCTracer::report_gc_heap_summary(GCWhen::Type when, const GCHeapSummary& heap_summary, const PermGenSummary& perm_gen_summary) const { assert_set_gc_id(); @@ -94,9 +123,12 @@ 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) { @@ -105,6 +137,9 @@ 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(); @@ -126,6 +161,12 @@ _parallel_old_gc_info.report_dense_prefix(dense_prefix); } +void CMSTracer::report_concurrent_mode_failure() { + assert_set_gc_id(); + + send_concurrent_mode_failure_event(); +} + #ifndef SERIALGC void G1NewTracer::report_yc_type(G1YCType type) { assert_set_gc_id(); @@ -139,4 +180,10 @@ 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); +} #endif
--- a/src/share/vm/gc_implementation/shared/gcTrace.hpp Wed Apr 10 10:29:50 2013 -0700 +++ b/src/share/vm/gc_implementation/shared/gcTrace.hpp Thu Apr 11 22:44:41 2013 -0700 @@ -37,11 +37,13 @@ typedef uint GCId; +class EvacuationInfo; class GCHeapSummary; class PermGenSummary; class PSHeapSummary; class ReferenceProcessorStats; class TimePartitions; +class BoolObjectClosure; class SharedGCInfo VALUE_OBJ_CLASS_SPEC { static const jlong UNSET_TIMESTAMP = -1; @@ -109,6 +111,7 @@ #endif // SERIALGC class GCTracer : public ResourceObj { + friend class ObjectCountEventSenderClosure; protected: SharedGCInfo _shared_gc_info; @@ -117,6 +120,7 @@ void report_gc_end(jlong timestamp, TimePartitions* time_partitions); void report_gc_heap_summary(GCWhen::Type when, const GCHeapSummary& heap_summary, const PermGenSummary& perm_gen_summary) const; void report_gc_reference_stats(const ReferenceProcessorStats& rp) const; + void report_object_count_after_gc(BoolObjectClosure* object_filter); bool has_reported_gc_start() const; @@ -131,17 +135,22 @@ void send_perm_gen_summary_event(GCWhen::Type when, const PermGenSummary& perm_gen_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(klassOop klass, jlong count, julong total_size) const; + bool should_send_object_count_after_gc_event() const; }; class YoungGCTracer : public GCTracer { + static const uint UNSET_TENURING_THRESHOLD = (uint) -1; + + uint _tenuring_threshold; + protected: - YoungGCTracer(GCName name) : GCTracer(name) {} + 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); - - protected: - virtual void report_gc_end_impl(jlong timestamp, TimePartitions* time_partitions); + void report_tenuring_threshold(const uint tenuring_threshold); private: void send_young_gc_event() const; @@ -151,8 +160,6 @@ class OldGCTracer : public GCTracer { protected: OldGCTracer(GCName name) : GCTracer(name) {} - - protected: virtual void report_gc_end_impl(jlong timestamp, TimePartitions* time_partitions); private: @@ -202,15 +209,22 @@ void report_yc_type(G1YCType type); void report_gc_end_impl(jlong timestamp, TimePartitions* time_partitions); + void report_evacuation_info(EvacuationInfo* info); private: void send_g1_young_gc_event(); + void send_evacuation_info_event(EvacuationInfo* info); }; #endif class CMSTracer : public OldGCTracer { public: CMSTracer() : OldGCTracer(ConcurrentMarkSweep) {} + + void report_concurrent_mode_failure(); + + private: + void send_concurrent_mode_failure_event(); }; class G1OldTracer : public OldGCTracer {
--- a/src/share/vm/gc_implementation/shared/gcTraceSend.cpp Wed Apr 10 10:29:50 2013 -0700 +++ b/src/share/vm/gc_implementation/shared/gcTraceSend.cpp Thu Apr 11 22:44:41 2013 -0700 @@ -28,8 +28,10 @@ #include "gc_implementation/shared/gcTrace.hpp" #include "gc_implementation/shared/gcWhen.hpp" #include "gc_implementation/shared/copyFailedInfo.hpp" +#include "trace/traceBackend.hpp" #include "trace/tracing.hpp" #ifndef SERIALGC +#include "gc_implementation/g1/evacuationInfo.hpp" #include "gc_implementation/g1/g1YCTypes.hpp" #endif @@ -76,6 +78,7 @@ 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(); @@ -111,6 +114,33 @@ } } +void CMSTracer::send_concurrent_mode_failure_event() { + EventConcurrentModeFailure e; + if (e.should_commit()) { + e.set_gcId(_shared_gc_info.id()); + e.commit(); + } +} + +void GCTracer::send_object_count_after_gc_event(klassOop 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(); + } +} + +bool GCTracer::should_send_object_count_after_gc_event() const { +#if INCLUDE_TRACE + return Tracing::enabled(EventObjectCountAfterGC::eventId); +#else + return false; +#endif +} + #ifndef SERIALGC void G1NewTracer::send_g1_young_gc_event() { EventGCG1GarbageCollection e(UNTIMED); @@ -122,6 +152,22 @@ 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(); + } +} #endif static TraceStructVirtualSpace to_trace_struct(const VirtualSpaceSummary& summary) {
--- a/src/share/vm/gc_implementation/shared/vmGCOperations.cpp Wed Apr 10 10:29:50 2013 -0700 +++ b/src/share/vm/gc_implementation/shared/vmGCOperations.cpp Thu Apr 11 22:44:41 2013 -0700 @@ -144,27 +144,33 @@ return false; } -void VM_GC_HeapInspection::doit() { - HandleMark hm; +bool VM_GC_HeapInspection::collect() { CollectedHeap* ch = Universe::heap(); ch->ensure_parsability(false); // must happen, even if collection does // not happen (e.g. due to GC_locker) + + if (GC_locker::is_active()) { + return false; + } + ch->collect_as_vm_thread(GCCause::_heap_inspection); + return true; +} + +void VM_GC_HeapInspection::doit() { + HandleMark hm; 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::heap_inspection(_out, _need_prologue /* need_prologue */);
--- a/src/share/vm/gc_implementation/shared/vmGCOperations.hpp Wed Apr 10 10:29:50 2013 -0700 +++ b/src/share/vm/gc_implementation/shared/vmGCOperations.hpp Thu Apr 11 22:44:41 2013 -0700 @@ -150,6 +150,8 @@ virtual bool skip_operation() const; virtual bool doit_prologue(); virtual void doit(); + protected: + bool collect(); };
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/vm/gc_interface/allocTracer.cpp Thu Apr 11 22:44:41 2013 -0700 @@ -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(); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/vm/gc_interface/allocTracer.hpp Thu Apr 11 22:44:41 2013 -0700 @@ -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 */
--- a/src/share/vm/gc_interface/collectedHeap.cpp Wed Apr 10 10:29:50 2013 -0700 +++ b/src/share/vm/gc_interface/collectedHeap.cpp Thu Apr 11 22:44:41 2013 -0700 @@ -29,6 +29,7 @@ #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 "oops/oop.inline.hpp" @@ -218,7 +219,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. @@ -242,6 +243,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); @@ -528,7 +532,7 @@ obj = common_permanent_mem_allocate_init(size, CHECK_NULL); } else { 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() ||
--- a/src/share/vm/gc_interface/collectedHeap.hpp Wed Apr 10 10:29:50 2013 -0700 +++ b/src/share/vm/gc_interface/collectedHeap.hpp Thu Apr 11 22:44:41 2013 -0700 @@ -135,16 +135,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); // Same as common_mem version, except memory is allocated in the permanent area // If there is no permanent area, revert to common_mem_allocate_noinit
--- a/src/share/vm/gc_interface/collectedHeap.inline.hpp Wed Apr 10 10:29:50 2013 -0700 +++ b/src/share/vm/gc_interface/collectedHeap.inline.hpp Thu Apr 11 22:44:41 2013 -0700 @@ -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" @@ -120,7 +121,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. @@ -133,7 +134,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"); @@ -149,6 +150,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; } @@ -178,8 +182,8 @@ } } -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; } @@ -227,7 +231,7 @@ 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); @@ -235,7 +239,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) { @@ -250,7 +254,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; @@ -263,7 +267,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; @@ -276,7 +280,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
--- a/src/share/vm/memory/cardTableModRefBS.cpp Wed Apr 10 10:29:50 2013 -0700 +++ b/src/share/vm/memory/cardTableModRefBS.cpp Thu Apr 11 22:44:41 2013 -0700 @@ -693,7 +693,7 @@ if (failed) { if (!failures) { tty->cr(); - tty->print_cr("== CT verification failed: ["PTR_FORMAT","PTR_FORMAT"]"); + tty->print_cr("== CT verification failed: ["PTR_FORMAT","PTR_FORMAT"]", start, end); tty->print_cr("== %sexpecting value: %d", (val_equals) ? "" : "not ", val); failures = true;
--- a/src/share/vm/memory/cardTableRS.cpp Wed Apr 10 10:29:50 2013 -0700 +++ b/src/share/vm/memory/cardTableRS.cpp Thu Apr 11 22:44:41 2013 -0700 @@ -369,7 +369,7 @@ assert(jp >= _begin && jp < _end, err_msg("Error: jp " PTR_FORMAT " should be within " "[_begin, _end) = [" PTR_FORMAT "," PTR_FORMAT ")", - _begin, _end)); + jp, _begin, _end)); oop obj = oopDesc::load_decode_heap_oop(p); guarantee(obj == NULL || (HeapWord*)obj >= _boundary, err_msg("pointer " PTR_FORMAT " at " PTR_FORMAT " on "
--- a/src/share/vm/memory/defNewGeneration.cpp Wed Apr 10 10:29:50 2013 -0700 +++ b/src/share/vm/memory/defNewGeneration.cpp Thu Apr 11 22:44:41 2013 -0700 @@ -680,6 +680,7 @@ 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());
--- a/src/share/vm/memory/genMarkSweep.cpp Wed Apr 10 10:29:50 2013 -0700 +++ b/src/share/vm/memory/genMarkSweep.cpp Thu Apr 11 22:44:41 2013 -0700 @@ -318,6 +318,8 @@ SymbolTable::unlink(); assert(_marking_stack.is_empty(), "stack should be empty by now"); + + gc_tracer()->report_object_count_after_gc(&is_alive); }
--- a/src/share/vm/memory/heapInspection.cpp Wed Apr 10 10:29:50 2013 -0700 +++ b/src/share/vm/memory/heapInspection.cpp Thu Apr 11 22:44:41 2013 -0700 @@ -87,7 +87,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); @@ -113,12 +113,12 @@ } } -KlassInfoTable::KlassInfoTable(int size, HeapWord* ref) { +KlassInfoTable::KlassInfoTable(HeapWord* ref) { _size = 0; _ref = ref; - _buckets = NEW_C_HEAP_ARRAY(KlassInfoBucket, size, mtInternal); + _buckets = (KlassInfoBucket *) os::malloc(sizeof(KlassInfoBucket) * _num_buckets, mtInternal); if (_buckets != NULL) { - _size = size; + _size = _num_buckets; for (int index = 0; index < _size; index++) { _buckets[index].initialize(); } @@ -177,9 +177,9 @@ return (*e1)->compare(*e1,*e2); } -KlassInfoHisto::KlassInfoHisto(const char* title, int estimatedCount) : +KlassInfoHisto::KlassInfoHisto(const char* title) : _title(title) { - _elements = new (ResourceObj::C_HEAP, mtInternal) GrowableArray<KlassInfoEntry*>(estimatedCount,true); + _elements = new (ResourceObj::C_HEAP, mtInternal) GrowableArray<KlassInfoEntry*>(_histo_initial_size, true); } KlassInfoHisto::~KlassInfoHisto() { @@ -228,82 +228,104 @@ 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); + } }; +HeapWord* HeapInspection::start_of_perm_gen() { + if (is_shared_heap()) { + SharedHeap* sh = SharedHeap::heap(); + return sh->perm_gen()->used_region().start(); + } +#ifndef SERIALGC + ParallelScavengeHeap* psh = (ParallelScavengeHeap*)Universe::heap(); + return psh->perm_gen()->object_space()->used_region().start(); +#else + ShouldNotReachHere(); + return NULL; +#endif // SERIALGC +} + +bool HeapInspection::is_shared_heap() { + CollectedHeap* heap = Universe::heap(); + return heap->kind() == CollectedHeap::G1CollectedHeap || + heap->kind() == CollectedHeap::GenCollectedHeap; +} + +void HeapInspection::prologue() { + if (is_shared_heap()) { + SharedHeap* sh = SharedHeap::heap(); + sh->gc_prologue(false /* !full */); // get any necessary locks, etc. + } +} + +void HeapInspection::epilogue() { + if (is_shared_heap()) { + SharedHeap* sh = SharedHeap::heap(); + sh->gc_epilogue(false /* !full */); // release all acquired locks, etc. + } +} + +size_t HeapInspection::instance_inspection(KlassInfoTable* cit, + KlassInfoClosure* cl, + bool need_prologue, + BoolObjectClosure* filter) { + ResourceMark rm; + + if (need_prologue) { + prologue(); + } + + RecordInstanceClosure ric(cit, filter); + Universe::heap()->object_iterate(&ric); + cit->iterate(cl); + + // need to run epilogue if we run prologue + if (need_prologue) { + epilogue(); + } + + return ric.missed_count(); +} + void HeapInspection::heap_inspection(outputStream* st, bool need_prologue) { ResourceMark rm; - HeapWord* ref; - CollectedHeap* heap = Universe::heap(); - bool is_shared_heap = false; - switch (heap->kind()) { - case CollectedHeap::G1CollectedHeap: - case CollectedHeap::GenCollectedHeap: { - is_shared_heap = true; - SharedHeap* sh = (SharedHeap*)heap; - if (need_prologue) { - sh->gc_prologue(false /* !full */); // get any necessary locks, etc. - } - ref = sh->perm_gen()->used_region().start(); - break; - } -#ifndef SERIALGC - case CollectedHeap::ParallelScavengeHeap: { - ParallelScavengeHeap* psh = (ParallelScavengeHeap*)heap; - ref = psh->perm_gen()->object_space()->used_region().start(); - break; - } -#endif // SERIALGC - default: - ShouldNotReachHere(); // Unexpected heap kind for this op - } - // Collect klass instance info - KlassInfoTable cit(KlassInfoTable::cit_size, ref); + KlassInfoTable cit(start_of_perm_gen()); if (!cit.allocation_failed()) { - // Iterate over objects in the heap - RecordInstanceClosure ric(&cit); - // If this operation encounters a bad object when using CMS, - // consider using safe_object_iterate() which avoids perm gen - // objects that may contain bad references. - Universe::heap()->object_iterate(&ric); + KlassInfoHisto histo("\n" + " num #instances #bytes class name\n" + "----------------------------------------------"); + HistoClosure hc(&histo); - // 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 = instance_inspection(&cit, &hc, need_prologue); 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 - KlassInfoHisto histo("\n" - " num #instances #bytes class name\n" - "----------------------------------------------", - KlassInfoHisto::histo_initial_size); - HistoClosure hc(&histo); - cit.iterate(&hc); histo.sort(); histo.print_on(st); } 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 {
--- a/src/share/vm/memory/heapInspection.hpp Wed Apr 10 10:29:50 2013 -0700 +++ b/src/share/vm/memory/heapInspection.hpp Thu Apr 11 22:44:41 2013 -0700 @@ -85,6 +85,7 @@ class KlassInfoTable: public StackObj { private: int _size; + static const int _num_buckets = 20011; // An aligned reference address (typically the least // address in the perm gen) used for hashing klass @@ -96,11 +97,7 @@ KlassInfoEntry* lookup(const klassOop k); public: - // Table size - enum { - cit_size = 20011 - }; - KlassInfoTable(int size, HeapWord* ref); + KlassInfoTable(HeapWord* ref); ~KlassInfoTable(); bool record_instance(const oop obj); void iterate(KlassInfoClosure* cic); @@ -115,12 +112,9 @@ const char* title() const { return _title; } static int sort_helper(KlassInfoEntry** e1, KlassInfoEntry** e2); void print_elements(outputStream* st) const; + static const int _histo_initial_size = 1000; public: - enum { - histo_initial_size = 1000 - }; - KlassInfoHisto(const char* title, - int estimatedCount); + KlassInfoHisto(const char* title); ~KlassInfoHisto(); void add(KlassInfoEntry* cie); void print_on(outputStream* st) const; @@ -131,7 +125,16 @@ class HeapInspection : public AllStatic { public: static void heap_inspection(outputStream* st, bool need_prologue); + static size_t instance_inspection(KlassInfoTable* cit, + KlassInfoClosure* cl, + bool need_prologue, + BoolObjectClosure* filter = NULL); + static HeapWord* start_of_perm_gen(); static void find_instances_at_safepoint(klassOop k, GrowableArray<oop>* result); + private: + static bool is_shared_heap(); + static void prologue(); + static void epilogue(); }; #endif // SHARE_VM_MEMORY_HEAPINSPECTION_HPP
--- a/src/share/vm/opto/compile.cpp Wed Apr 10 10:29:50 2013 -0700 +++ b/src/share/vm/opto/compile.cpp Thu Apr 11 22:44:41 2013 -0700 @@ -2892,6 +2892,13 @@ } } break; + case Op_MemBarStoreStore: + // Break the link with AllocateNode: it is no longer useful and + // confuses register allocation. + if (n->req() > MemBarNode::Precedent) { + n->set_req(MemBarNode::Precedent, top()); + } + break; default: assert( !n->is_Call(), "" ); assert( !n->is_Mem(), "" );
--- a/src/share/vm/opto/graphKit.cpp Wed Apr 10 10:29:50 2013 -0700 +++ b/src/share/vm/opto/graphKit.cpp Thu Apr 11 22:44:41 2013 -0700 @@ -3445,7 +3445,6 @@ void GraphKit::final_sync(IdealKit& ideal) { // Final sync IdealKit and graphKit. - __ drain_delay_transform(); sync_kit(ideal); }
--- a/src/share/vm/opto/idealKit.cpp Wed Apr 10 10:29:50 2013 -0700 +++ b/src/share/vm/opto/idealKit.cpp Thu Apr 11 22:44:41 2013 -0700 @@ -48,9 +48,9 @@ _cvstate = NULL; // We can go memory state free or else we need the entire memory state assert(_initial_memory == NULL || _initial_memory->Opcode() == Op_MergeMem, "memory must be pre-split"); + assert(!_gvn.is_IterGVN(), "IdealKit can't be used during Optimize phase"); int init_size = 5; _pending_cvstates = new (C->node_arena()) GrowableArray<Node*>(C->node_arena(), init_size, 0, 0); - _delay_transform = new (C->node_arena()) GrowableArray<Node*>(C->node_arena(), init_size, 0, 0); DEBUG_ONLY(_state = new (C->node_arena()) GrowableArray<int>(C->node_arena(), init_size, 0, 0)); if (!has_declarations) { declarations_done(); @@ -296,19 +296,16 @@ return delay_transform(n); } else { n = gvn().transform(n); - if (!gvn().is_IterGVN()) { - C->record_for_igvn(n); - } + C->record_for_igvn(n); return n; } } //-----------------------------delay_transform----------------------------------- Node* IdealKit::delay_transform(Node* n) { - if (!gvn().is_IterGVN() || !gvn().is_IterGVN()->delay_transform()) { - gvn().set_type(n, n->bottom_type()); - } - _delay_transform->push(n); + // Delay transform until IterativeGVN + gvn().set_type(n, n->bottom_type()); + C->record_for_igvn(n); return n; } @@ -332,17 +329,6 @@ for (uint i = 0; i < m->req(); i++) m->set_req(i, NULL); } -//-----------------------------drain_delay_transform---------------------------- -void IdealKit::drain_delay_transform() { - while (_delay_transform->length() > 0) { - Node* n = _delay_transform->pop(); - gvn().transform(n); - if (!gvn().is_IterGVN()) { - C->record_for_igvn(n); - } - } -} - //-----------------------------IdealVariable---------------------------- IdealVariable::IdealVariable(IdealKit &k) { k.declare(this); @@ -351,9 +337,7 @@ Node* IdealKit::memory(uint alias_idx) { MergeMemNode* mem = merged_memory(); Node* p = mem->memory_at(alias_idx); - if (!gvn().is_IterGVN() || !gvn().is_IterGVN()->delay_transform()) { - _gvn.set_type(p, Type::MEMORY); // must be mapped - } + _gvn.set_type(p, Type::MEMORY); // must be mapped return p; }
--- a/src/share/vm/opto/idealKit.hpp Wed Apr 10 10:29:50 2013 -0700 +++ b/src/share/vm/opto/idealKit.hpp Thu Apr 11 22:44:41 2013 -0700 @@ -102,7 +102,6 @@ Compile * const C; PhaseGVN &_gvn; GrowableArray<Node*>* _pending_cvstates; // stack of cvstates - GrowableArray<Node*>* _delay_transform; // delay invoking gvn.transform until drain Node* _cvstate; // current cvstate (control, memory and variables) uint _var_ct; // number of variables bool _delay_all_transforms; // flag forcing all transforms to be delayed @@ -121,7 +120,7 @@ void clear(Node* m); // clear a cvstate void stop() { clear(_cvstate); } // clear current cvstate Node* delay_transform(Node* n); - Node* transform(Node* n); // gvn.transform or push node on delay list + Node* transform(Node* n); // gvn.transform or skip it Node* promote_to_phi(Node* n, Node* reg);// Promote "n" to a phi on region "reg" bool was_promoted_to_phi(Node* n, Node* reg) { return (n->is_Phi() && n->in(0) == reg); @@ -146,7 +145,6 @@ IdealKit(GraphKit* gkit, bool delay_all_transforms = false, bool has_declarations = false); ~IdealKit() { stop(); - drain_delay_transform(); } void sync_kit(GraphKit* gkit); @@ -173,7 +171,6 @@ void bind(Node* lab); void goto_(Node* lab, bool bind = false); void declarations_done(); - void drain_delay_transform(); Node* IfTrue(IfNode* iff) { return transform(new (C) IfTrueNode(iff)); } Node* IfFalse(IfNode* iff) { return transform(new (C) IfFalseNode(iff)); } @@ -198,7 +195,11 @@ Node* thread() { return gvn().transform(new (C) ThreadLocalNode()); } // Pointers - Node* AddP(Node *base, Node *ptr, Node *off) { return transform(new (C) AddPNode(base, ptr, off)); } + + // Raw address should be transformed regardless 'delay_transform' flag + // to produce canonical form CastX2P(offset). + Node* AddP(Node *base, Node *ptr, Node *off) { return _gvn.transform(new (C) AddPNode(base, ptr, off)); } + Node* CmpP(Node* l, Node* r) { return transform(new (C) CmpPNode(l, r)); } #ifdef _LP64 Node* XorX(Node* l, Node* r) { return transform(new (C) XorLNode(l, r)); } @@ -208,8 +209,6 @@ Node* URShiftX(Node* l, Node* r) { return transform(new (C) URShiftXNode(l, r)); } Node* ConX(jint k) { return (Node*)gvn().MakeConX(k); } Node* CastPX(Node* ctl, Node* p) { return transform(new (C) CastP2XNode(ctl, p)); } - // Add a fixed offset to a pointer - Node* basic_plus_adr(Node* base, Node* ptr, intptr_t offset); // Memory operations
--- a/src/share/vm/opto/loopnode.cpp Wed Apr 10 10:29:50 2013 -0700 +++ b/src/share/vm/opto/loopnode.cpp Thu Apr 11 22:44:41 2013 -0700 @@ -2251,6 +2251,11 @@ return; } + // clear out the dead code after build_loop_late + while (_deadlist.size()) { + _igvn.remove_globally_dead_node(_deadlist.pop()); + } + if (stop_early) { assert(do_expensive_nodes, "why are we here?"); if (process_expensive_nodes()) { @@ -2260,9 +2265,7 @@ // nodes again. C->set_major_progress(); } - _igvn.optimize(); - return; } @@ -2273,11 +2276,6 @@ eliminate_useless_predicates(); } - // clear out the dead code - while(_deadlist.size()) { - _igvn.remove_globally_dead_node(_deadlist.pop()); - } - #ifndef PRODUCT C->verify_graph_edges(); if (_verify_me) { // Nested verify pass?
--- a/src/share/vm/opto/macro.cpp Wed Apr 10 10:29:50 2013 -0700 +++ b/src/share/vm/opto/macro.cpp Thu Apr 11 22:44:41 2013 -0700 @@ -1094,12 +1094,6 @@ Node* klass_node = alloc->in(AllocateNode::KlassNode); Node* initial_slow_test = alloc->in(AllocateNode::InitialTest); - Node* storestore = alloc->storestore(); - if (storestore != NULL) { - // Break this link that is no longer useful and confuses register allocation - storestore->set_req(MemBarNode::Precedent, top()); - } - assert(ctrl != NULL, "must have control"); // We need a Region and corresponding Phi's to merge the slow-path and fast-path results. // they will not be used if "always_slow" is set @@ -1317,7 +1311,7 @@ // No InitializeNode or no stores captured by zeroing // elimination. Simply add the MemBarStoreStore after object // initialization. - MemBarNode* mb = MemBarNode::make(C, Op_MemBarStoreStore, Compile::AliasIdxBot, fast_oop_rawmem); + MemBarNode* mb = MemBarNode::make(C, Op_MemBarStoreStore, Compile::AliasIdxBot); transform_later(mb); mb->init_req(TypeFunc::Memory, fast_oop_rawmem);
--- a/src/share/vm/opto/phaseX.cpp Wed Apr 10 10:29:50 2013 -0700 +++ b/src/share/vm/opto/phaseX.cpp Thu Apr 11 22:44:41 2013 -0700 @@ -1166,31 +1166,30 @@ if (progress_state == PROCESS_INPUTS) { // After following inputs, continue to outputs _stack.set_index(PROCESS_OUTPUTS); - // Remove from iterative worklist - _worklist.remove(dead); if (!dead->is_Con()) { // Don't kill cons but uses bool recurse = false; // Remove from hash table _table.hash_delete( dead ); // Smash all inputs to 'dead', isolating him completely - for( uint i = 0; i < dead->req(); i++ ) { + for (uint i = 0; i < dead->req(); i++) { Node *in = dead->in(i); - if( in ) { // Points to something? - dead->set_req(i,NULL); // Kill the edge - if (in->outcnt() == 0 && in != C->top()) {// Made input go dead? + if (in != NULL && in != C->top()) { // Points to something? + int nrep = dead->replace_edge(in, NULL); // Kill edges + assert((nrep > 0), "sanity"); + if (in->outcnt() == 0) { // Made input go dead? _stack.push(in, PROCESS_INPUTS); // Recursively remove recurse = true; } else if (in->outcnt() == 1 && in->has_special_unique_user()) { _worklist.push(in->unique_out()); } else if (in->outcnt() <= 2 && dead->is_Phi()) { - if( in->Opcode() == Op_Region ) + if (in->Opcode() == Op_Region) { _worklist.push(in); - else if( in->is_Store() ) { + } else if (in->is_Store()) { DUIterator_Fast imax, i = in->fast_outs(imax); _worklist.push(in->fast_out(i)); i++; - if(in->outcnt() == 2) { + if (in->outcnt() == 2) { _worklist.push(in->fast_out(i)); i++; } @@ -1209,38 +1208,42 @@ } } } - } - } - C->record_dead_node(dead->_idx); - if (dead->is_macro()) { - C->remove_macro_node(dead); - } - if (dead->is_expensive()) { - C->remove_expensive_node(dead); - } - + } // if (in != NULL && in != C->top()) + } // for (uint i = 0; i < dead->req(); i++) if (recurse) { continue; } - } - // Constant node that has no out-edges and has only one in-edge from - // root is usually dead. However, sometimes reshaping walk makes - // it reachable by adding use edges. So, we will NOT count Con nodes - // as dead to be conservative about the dead node count at any - // given time. - } + } // if (!dead->is_Con()) + } // if (progress_state == PROCESS_INPUTS) // Aggressively kill globally dead uses // (Rather than pushing all the outs at once, we push one at a time, // plus the parent to resume later, because of the indefinite number // of edge deletions per loop trip.) if (dead->outcnt() > 0) { - // Recursively remove + // Recursively remove output edges _stack.push(dead->raw_out(0), PROCESS_INPUTS); } else { + // Finished disconnecting all input and output edges. _stack.pop(); + // Remove dead node from iterative worklist + _worklist.remove(dead); + // Constant node that has no out-edges and has only one in-edge from + // root is usually dead. However, sometimes reshaping walk makes + // it reachable by adding use edges. So, we will NOT count Con nodes + // as dead to be conservative about the dead node count at any + // given time. + if (!dead->is_Con()) { + C->record_dead_node(dead->_idx); + } + if (dead->is_macro()) { + C->remove_macro_node(dead); + } + if (dead->is_expensive()) { + C->remove_expensive_node(dead); + } } - } + } // while (_stack.is_nonempty()) } //------------------------------subsume_node-----------------------------------
--- a/src/share/vm/prims/jvmtiEnter.xsl Wed Apr 10 10:29:50 2013 -0700 +++ b/src/share/vm/prims/jvmtiEnter.xsl Thu Apr 11 22:44:41 2013 -0700 @@ -770,7 +770,7 @@ </xsl:text> <xsl:apply-templates select=".." mode="traceError"> <xsl:with-param name="err">JVMTI_ERROR_INVALID_THREAD</xsl:with-param> - <xsl:with-param name="comment"> - jthread resolved to NULL - jthread = %0x%x</xsl:with-param> + <xsl:with-param name="comment"> - jthread resolved to NULL - jthread = 0x%x</xsl:with-param> <xsl:with-param name="extraValue">, <xsl:value-of select="$name"/></xsl:with-param> </xsl:apply-templates> <xsl:text> @@ -779,7 +779,7 @@ </xsl:text> <xsl:apply-templates select=".." mode="traceError"> <xsl:with-param name="err">JVMTI_ERROR_INVALID_THREAD</xsl:with-param> - <xsl:with-param name="comment"> - oop is not a thread - jthread = %0x%x</xsl:with-param> + <xsl:with-param name="comment"> - oop is not a thread - jthread = 0x%x</xsl:with-param> <xsl:with-param name="extraValue">, <xsl:value-of select="$name"/></xsl:with-param> </xsl:apply-templates> <xsl:text> @@ -791,7 +791,7 @@ <xsl:with-param name="err"> <xsl:text>JVMTI_ERROR_THREAD_NOT_ALIVE</xsl:text> </xsl:with-param> - <xsl:with-param name="comment"> - not a Java thread - jthread = %0x%x</xsl:with-param> + <xsl:with-param name="comment"> - not a Java thread - jthread = 0x%x</xsl:with-param> <xsl:with-param name="extraValue">, <xsl:value-of select="$name"/></xsl:with-param> </xsl:apply-templates> <xsl:text> @@ -835,7 +835,7 @@ </xsl:text> <xsl:apply-templates select=".." mode="traceError"> <xsl:with-param name="err">JVMTI_ERROR_ILLEGAL_ARGUMENT</xsl:with-param> - <xsl:with-param name="comment"> - negative depth - jthread = %0x%x</xsl:with-param> + <xsl:with-param name="comment"> - negative depth - jthread = 0x%x</xsl:with-param> <xsl:with-param name="extraValue">, <xsl:value-of select="$name"/></xsl:with-param> </xsl:apply-templates> <xsl:text>
--- a/src/share/vm/runtime/arguments.cpp Wed Apr 10 10:29:50 2013 -0700 +++ b/src/share/vm/runtime/arguments.cpp Thu Apr 11 22:44:41 2013 -0700 @@ -2099,19 +2099,6 @@ FREE_C_HEAP_ARRAY(char, altclasses_path, mtInternal); } - if (WhiteBoxAPI) { - // Append wb.jar to bootclasspath if enabled - const char* wb_jar = "wb.jar"; - size_t wb_path_len = strlen(get_meta_index_dir()) + 1 + - strlen(wb_jar); - char* wb_path = NEW_C_HEAP_ARRAY(char, wb_path_len, mtInternal); - strcpy(wb_path, get_meta_index_dir()); - strcat(wb_path, wb_jar); - scp.add_suffix(wb_path); - scp_assembly_required = true; - FREE_C_HEAP_ARRAY(char, wb_path, mtInternal); - } - // Parse _JAVA_OPTIONS environment variable (if present) (mimics classic VM) result = parse_java_options_environment_variable(&scp, &scp_assembly_required); if (result != JNI_OK) {
--- a/src/share/vm/runtime/thread.hpp Wed Apr 10 10:29:50 2013 -0700 +++ b/src/share/vm/runtime/thread.hpp Thu Apr 11 22:44:41 2013 -0700 @@ -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 @@ -1274,6 +1274,7 @@ void enable_stack_red_zone(); void disable_stack_red_zone(); + inline bool stack_guard_zone_unused(); inline bool stack_yellow_zone_disabled(); inline bool stack_yellow_zone_enabled(); @@ -1741,6 +1742,10 @@ return (CompilerThread*)this; } +inline bool JavaThread::stack_guard_zone_unused() { + return _stack_guard_state == stack_guard_unused; +} + inline bool JavaThread::stack_yellow_zone_disabled() { return _stack_guard_state == stack_guard_yellow_disabled; }
--- a/src/share/vm/runtime/vm_operations.hpp Wed Apr 10 10:29:50 2013 -0700 +++ b/src/share/vm/runtime/vm_operations.hpp Thu Apr 11 22:44:41 2013 -0700 @@ -95,6 +95,7 @@ template(ReportJavaOutOfMemory) \ template(JFRCheckpoint) \ template(Exit) \ + template(LinuxDllLoad) \ class VM_Operation: public CHeapObj<mtInternal> { public:
--- a/src/share/vm/services/memReporter.cpp Wed Apr 10 10:29:50 2013 -0700 +++ b/src/share/vm/services/memReporter.cpp Thu Apr 11 22:44:41 2013 -0700 @@ -419,7 +419,7 @@ _output->print_cr("[" PTR_FORMAT "] %s+0x%x", pc, buf, offset); _output->print("%28s", " "); } else { - _output->print("[" PTR_FORMAT "]%18s", " "); + _output->print("[" PTR_FORMAT "]%18s", pc, " "); } _output->print_cr("(mmap: reserved=%d%s, committed=%d%s)", @@ -596,7 +596,7 @@ _output->print_cr("[" PTR_FORMAT "] %s+0x%x", pc, buf, offset); _output->print("%28s", " "); } else { - _output->print("[" PTR_FORMAT "]%18s", " "); + _output->print("[" PTR_FORMAT "]%18s", pc, " "); } }
--- a/src/share/vm/trace/trace.xml Wed Apr 10 10:29:50 2013 -0700 +++ b/src/share/vm/trace/trace.xml Thu Apr 11 22:44:41 2013 -0700 @@ -168,6 +168,7 @@ <event id="GCYoungGarbageCollection" path="vm/gc/collector/young_garbage_collection" label="Young Garbage Collection" description="Extra information specific to Young Garbage Collections"> <value type="ULONG" field="gcId" label="GC ID" relation="GC_ID" /> + <value type="UINT" field="tenuringThreshold" label="Tenuring Threshold" /> </event> <event id="GCOldGarbageCollection" path="vm/gc/collector/old_garbage_collection" label="Old Garbage Collection" @@ -181,6 +182,18 @@ <value type="G1YCTYPE" field="type" label="Type" /> </event> + <event id="EvacuationInfo" path="vm/gc/detailed/evacuation_info" label="Evacuation Info" is_instant="true"> + <value type="ULONG" field="gcId" label="GC ID" relation="GC_ID"/> + <value type="UINT" field="cSetRegions" label="Collection Set Regions"/> + <value type="BYTES64" field="cSetUsedBefore" label="Collection Set Before" description="Memory usage before GC in the collection set regions"/> + <value type="BYTES64" field="cSetUsedAfter" label="Collection Set After" description="Memory usage after GC in the collection set regions"/> + <value type="UINT" field="allocationRegions" label="Allocation Regions" description="Regions chosen as allocation regions during evacuation (includes survivors and old space regions)"/> + <value type="BYTES64" field="allocRegionsUsedBefore" label="Alloc Regions Before" description="Memory usage before GC in allocation regions"/> + <value type="BYTES64" field="allocRegionsUsedAfter" label="Alloc Regions After" description="Memory usage after GC in allocation regions"/> + <value type="BYTES64" field="bytesCopied" label="BytesCopied"/> + <value type="UINT" field="regionsFreed" label="Regions Freed"/> + </event> + <event id="GCReferenceStatistics" path="vm/gc/reference/statistics" label="GC Reference Processing" is_instant="true" description="Total count of processed references during GC"> @@ -197,12 +210,24 @@ <value type="OSTHREAD" field="thread" label="Running thread"/> </struct> + <event id="ObjectCountAfterGC" path="vm/gc/detailed/object_count_after_gc" is_instant="true" label="Object Count After GC"> + <value type="ULONG" field="gcId" label="GC ID" relation="GC_ID" /> + <value type="CLASS" field="class" label="Class" /> + <value type="LONG" field="count" label="Count" /> + <value type="BYTES64" field="totalSize" label="Total Size" /> + </event> + <event id="PromotionFailed" path="vm/gc/detailed/promotion_failed" label="Promotion Failed" is_instant="true" description="Promotion of an object failed"> <value type="ULONG" field="gcId" label="GC ID" relation="GC_ID"/> <structvalue type="CopyFailed" field="data" label="data"/> </event> + <event id="ConcurrentModeFailure" path="vm/gc/detailed/concurrent_mode_failure" label="Concurrent Mode Failure" + is_instant="true" description="Concurrent Mode failed"> + <value type="ULONG" field="gcId" label="GC ID" relation="GC_ID"/> + </event> + <event id="GCPhasePause" path="vm/gc/phases/pause" label="GC Phase Pause"> <value type="ULONG" field="gcId" label="GC ID" relation="GC_ID"/> <value type="UTF8" field="name" label="Name" /> @@ -290,7 +315,20 @@ <value type="BOOLEAN" field="blocking" label="Caller Blocked" description="If the calling thread was blocked until the operation was complete."/> <value type="OSTHREAD" field="caller" label="Caller" transition="TO" description="Thread requesting operation. If non-blocking, will be set to 0 indicating thread is unknown."/> </event> + + <!-- Allocation events --> + <event id="AllocObjectInNewTLAB" path="java/object_alloc_in_new_TLAB" label="Allocation in new TLAB" + description="Allocation in new Thread Local Allocation Buffer" has_thread="true" has_stacktrace="true" is_instant="true"> + <value type="CLASS" field="class" label="Class" description="Class of allocated object"/> + <value type="BYTES64" field="allocationSize" label="Allocation Size"/> + <value type="BYTES64" field="tlabSize" label="TLAB Size"/> + </event> + <event id="AllocObjectOutsideTLAB" path="java/object_alloc_outside_TLAB" label="Allocation outside TLAB" + description="Allocation outside Thread Local Allocation Buffers" has_thread="true" has_stacktrace="true" is_instant="true"> + <value type="CLASS" field="class" label="Class" description="Class of allocated object"/> + <value type="BYTES64" field="allocationSize" label="Allocation Size"/> + </event> </events> <xi:include href="../../../closed/share/vm/trace/traceeventtypes.xml" xmlns:xi="http://www.w3.org/2001/XInclude">
--- a/src/share/vm/utilities/elfFile.cpp Wed Apr 10 10:29:50 2013 -0700 +++ b/src/share/vm/utilities/elfFile.cpp Thu Apr 11 22:44:41 2013 -0700 @@ -197,4 +197,28 @@ return NULL; } +#ifdef LINUX +bool ElfFile::specifies_noexecstack() { + Elf_Phdr phdr; + if (!m_file) return true; + + if (!fseek(m_file, m_elfHdr.e_phoff, SEEK_SET)) { + for (int index = 0; index < m_elfHdr.e_phnum; index ++) { + if (fread((void*)&phdr, sizeof(Elf_Phdr), 1, m_file) != 1) { + m_status = NullDecoder::file_invalid; + return false; + } + if (phdr.p_type == PT_GNU_STACK) { + if (phdr.p_flags == (PF_R | PF_W)) { + return true; + } else { + return false; + } + } + } + } + return false; +} +#endif + #endif // _WINDOWS
--- a/src/share/vm/utilities/elfFile.hpp Wed Apr 10 10:29:50 2013 -0700 +++ b/src/share/vm/utilities/elfFile.hpp Thu Apr 11 22:44:41 2013 -0700 @@ -43,6 +43,7 @@ typedef Elf64_Ehdr Elf_Ehdr; typedef Elf64_Shdr Elf_Shdr; +typedef Elf64_Phdr Elf_Phdr; typedef Elf64_Sym Elf_Sym; #if !defined(_ALLBSD_SOURCE) || defined(__APPLE__) @@ -59,6 +60,7 @@ typedef Elf32_Ehdr Elf_Ehdr; typedef Elf32_Shdr Elf_Shdr; +typedef Elf32_Phdr Elf_Phdr; typedef Elf32_Sym Elf_Sym; #if !defined(_ALLBSD_SOURCE) || defined(__APPLE__) @@ -123,6 +125,14 @@ ElfFile* next() const { return m_next; } void set_next(ElfFile* file) { m_next = file; } + public: + // Returns true if the elf file is marked NOT to require an executable stack, + // or if the file could not be opened. + // Returns false if the elf file requires an executable stack, the stack flag + // is not set at all, or if the file can not be read. + // On systems other than linux it always returns false. + bool specifies_noexecstack() NOT_LINUX({ return false; }); + protected: ElfFile* m_next;
--- a/src/share/vm/utilities/numberSeq.cpp Wed Apr 10 10:29:50 2013 -0700 +++ b/src/share/vm/utilities/numberSeq.cpp Thu Apr 11 22:44:41 2013 -0700 @@ -245,7 +245,7 @@ void NumberSeq::dump_on(outputStream* s) { AbsSeq::dump_on(s); - s->print_cr("\t\t _last = %7.3f, _maximum = %7.3f"); + s->print_cr("\t\t _last = %7.3f, _maximum = %7.3f", _last, _maximum); } void TruncatedSeq::dump_on(outputStream* s) {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/gc/heap_inspection/TestPrintClassHistogram.java Thu Apr 11 22:44:41 2013 -0700 @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test TestPrintClassHistogram + * @bug 8010294 + * @summary Checks that a class histogram can be printed both before and after + * a GC + * @library /testlibrary + * @run main/othervm TestPrintClassHistogram launch BeforeGC + * @run main/othervm TestPrintClassHistogram launch AfterGC + * @run main/othervm TestPrintClassHistogram launch BeforeGC AfterGC + */ + +import java.util.List; +import java.util.ArrayList; +import java.util.Arrays; + +import com.oracle.java.testlibrary.OutputAnalyzer; +import com.oracle.java.testlibrary.ProcessTools; + +/* This test uses a "trick" to be able to analyze the output of the test: + * + * The test starts a java process that runs the same code, but the first + * argument is different ("run" instead of "launch"). The change of flags + * will run the test code instead of launching the test again. + */ +public class TestPrintClassHistogram { + public static void main(String[] args) throws Exception { + if (shouldLaunchTest(args)) { + launchTest(args); + return; + } + + // This is the actual test code + System.gc(); + } + + private static boolean shouldLaunchTest(String[] cmdlineArguments) { + return cmdlineArguments[0].equals("launch"); + } + + private static void launchTest(String[] args) throws Exception { + String[] testArgs = createTestArguments(args); + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(testArgs); + + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + output.shouldNotContain("WARNING"); + + // There will always be at least one java.lang.Class instance + output.shouldContain("java.lang.Class"); + + // There will always be at least one java.lang.String instance + output.shouldContain("java.lang.String"); + + output.shouldHaveExitValue(0); + } + + private static String[] createTestArguments(String[] cmdlineArguments) { + List<String> cmdlineArgs = Arrays.asList(cmdlineArguments); + List<String> testArgs = new ArrayList<String>(); + + if (cmdlineArgs.contains("BeforeGC")) { + testArgs.add("-XX:+PrintClassHistogramBeforeFullGC"); + } + if (cmdlineArgs.contains("AfterGC")) { + testArgs.add("-XX:+PrintClassHistogramAfterFullGC"); + } + + testArgs.add("TestPrintClassHistogram"); + testArgs.add("run"); + + return testArgs.toArray(new String[testArgs.size()]); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/runtime/7107135/Test.java Thu Apr 11 22:44:41 2013 -0700 @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2002-2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011 SAP AG. All Rights Reserved. + * 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. + */ + +class Test { + + static boolean loadLib(String libName){ + try { + System.loadLibrary(libName); + System.out.println("Loaded library "+ libName + "."); + return true; + } catch (SecurityException e) { + System.out.println("loadLibrary(\"" + libName + "\") throws: " + e + "\n"); + } catch (UnsatisfiedLinkError e) { + System.out.println("loadLibrary(\"" + libName + "\") throws: " + e + "\n"); + } + return false; + } + + public static int counter = 1; + + static int Runner() { + counter = counter * -1; + int i = counter; + if(counter < 2) counter += Runner(); + return i; + } + + public static int run() { + try{ + Runner(); + } catch (StackOverflowError e) { + System.out.println("Caught stack overflow error."); + return 0; + } catch (OutOfMemoryError e) { + return 0; + } + return 2; + } + + public static void main(String argv[]) { + loadLib(argv[0]); + System.exit(run()); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/runtime/7107135/Test7107135.sh Thu Apr 11 22:44:41 2013 -0700 @@ -0,0 +1,98 @@ +#!/bin/sh + +# +# Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011 SAP AG. All Rights Reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# + +## +## @test Test7107135.sh +## @bug 7107135 +## @summary Stack guard pages lost after loading library with executable stack. +## @run shell Test7107135.sh +## + +if [ "${TESTSRC}" = "" ] +then TESTSRC=. +fi + +if [ "${TESTJAVA}" = "" ] +then + PARENT=`dirname \`which java\`` + TESTJAVA=`dirname ${PARENT}` + echo "TESTJAVA not set, selecting " ${TESTJAVA} + echo "If this is incorrect, try setting the variable manually." +fi + +BIT_FLAG="" + +# set platform-dependent variables +OS=`uname -s` +case "$OS" in + Linux) + NULL=/dev/null + PS=":" + FS="/" + ;; + *) + NULL=NUL + PS=";" + FS="\\" + echo "Test passed; only valid for Linux" + exit 0; + ;; +esac + +ARCH=`uname -m` + +THIS_DIR=`pwd` + +cp ${TESTSRC}${FS}*.java ${THIS_DIR} +${TESTJAVA}${FS}bin${FS}javac *.java + +gcc -fPIC -shared -c -o test.o -I${TESTJAVA}${FS}include -I${TESTJAVA}${FS}include${FS}linux ${TESTSRC}${FS}test.c +ld -shared -z execstack -o libtest-rwx.so test.o +ld -shared -z noexecstack -o libtest-rw.so test.o + + +LD_LIBRARY_PATH=${THIS_DIR} +echo LD_LIBRARY_PATH = ${LD_LIBRARY_PATH} +export LD_LIBRARY_PATH + +# This should not fail. +echo Check testprogram. Expected to pass: +echo ${TESTJAVA}${FS}bin${FS}java -cp ${THIS_DIR} Test test-rw +${TESTJAVA}${FS}bin${FS}java -cp ${THIS_DIR} Test test-rw + +echo +echo Test changing of stack protection: +echo ${TESTJAVA}${FS}bin${FS}java -cp ${THIS_DIR} Test test-rw +${TESTJAVA}${FS}bin${FS}java -cp ${THIS_DIR} Test test-rwx + +if [ "$?" == "0" ] +then + echo + echo ${TESTJAVA}${FS}bin${FS}java -cp ${THIS_DIR} TestMT test-rwx + ${TESTJAVA}${FS}bin${FS}java -cp ${THIS_DIR} TestMT test-rwx +fi + +exit $?
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/runtime/7107135/TestMT.java Thu Apr 11 22:44:41 2013 -0700 @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2002-2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011 SAP AG. All Rights Reserved. + * 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. + */ + +class TestMT { + + static boolean loadLib(String libName) { + try { + System.loadLibrary(libName); + System.out.println("Loaded library "+ libName + "."); + return true; + } catch (SecurityException e) { + System.out.println("loadLibrary(\"" + libName + "\") throws: " + e + "\n"); + } catch (UnsatisfiedLinkError e) { + System.out.println("loadLibrary(\"" + libName + "\") throws: " + e + "\n"); + } + return false; + } + + public static int counter = 1; + static int Runner() { + counter = counter * -1; + int i = counter; + if (counter < 2) counter += Runner(); + return i; + } + + public static int run(String msg) { + try { + Runner(); + } catch (StackOverflowError e) { + System.out.println(msg + " caught stack overflow error."); + return 0; + } catch (OutOfMemoryError e) { + return 0; + } + return 2; + } + + public static void main(String argv[]) { + try { + for (int i = 0; i < 20; i++) { + Thread t = new DoStackOverflow("SpawnedThread " + i); + t.start(); + } + run("Main thread"); + loadLib("test-rwx"); + run("Main thread"); + } catch (Exception e) { + System.out.println(e); + } + } + + static class DoStackOverflow extends Thread { + public DoStackOverflow(String name) { + super(name); + } + public void run() { + for (int i = 0; i < 10; ++i) { + TestMT.run(getName()); + yield(); + } + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/runtime/7107135/test.c Thu Apr 11 22:44:41 2013 -0700 @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2002-2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011 SAP AG. All Rights Reserved. + * 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 <stdlib.h> +#include <string.h> +#include <stdio.h> +#include "jni.h" +#ifdef __cplusplus +extern "C" { +#endif + +JNIEXPORT jint JNICALL Java_Test_someMethod(JNIEnv *env, jobject mainObject) { + return 3; +} + +#ifdef __cplusplus +} +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/runtime/8010389/VMThreadDlopen.java Thu Apr 11 22:44:41 2013 -0700 @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.io.File; + +/* + * @test + * @key regression + * @bug 8010389 + * @run main/othervm -Djava.library.path=. VMThreadDlopen + */ + +public class VMThreadDlopen { + public static void main(String[] args) throws Exception { + File file = new File("libbroken.so"); + file.createNewFile(); + try { + System.loadLibrary("broken"); + } catch (UnsatisfiedLinkError e) { + e.printStackTrace(); + // expected + } + } +}
--- a/test/runtime/NMT/AllocTestType.java Wed Apr 10 10:29:50 2013 -0700 +++ b/test/runtime/NMT/AllocTestType.java Thu Apr 11 22:44:41 2013 -0700 @@ -25,9 +25,10 @@ * @test * @summary Test consistency of NMT by leaking a few select allocations of the Test type and then verify visibility with jcmd * @key nmt jcmd - * @library /testlibrary - * @run compile -J-XX:+UnlockDiagnosticVMOptions -J-XX:+WhiteBoxAPI AllocTestType.java - * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:NativeMemoryTracking=detail AllocTestType + * @library /testlibrary /testlibrary/whitebox + * @build AllocTestType + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:NativeMemoryTracking=detail AllocTestType */ import com.oracle.java.testlibrary.*;
--- a/test/runtime/NMT/PrintNMTStatistics.java Wed Apr 10 10:29:50 2013 -0700 +++ b/test/runtime/NMT/PrintNMTStatistics.java Thu Apr 11 22:44:41 2013 -0700 @@ -26,8 +26,8 @@ * @key nmt regression * @bug 8005936 * @summary Make sure PrintNMTStatistics works on normal JVM exit - * @library /testlibrary - * @run compile -J-XX:+UnlockDiagnosticVMOptions -J-XX:+WhiteBoxAPI PrintNMTStatistics.java + * @library /testlibrary /testlibrary/whitebox + * @run compile PrintNMTStatistics.java */ import com.oracle.java.testlibrary.*;
--- a/test/runtime/NMT/SummarySanityCheck.java Wed Apr 10 10:29:50 2013 -0700 +++ b/test/runtime/NMT/SummarySanityCheck.java Thu Apr 11 22:44:41 2013 -0700 @@ -25,9 +25,10 @@ * @test * @key nmt jcmd * @summary Sanity check the output of NMT - * @library /testlibrary - * @run compile -J-XX:+UnlockDiagnosticVMOptions -J-XX:+WhiteBoxAPI SummarySanityCheck.java - * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:NativeMemoryTracking=summary -XX:+WhiteBoxAPI SummarySanityCheck + * @library /testlibrary /testlibrary/whitebox + * @build SummarySanityCheck + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:NativeMemoryTracking=summary -XX:+WhiteBoxAPI SummarySanityCheck */ import com.oracle.java.testlibrary.*;
--- a/test/sanity/WBApi.java Wed Apr 10 10:29:50 2013 -0700 +++ b/test/sanity/WBApi.java Thu Apr 11 22:44:41 2013 -0700 @@ -1,8 +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. + */ + /* * @test WBApi * @summary verify that whitebox functions can be linked and executed - * @run compile -J-XX:+UnlockDiagnosticVMOptions -J-XX:+WhiteBoxAPI WBApi.java - * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI WBApi + * @library /testlibrary /testlibrary/whitebox + * @build WBApi + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI WBApi */ import sun.hotspot.WhiteBox;
--- a/test/serviceability/ParserTest.java Wed Apr 10 10:29:50 2013 -0700 +++ b/test/serviceability/ParserTest.java Thu Apr 11 22:44:41 2013 -0700 @@ -1,8 +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. + */ + /* * @test ParserTest - * @summary verify that whitebox functions can be linked and executed - * @run compile -J-XX:+UnlockDiagnosticVMOptions -J-XX:+WhiteBoxAPI ParserTest.java - * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI ParserTest + * @summary Test that the diagnostic command arguemnt parser works + * @library /testlibrary /testlibrary/whitebox + * @build ParserTest + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI ParserTest */ import java.math.BigInteger;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/testlibrary/ClassFileInstaller.java Thu Apr 11 22:44:41 2013 -0700 @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.io.InputStream; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.StandardCopyOption; + +/** + * Dump a class file for a class on the class path in the current directory + */ +public class ClassFileInstaller { + /** + * @param args The names of the classes to dump + * @throws Exception + */ + public static void main(String... args) throws Exception { + for (String arg : args) { + ClassLoader cl = ClassFileInstaller.class.getClassLoader(); + + // Convert dotted class name to a path to a class file + String pathName = arg.replace('.', '/').concat(".class"); + InputStream is = cl.getResourceAsStream(pathName); + + // Create the class file's package directory + Path p = Paths.get(pathName); + Files.createDirectories(p.getParent()); + // Create the class file + Files.copy(is, p, StandardCopyOption.REPLACE_EXISTING); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/testlibrary/whitebox/sun/hotspot/WhiteBox.java Thu Apr 11 22:44:41 2013 -0700 @@ -0,0 +1,77 @@ +/* + * 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. + * + */ + +package sun.hotspot; +import java.security.BasicPermission; +import sun.hotspot.parser.DiagnosticCommand; + +public class WhiteBox { + + @SuppressWarnings("serial") + public static class WhiteBoxPermission extends BasicPermission { + public WhiteBoxPermission(String s) { + super(s); + } + } + + private WhiteBox() {} + private static final WhiteBox instance = new WhiteBox(); + private static native void registerNatives(); + + /** + * Returns the singleton WhiteBox instance. + * + * The returned WhiteBox object should be carefully guarded + * by the caller, since it can be used to read and write data + * at arbitrary memory addresses. It must never be passed to + * untrusted code. + */ + public synchronized static WhiteBox getWhiteBox() { + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + sm.checkPermission(new WhiteBoxPermission("getInstance")); + } + return instance; + } + + static { + registerNatives(); + } + + // Memory + public native long getObjectAddress(Object o); + public native int getHeapOopSize(); + + // G1 + public native boolean g1InConcurrentMark(); + public native boolean g1IsHumongous(Object o); + public native long g1NumFreeRegions(); + public native int g1RegionSize(); + public native Object[] parseCommandLine(String commandline, DiagnosticCommand[] args); + + // NMT + public native boolean NMTAllocTest(); + public native boolean NMTFreeTestMemory(); + public native boolean NMTWaitForDataMerge(); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/testlibrary/whitebox/sun/hotspot/parser/DiagnosticCommand.java Thu Apr 11 22:44:41 2013 -0700 @@ -0,0 +1,66 @@ +/* + * 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. + */ + +package sun.hotspot.parser; + +public class DiagnosticCommand { + + public enum DiagnosticArgumentType { + JLONG, BOOLEAN, STRING, NANOTIME, STRINGARRAY, MEMORYSIZE + } + + private String name; + private String desc; + private DiagnosticArgumentType type; + private boolean mandatory; + private String defaultValue; + + public DiagnosticCommand(String name, String desc, DiagnosticArgumentType type, + boolean mandatory, String defaultValue) { + this.name = name; + this.desc = desc; + this.type = type; + this.mandatory = mandatory; + this.defaultValue = defaultValue; + } + + public String getName() { + return name; + } + + public String getDesc() { + return desc; + } + + public DiagnosticArgumentType getType() { + return type; + } + + public boolean isMandatory() { + return mandatory; + } + + public String getDefaultValue() { + return defaultValue; + } +}