OpenJDK / jdk / jdk
changeset 37267:ad8c0e8de29f
Merge
line wrap: on
line diff
--- a/hotspot/make/aix/adlc_updater Mon Apr 04 13:40:18 2016 -0700 +++ b/hotspot/make/aix/adlc_updater Thu Apr 07 09:47:48 2016 -0700 @@ -9,12 +9,15 @@ # fix_lines() { # repair bare #line directives in $1 to refer to $2 - awk < $1 > $1+ ' + # and add an override of __FILE__ with just the basename on the + # first line of the file. + awk < $1 > $1+ -v F2=$2 ' + BEGIN { print "#line 1 \"" F2 "\""; } /^#line 999999$/ {print "#line " (NR+1) " \"" F2 "\""; next} {print} - ' F2=$2 + ' mv $1+ $1 } -fix_lines $2/$1 $3/$1 +fix_lines $2/$1 $1 [ -f $3/$1 ] && cmp -s $2/$1 $3/$1 || \ ( [ -f $3/$1 ] && echo Updating $3/$1 ; touch $2/made-change ; mv $2/$1 $3/$1 )
--- a/hotspot/make/aix/makefiles/trace.make Mon Apr 04 13:40:18 2016 -0700 +++ b/hotspot/make/aix/makefiles/trace.make Thu Apr 07 09:47:48 2016 -0700 @@ -27,14 +27,17 @@ # # It knows how to build and run the tools to generate trace files. -include $(GAMMADIR)/make/linux/makefiles/rules.make +include $(GAMMADIR)/make/aix/makefiles/rules.make include $(GAMMADIR)/make/altsrc.make # ######################################################################### -HAS_ALT_SRC:=$(shell if [ -d $(HS_ALT_SRC)/share/vm/trace ]; then \ - echo "true"; else echo "false";\ - fi) +HAS_ALT_SRC := false +ifndef OPENJDK + ifneq ($(wildcard $(HS_ALT_SRC)/share/vm/trace), ) + HAS_ALT_SRC := true + endif +endif TOPDIR = $(shell echo `pwd`) GENERATED = $(TOPDIR)/../generated @@ -50,23 +53,30 @@ TraceGeneratedNames = \ traceEventClasses.hpp \ - traceEventIds.hpp \ - traceTypes.hpp + traceEventIds.hpp \ + traceTypes.hpp ifeq ($(HAS_ALT_SRC), true) -TraceGeneratedNames += \ - traceRequestables.hpp \ - traceEventControl.hpp + TraceGeneratedNames += \ + traceRequestables.hpp \ + traceEventControl.hpp endif TraceGeneratedFiles = $(TraceGeneratedNames:%=$(TraceOutDir)/%) XSLT = $(REMOTE) $(RUN.JAVA) -classpath $(JvmtiOutDir) jvmtiGen -XML_DEPS = $(TraceSrcDir)/trace.xml $(TraceSrcDir)/tracetypes.xml \ - $(TraceSrcDir)/trace.dtd $(TraceSrcDir)/xinclude.mod +TraceXml = $(TraceSrcDir)/trace.xml ifeq ($(HAS_ALT_SRC), true) - XML_DEPS += $(TraceAltSrcDir)/traceevents.xml + TraceXml = $(TraceAltSrcDir)/trace.xml +endif + +XML_DEPS = $(TraceXml) $(TraceSrcDir)/tracetypes.xml \ + $(TraceSrcDir)/trace.dtd $(TraceSrcDir)/xinclude.mod \ + $(TraceSrcDir)/tracerelationdecls.xml $(TraceSrcDir)/traceevents.xml +ifeq ($(HAS_ALT_SRC), true) + XML_DEPS += $(TraceAltSrcDir)/traceeventscustom.xml \ + $(TraceAltSrcDir)/traceeventtypes.xml endif .PHONY: all clean cleanall @@ -79,26 +89,26 @@ $(QUIETLY) echo $(LOG_INFO) Generating $@; \ $(XSLT) -IN $(word 1,$^) -XSL $(word 2,$^) -OUT $@ -$(TraceOutDir)/traceEventIds.hpp: $(TraceSrcDir)/trace.xml $(TraceSrcDir)/traceEventIds.xsl $(XML_DEPS) +$(TraceOutDir)/traceEventIds.hpp: $(TraceXml) $(TraceSrcDir)/traceEventIds.xsl $(XML_DEPS) $(GENERATE_CODE) -$(TraceOutDir)/traceTypes.hpp: $(TraceSrcDir)/trace.xml $(TraceSrcDir)/traceTypes.xsl $(XML_DEPS) +$(TraceOutDir)/traceTypes.hpp: $(TraceXml) $(TraceSrcDir)/traceTypes.xsl $(XML_DEPS) $(GENERATE_CODE) ifeq ($(HAS_ALT_SRC), false) -$(TraceOutDir)/traceEventClasses.hpp: $(TraceSrcDir)/trace.xml $(TraceSrcDir)/traceEventClasses.xsl $(XML_DEPS) +$(TraceOutDir)/traceEventClasses.hpp: $(TraceXml) $(TraceSrcDir)/traceEventClasses.xsl $(XML_DEPS) $(GENERATE_CODE) else -$(TraceOutDir)/traceEventClasses.hpp: $(TraceSrcDir)/trace.xml $(TraceAltSrcDir)/traceEventClasses.xsl $(XML_DEPS) +$(TraceOutDir)/traceEventClasses.hpp: $(TraceXml) $(TraceAltSrcDir)/traceEventClasses.xsl $(XML_DEPS) $(GENERATE_CODE) -$(TraceOutDir)/traceRequestables.hpp: $(TraceSrcDir)/trace.xml $(TraceAltSrcDir)/traceRequestables.xsl $(XML_DEPS) +$(TraceOutDir)/traceRequestables.hpp: $(TraceXml) $(TraceAltSrcDir)/traceRequestables.xsl $(XML_DEPS) $(GENERATE_CODE) -$(TraceOutDir)/traceEventControl.hpp: $(TraceSrcDir)/trace.xml $(TraceAltSrcDir)/traceEventControl.xsl $(XML_DEPS) +$(TraceOutDir)/traceEventControl.hpp: $(TraceXml) $(TraceAltSrcDir)/traceEventControl.xsl $(XML_DEPS) $(GENERATE_CODE) endif
--- a/hotspot/make/bsd/adlc_updater Mon Apr 04 13:40:18 2016 -0700 +++ b/hotspot/make/bsd/adlc_updater Thu Apr 07 09:47:48 2016 -0700 @@ -9,12 +9,15 @@ # fix_lines() { # repair bare #line directives in $1 to refer to $2 - awk < $1 > $1+ ' + # and add an override of __FILE__ with just the basename on the + # first line of the file. + awk < $1 > $1+ -v F2=$2 ' + BEGIN { print "#line 1 \"" F2 "\""; } /^#line 999999$/ {print "#line " (NR+1) " \"" F2 "\""; next} {print} - ' F2=$2 + ' mv $1+ $1 } -fix_lines $2/$1 $3/$1 +fix_lines $2/$1 $1 [ -f $3/$1 ] && cmp -s $2/$1 $3/$1 || \ ( [ -f $3/$1 ] && echo Updating $3/$1 ; touch $2/made-change ; mv $2/$1 $3/$1 )
--- a/hotspot/make/bsd/makefiles/trace.make Mon Apr 04 13:40:18 2016 -0700 +++ b/hotspot/make/bsd/makefiles/trace.make Thu Apr 07 09:47:48 2016 -0700 @@ -32,9 +32,12 @@ # ######################################################################### -HAS_ALT_SRC:=$(shell if [ -d $(HS_ALT_SRC)/share/vm/trace ]; then \ - echo "true"; else echo "false";\ - fi) +HAS_ALT_SRC := false +ifndef OPENJDK + ifneq ($(wildcard $(HS_ALT_SRC)/share/vm/trace), ) + HAS_ALT_SRC := true + endif +endif TOPDIR = $(shell echo `pwd`) GENERATED = $(TOPDIR)/../generated @@ -50,24 +53,30 @@ TraceGeneratedNames = \ traceEventClasses.hpp \ - traceEventIds.hpp \ - traceTypes.hpp + traceEventIds.hpp \ + traceTypes.hpp ifeq ($(HAS_ALT_SRC), true) -TraceGeneratedNames += \ - traceRequestables.hpp \ - traceEventControl.hpp + TraceGeneratedNames += \ + traceRequestables.hpp \ + traceEventControl.hpp endif - TraceGeneratedFiles = $(TraceGeneratedNames:%=$(TraceOutDir)/%) XSLT = $(REMOTE) $(RUN.JAVA) -classpath $(JvmtiOutDir) jvmtiGen -XML_DEPS = $(TraceSrcDir)/trace.xml $(TraceSrcDir)/tracetypes.xml \ - $(TraceSrcDir)/trace.dtd $(TraceSrcDir)/xinclude.mod +TraceXml = $(TraceSrcDir)/trace.xml ifeq ($(HAS_ALT_SRC), true) - XML_DEPS += $(TraceAltSrcDir)/traceevents.xml + TraceXml = $(TraceAltSrcDir)/trace.xml +endif + +XML_DEPS = $(TraceXml) $(TraceSrcDir)/tracetypes.xml \ + $(TraceSrcDir)/trace.dtd $(TraceSrcDir)/xinclude.mod \ + $(TraceSrcDir)/tracerelationdecls.xml $(TraceSrcDir)/traceevents.xml +ifeq ($(HAS_ALT_SRC), true) + XML_DEPS += $(TraceAltSrcDir)/traceeventscustom.xml \ + $(TraceAltSrcDir)/traceeventtypes.xml endif .PHONY: all clean cleanall @@ -80,32 +89,31 @@ $(QUIETLY) echo $(LOG_INFO) Generating $@; \ $(XSLT) -IN $(word 1,$^) -XSL $(word 2,$^) -OUT $@ -$(TraceOutDir)/traceEventIds.hpp: $(TraceSrcDir)/trace.xml $(TraceSrcDir)/traceEventIds.xsl $(XML_DEPS) +$(TraceOutDir)/traceEventIds.hpp: $(TraceXml) $(TraceSrcDir)/traceEventIds.xsl $(XML_DEPS) $(GENERATE_CODE) -$(TraceOutDir)/traceTypes.hpp: $(TraceSrcDir)/trace.xml $(TraceSrcDir)/traceTypes.xsl $(XML_DEPS) +$(TraceOutDir)/traceTypes.hpp: $(TraceXml) $(TraceSrcDir)/traceTypes.xsl $(XML_DEPS) $(GENERATE_CODE) ifeq ($(HAS_ALT_SRC), false) -$(TraceOutDir)/traceEventClasses.hpp: $(TraceSrcDir)/trace.xml $(TraceSrcDir)/traceEventClasses.xsl $(XML_DEPS) +$(TraceOutDir)/traceEventClasses.hpp: $(TraceXml) $(TraceSrcDir)/traceEventClasses.xsl $(XML_DEPS) $(GENERATE_CODE) else -$(TraceOutDir)/traceEventClasses.hpp: $(TraceSrcDir)/trace.xml $(TraceAltSrcDir)/traceEventClasses.xsl $(XML_DEPS) +$(TraceOutDir)/traceEventClasses.hpp: $(TraceXml) $(TraceAltSrcDir)/traceEventClasses.xsl $(XML_DEPS) $(GENERATE_CODE) -$(TraceOutDir)/traceRequestables.hpp: $(TraceSrcDir)/trace.xml $(TraceAltSrcDir)/traceRequestables.xsl $(XML_DEPS) +$(TraceOutDir)/traceRequestables.hpp: $(TraceXml) $(TraceAltSrcDir)/traceRequestables.xsl $(XML_DEPS) $(GENERATE_CODE) -$(TraceOutDir)/traceEventControl.hpp: $(TraceSrcDir)/trace.xml $(TraceAltSrcDir)/traceEventControl.xsl $(XML_DEPS) +$(TraceOutDir)/traceEventControl.hpp: $(TraceXml) $(TraceAltSrcDir)/traceEventControl.xsl $(XML_DEPS) $(GENERATE_CODE) endif # ######################################################################### - clean cleanall: rm $(TraceGeneratedFiles)
--- a/hotspot/make/linux/adlc_updater Mon Apr 04 13:40:18 2016 -0700 +++ b/hotspot/make/linux/adlc_updater Thu Apr 07 09:47:48 2016 -0700 @@ -9,12 +9,15 @@ # fix_lines() { # repair bare #line directives in $1 to refer to $2 - awk < $1 > $1+ ' + # and add an override of __FILE__ with just the basename on the + # first line of the file. + awk < $1 > $1+ -v F2=$2 ' + BEGIN { print "#line 1 \"" F2 "\""; } /^#line 999999$/ {print "#line " (NR+1) " \"" F2 "\""; next} {print} - ' F2=$2 + ' mv $1+ $1 } -fix_lines $2/$1 $3/$1 +fix_lines $2/$1 $1 [ -f $3/$1 ] && cmp -s $2/$1 $3/$1 || \ ( [ -f $3/$1 ] && echo Updating $3/$1 ; touch $2/made-change ; mv $2/$1 $3/$1 )
--- a/hotspot/make/linux/makefiles/trace.make Mon Apr 04 13:40:18 2016 -0700 +++ b/hotspot/make/linux/makefiles/trace.make Thu Apr 07 09:47:48 2016 -0700 @@ -32,9 +32,12 @@ # ######################################################################### -HAS_ALT_SRC:=$(shell if [ -d $(HS_ALT_SRC)/share/vm/trace ]; then \ - echo "true"; else echo "false";\ - fi) +HAS_ALT_SRC := false +ifndef OPENJDK + ifneq ($(wildcard $(HS_ALT_SRC)/share/vm/trace), ) + HAS_ALT_SRC := true + endif +endif TOPDIR = $(shell echo `pwd`) GENERATED = $(TOPDIR)/../generated @@ -50,23 +53,30 @@ TraceGeneratedNames = \ traceEventClasses.hpp \ - traceEventIds.hpp \ - traceTypes.hpp + traceEventIds.hpp \ + traceTypes.hpp ifeq ($(HAS_ALT_SRC), true) -TraceGeneratedNames += \ - traceRequestables.hpp \ - traceEventControl.hpp + TraceGeneratedNames += \ + traceRequestables.hpp \ + traceEventControl.hpp endif TraceGeneratedFiles = $(TraceGeneratedNames:%=$(TraceOutDir)/%) XSLT = $(REMOTE) $(RUN.JAVA) -classpath $(JvmtiOutDir) jvmtiGen -XML_DEPS = $(TraceSrcDir)/trace.xml $(TraceSrcDir)/tracetypes.xml \ - $(TraceSrcDir)/trace.dtd $(TraceSrcDir)/xinclude.mod +TraceXml = $(TraceSrcDir)/trace.xml ifeq ($(HAS_ALT_SRC), true) - XML_DEPS += $(TraceAltSrcDir)/traceevents.xml + TraceXml = $(TraceAltSrcDir)/trace.xml +endif + +XML_DEPS = $(TraceXml) $(TraceSrcDir)/tracetypes.xml \ + $(TraceSrcDir)/trace.dtd $(TraceSrcDir)/xinclude.mod \ + $(TraceSrcDir)/tracerelationdecls.xml $(TraceSrcDir)/traceevents.xml +ifeq ($(HAS_ALT_SRC), true) + XML_DEPS += $(TraceAltSrcDir)/traceeventscustom.xml \ + $(TraceAltSrcDir)/traceeventtypes.xml endif .PHONY: all clean cleanall @@ -79,26 +89,26 @@ $(QUIETLY) echo $(LOG_INFO) Generating $@; \ $(XSLT) -IN $(word 1,$^) -XSL $(word 2,$^) -OUT $@ -$(TraceOutDir)/traceEventIds.hpp: $(TraceSrcDir)/trace.xml $(TraceSrcDir)/traceEventIds.xsl $(XML_DEPS) +$(TraceOutDir)/traceEventIds.hpp: $(TraceXml) $(TraceSrcDir)/traceEventIds.xsl $(XML_DEPS) $(GENERATE_CODE) -$(TraceOutDir)/traceTypes.hpp: $(TraceSrcDir)/trace.xml $(TraceSrcDir)/traceTypes.xsl $(XML_DEPS) +$(TraceOutDir)/traceTypes.hpp: $(TraceXml) $(TraceSrcDir)/traceTypes.xsl $(XML_DEPS) $(GENERATE_CODE) ifeq ($(HAS_ALT_SRC), false) -$(TraceOutDir)/traceEventClasses.hpp: $(TraceSrcDir)/trace.xml $(TraceSrcDir)/traceEventClasses.xsl $(XML_DEPS) +$(TraceOutDir)/traceEventClasses.hpp: $(TraceXml) $(TraceSrcDir)/traceEventClasses.xsl $(XML_DEPS) $(GENERATE_CODE) else -$(TraceOutDir)/traceEventClasses.hpp: $(TraceSrcDir)/trace.xml $(TraceAltSrcDir)/traceEventClasses.xsl $(XML_DEPS) +$(TraceOutDir)/traceEventClasses.hpp: $(TraceXml) $(TraceAltSrcDir)/traceEventClasses.xsl $(XML_DEPS) $(GENERATE_CODE) -$(TraceOutDir)/traceRequestables.hpp: $(TraceSrcDir)/trace.xml $(TraceAltSrcDir)/traceRequestables.xsl $(XML_DEPS) +$(TraceOutDir)/traceRequestables.hpp: $(TraceXml) $(TraceAltSrcDir)/traceRequestables.xsl $(XML_DEPS) $(GENERATE_CODE) -$(TraceOutDir)/traceEventControl.hpp: $(TraceSrcDir)/trace.xml $(TraceAltSrcDir)/traceEventControl.xsl $(XML_DEPS) +$(TraceOutDir)/traceEventControl.hpp: $(TraceXml) $(TraceAltSrcDir)/traceEventControl.xsl $(XML_DEPS) $(GENERATE_CODE) endif @@ -107,5 +117,3 @@ clean cleanall: rm $(TraceGeneratedFiles) - -
--- a/hotspot/make/share/makefiles/mapfile-vers Mon Apr 04 13:40:18 2016 -0700 +++ b/hotspot/make/share/makefiles/mapfile-vers Thu Apr 07 09:47:48 2016 -0700 @@ -109,8 +109,7 @@ JVM_GetPrimitiveArrayElement; JVM_GetProtectionDomain; JVM_GetStackAccessControlContext; - JVM_GetStackTraceDepth; - JVM_GetStackTraceElement; + JVM_GetStackTraceElements; JVM_GetSystemPackage; JVM_GetSystemPackages; JVM_GetTemporaryDirectory;
--- a/hotspot/make/solaris/adlc_updater Mon Apr 04 13:40:18 2016 -0700 +++ b/hotspot/make/solaris/adlc_updater Thu Apr 07 09:47:48 2016 -0700 @@ -9,12 +9,15 @@ # fix_lines() { # repair bare #line directives in $1 to refer to $2 - awk < $1 > $1+ ' + # and add an override of __FILE__ with just the basename on the + # first line of the file. + nawk < $1 > $1+ -v F2=$2 ' + BEGIN { print "#line 1 \"" F2 "\""; } /^#line 999999$/ {print "#line " (NR+1) " \"" F2 "\""; next} {print} - ' F2=$2 + ' mv $1+ $1 } -fix_lines $2/$1 $3/$1 +fix_lines $2/$1 $1 [ -f $3/$1 ] && cmp -s $2/$1 $3/$1 || \ ( [ -f $3/$1 ] && echo Updating $3/$1 ; touch $2/made-change ; mv $2/$1 $3/$1 )
--- a/hotspot/make/solaris/makefiles/trace.make Mon Apr 04 13:40:18 2016 -0700 +++ b/hotspot/make/solaris/makefiles/trace.make Thu Apr 07 09:47:48 2016 -0700 @@ -32,9 +32,12 @@ # ######################################################################### -HAS_ALT_SRC:=$(shell if [ -d $(HS_ALT_SRC)/share/vm/trace ]; then \ - echo "true"; else echo "false";\ - fi) +HAS_ALT_SRC := false +ifndef OPENJDK + ifneq ($(wildcard $(HS_ALT_SRC)/share/vm/trace), ) + HAS_ALT_SRC := true + endif +endif TOPDIR = $(shell echo `pwd`) GENERATED = $(TOPDIR)/../generated @@ -50,23 +53,30 @@ TraceGeneratedNames = \ traceEventClasses.hpp \ - traceEventIds.hpp \ - traceTypes.hpp + traceEventIds.hpp \ + traceTypes.hpp ifeq ($(HAS_ALT_SRC), true) -TraceGeneratedNames += \ - traceRequestables.hpp \ - traceEventControl.hpp + TraceGeneratedNames += \ + traceRequestables.hpp \ + traceEventControl.hpp endif TraceGeneratedFiles = $(TraceGeneratedNames:%=$(TraceOutDir)/%) XSLT = $(REMOTE) $(RUN.JAVA) -classpath $(JvmtiOutDir) jvmtiGen -XML_DEPS = $(TraceSrcDir)/trace.xml $(TraceSrcDir)/tracetypes.xml \ - $(TraceSrcDir)/trace.dtd $(TraceSrcDir)/xinclude.mod +TraceXml = $(TraceSrcDir)/trace.xml ifeq ($(HAS_ALT_SRC), true) - XML_DEPS += $(TraceAltSrcDir)/traceevents.xml + TraceXml = $(TraceAltSrcDir)/trace.xml +endif + +XML_DEPS = $(TraceXml) $(TraceSrcDir)/tracetypes.xml \ + $(TraceSrcDir)/trace.dtd $(TraceSrcDir)/xinclude.mod \ + $(TraceSrcDir)/tracerelationdecls.xml $(TraceSrcDir)/traceevents.xml +ifeq ($(HAS_ALT_SRC), true) + XML_DEPS += $(TraceAltSrcDir)/traceeventscustom.xml \ + $(TraceAltSrcDir)/traceeventtypes.xml endif .PHONY: all clean cleanall @@ -79,26 +89,26 @@ $(QUIETLY) echo $(LOG_INFO) Generating $@; \ $(XSLT) -IN $(word 1,$^) -XSL $(word 2,$^) -OUT $@ -$(TraceOutDir)/traceEventIds.hpp: $(TraceSrcDir)/trace.xml $(TraceSrcDir)/traceEventIds.xsl $(XML_DEPS) +$(TraceOutDir)/traceEventIds.hpp: $(TraceXml) $(TraceSrcDir)/traceEventIds.xsl $(XML_DEPS) $(GENERATE_CODE) -$(TraceOutDir)/traceTypes.hpp: $(TraceSrcDir)/trace.xml $(TraceSrcDir)/traceTypes.xsl $(XML_DEPS) +$(TraceOutDir)/traceTypes.hpp: $(TraceXml) $(TraceSrcDir)/traceTypes.xsl $(XML_DEPS) $(GENERATE_CODE) ifeq ($(HAS_ALT_SRC), false) -$(TraceOutDir)/traceEventClasses.hpp: $(TraceSrcDir)/trace.xml $(TraceSrcDir)/traceEventClasses.xsl $(XML_DEPS) +$(TraceOutDir)/traceEventClasses.hpp: $(TraceXml) $(TraceSrcDir)/traceEventClasses.xsl $(XML_DEPS) $(GENERATE_CODE) else -$(TraceOutDir)/traceEventClasses.hpp: $(TraceSrcDir)/trace.xml $(TraceAltSrcDir)/traceEventClasses.xsl $(XML_DEPS) +$(TraceOutDir)/traceEventClasses.hpp: $(TraceXml) $(TraceAltSrcDir)/traceEventClasses.xsl $(XML_DEPS) $(GENERATE_CODE) -$(TraceOutDir)/traceRequestables.hpp: $(TraceSrcDir)/trace.xml $(TraceAltSrcDir)/traceRequestables.xsl $(XML_DEPS) +$(TraceOutDir)/traceRequestables.hpp: $(TraceXml) $(TraceAltSrcDir)/traceRequestables.xsl $(XML_DEPS) $(GENERATE_CODE) -$(TraceOutDir)/traceEventControl.hpp: $(TraceSrcDir)/trace.xml $(TraceAltSrcDir)/traceEventControl.xsl $(XML_DEPS) +$(TraceOutDir)/traceEventControl.hpp: $(TraceXml) $(TraceAltSrcDir)/traceEventControl.xsl $(XML_DEPS) $(GENERATE_CODE) endif
--- a/hotspot/make/windows/build.make Mon Apr 04 13:40:18 2016 -0700 +++ b/hotspot/make/windows/build.make Thu Apr 07 09:47:48 2016 -0700 @@ -114,11 +114,15 @@ # Define HOTSPOT_VM_DISTRO based on settings in make/openjdk_distro # or make/hotspot_distro. !ifndef HOTSPOT_VM_DISTRO +!ifndef OPENJDK !if exists($(WorkSpace)\src\closed) !include $(WorkSpace)\make\hotspot_distro !else !include $(WorkSpace)\make\openjdk_distro !endif +!else +!include $(WorkSpace)\make\openjdk_distro +!endif !endif HS_FILEDESC=$(HOTSPOT_VM_DISTRO) $(ARCH_TEXT) $(VARIANT_TEXT) VM
--- a/hotspot/make/windows/create_obj_files.sh Mon Apr 04 13:40:18 2016 -0700 +++ b/hotspot/make/windows/create_obj_files.sh Thu Apr 07 09:47:48 2016 -0700 @@ -55,7 +55,11 @@ ALTSRC_REL=src/closed # Change this to pick up alt sources from somewhere else COMMONSRC=${WorkSpace}/${COMMONSRC_REL} -ALTSRC=${WorkSpace}/${ALTSRC_REL} +if [ "x$OPENJDK" != "xtrue" ]; then + ALTSRC=${WorkSpace}/${ALTSRC_REL} +else + ALTSRC=PATH_THAT_DOES_NOT_EXIST +fi BASE_PATHS="`if [ -d ${ALTSRC}/share/vm ]; then $FIND ${ALTSRC}/share/vm ! -name vm -prune -type d \! \( -name adlc -o -name c1 -o -name gc -o -name opto -o -name shark -o -name libadt \); fi`" BASE_PATHS="${BASE_PATHS} ` $FIND ${COMMONSRC}/share/vm ! -name vm -prune -type d \! \( -name adlc -o -name c1 -o -name gc -o -name opto -o -name shark -o -name libadt \)`" @@ -158,6 +162,6 @@ fi Obj_Files="${Obj_Files}$o " done -Obj_Files=`echo ${Obj_Files} | tr ' ' '\n' | sort` +Obj_Files=`echo ${Obj_Files} | tr ' ' '\n' | LC_ALL=C sort` echo Obj_Files=${Obj_Files}
--- a/hotspot/make/windows/makefiles/defs.make Mon Apr 04 13:40:18 2016 -0700 +++ b/hotspot/make/windows/makefiles/defs.make Thu Apr 07 09:47:48 2016 -0700 @@ -276,3 +276,7 @@ MAKE_ARGS += MT="$(subst /,\\,$(MT))" endif endif + +ifdef OPENJDK + MAKE_ARGS += OPENJDK="$(OPENJDK)" +endif
--- a/hotspot/make/windows/makefiles/trace.make Mon Apr 04 13:40:18 2016 -0700 +++ b/hotspot/make/windows/makefiles/trace.make Thu Apr 07 09:47:48 2016 -0700 @@ -32,15 +32,21 @@ # ######################################################################### -TraceAltSrcDir = $(WorkSpace)/src/closed/share/vm/trace -TraceSrcDir = $(WorkSpace)/src/share/vm/trace +TraceAltSrcDir = $(WorkSpace)\src\closed\share\vm\trace +TraceSrcDir = $(WorkSpace)\src\share\vm\trace + +!ifndef OPENJDK +!if EXISTS($(TraceAltSrcDir)) +HAS_ALT_SRC = true +!endif +!endif TraceGeneratedNames = \ traceEventClasses.hpp \ traceEventIds.hpp \ traceTypes.hpp -!if EXISTS($(TraceAltSrcDir)) +!ifdef HAS_ALT_SRC TraceGeneratedNames = $(TraceGeneratedNames) \ traceRequestables.hpp \ traceEventControl.hpp @@ -51,22 +57,30 @@ #Should be equivalent to "TraceGeneratedFiles = $(TraceGeneratedNames:%=$(TraceOutDir)/%)" TraceGeneratedFiles = \ $(TraceOutDir)/traceEventClasses.hpp \ - $(TraceOutDir)/traceEventIds.hpp \ - $(TraceOutDir)/traceTypes.hpp + $(TraceOutDir)/traceEventIds.hpp \ + $(TraceOutDir)/traceTypes.hpp -!if EXISTS($(TraceAltSrcDir)) +!ifdef HAS_ALT_SRC TraceGeneratedFiles = $(TraceGeneratedFiles) \ - $(TraceOutDir)/traceRequestables.hpp \ + $(TraceOutDir)/traceRequestables.hpp \ $(TraceOutDir)/traceEventControl.hpp !endif XSLT = $(QUIETLY) $(REMOTE) $(RUN_JAVA) -classpath $(JvmtiOutDir) jvmtiGen -XML_DEPS = $(TraceSrcDir)/trace.xml $(TraceSrcDir)/tracetypes.xml \ - $(TraceSrcDir)/trace.dtd $(TraceSrcDir)/xinclude.mod +TraceXml = $(TraceSrcDir)/trace.xml + +!ifdef HAS_ALT_SRC +TraceXml = $(TraceAltSrcDir)/trace.xml +!endif -!if EXISTS($(TraceAltSrcDir)) -XML_DEPS = $(XML_DEPS) $(TraceAltSrcDir)/traceevents.xml +XML_DEPS = $(TraceXml) $(TraceSrcDir)/tracetypes.xml \ + $(TraceSrcDir)/trace.dtd $(TraceSrcDir)/xinclude.mod \ + $(TraceSrcDir)/tracerelationdecls.xml $(TraceSrcDir)/traceevents.xml + +!ifdef HAS_ALT_SRC +XML_DEPS = $(XML_DEPS) $(TraceAltSrcDir)/traceeventscustom.xml \ + $(TraceAltSrcDir)/traceeventtypes.xml !endif .PHONY: all clean cleanall @@ -76,33 +90,33 @@ default:: @if not exist $(TraceOutDir) mkdir $(TraceOutDir) -$(TraceOutDir)/traceEventIds.hpp: $(TraceSrcDir)/trace.xml $(TraceSrcDir)/traceEventIds.xsl $(XML_DEPS) +$(TraceOutDir)/traceEventIds.hpp: $(TraceSrcDir)/traceEventIds.xsl $(XML_DEPS) @echo Generating $@ - @$(XSLT) -IN $(TraceSrcDir)/trace.xml -XSL $(TraceSrcDir)/traceEventIds.xsl -OUT $(TraceOutDir)/traceEventIds.hpp + $(XSLT) -IN $(TraceXml) -XSL $(TraceSrcDir)/traceEventIds.xsl -OUT $(TraceOutDir)/traceEventIds.hpp -$(TraceOutDir)/traceTypes.hpp: $(TraceSrcDir)/trace.xml $(TraceSrcDir)/traceTypes.xsl $(XML_DEPS) +$(TraceOutDir)/traceTypes.hpp: $(TraceSrcDir)/traceTypes.xsl $(XML_DEPS) @echo Generating $@ - @$(XSLT) -IN $(TraceSrcDir)/trace.xml -XSL $(TraceSrcDir)/traceTypes.xsl -OUT $(TraceOutDir)/traceTypes.hpp + $(XSLT) -IN $(TraceXml) -XSL $(TraceSrcDir)/traceTypes.xsl -OUT $(TraceOutDir)/traceTypes.hpp -!if !EXISTS($(TraceAltSrcDir)) +!ifndef HAS_ALT_SRC -$(TraceOutDir)/traceEventClasses.hpp: $(TraceSrcDir)/trace.xml $(TraceSrcDir)/traceEventClasses.xsl $(XML_DEPS) +$(TraceOutDir)/traceEventClasses.hpp: $(TraceSrcDir)/traceEventClasses.xsl $(XML_DEPS) @echo Generating OpenJDK $@ - @$(XSLT) -IN $(TraceSrcDir)/trace.xml -XSL $(TraceSrcDir)/traceEventClasses.xsl -OUT $(TraceOutDir)/traceEventClasses.hpp + $(XSLT) -IN $(TraceXml) -XSL $(TraceSrcDir)/traceEventClasses.xsl -OUT $(TraceOutDir)/traceEventClasses.hpp !else -$(TraceOutDir)/traceEventClasses.hpp: $(TraceSrcDir)/trace.xml $(TraceAltSrcDir)/traceEventClasses.xsl $(XML_DEPS) +$(TraceOutDir)/traceEventClasses.hpp: $(TraceAltSrcDir)/traceEventClasses.xsl $(XML_DEPS) @echo Generating AltSrc $@ - @$(XSLT) -IN $(TraceSrcDir)/trace.xml -XSL $(TraceAltSrcDir)/traceEventClasses.xsl -OUT $(TraceOutDir)/traceEventClasses.hpp + $(XSLT) -IN $(TraceXml) -XSL $(TraceAltSrcDir)/traceEventClasses.xsl -OUT $(TraceOutDir)/traceEventClasses.hpp -$(TraceOutDir)/traceRequestables.hpp: $(TraceSrcDir)/trace.xml $(TraceAltSrcDir)/traceRequestables.xsl $(XML_DEPS) +$(TraceOutDir)/traceRequestables.hpp: $(TraceAltSrcDir)/traceRequestables.xsl $(XML_DEPS) @echo Generating AltSrc $@ - @$(XSLT) -IN $(TraceSrcDir)/trace.xml -XSL $(TraceAltSrcDir)/traceRequestables.xsl -OUT $(TraceOutDir)/traceRequestables.hpp + $(XSLT) -IN $(TraceXml) -XSL $(TraceAltSrcDir)/traceRequestables.xsl -OUT $(TraceOutDir)/traceRequestables.hpp -$(TraceOutDir)/traceEventControl.hpp: $(TraceSrcDir)/trace.xml $(TraceAltSrcDir)/traceEventControl.xsl $(XML_DEPS) +$(TraceOutDir)/traceEventControl.hpp: $(TraceAltSrcDir)/traceEventControl.xsl $(XML_DEPS) @echo Generating AltSrc $@ - @$(XSLT) -IN $(TraceSrcDir)/trace.xml -XSL $(TraceAltSrcDir)/traceEventControl.xsl -OUT $(TraceOutDir)/traceEventControl.hpp + $(XSLT) -IN $(TraceXml) -XSL $(TraceAltSrcDir)/traceEventControl.xsl -OUT $(TraceOutDir)/traceEventControl.hpp !endif @@ -110,5 +124,3 @@ cleanall : rm $(TraceGeneratedFiles) - -
--- a/hotspot/make/windows/makefiles/vm.make Mon Apr 04 13:40:18 2016 -0700 +++ b/hotspot/make/windows/makefiles/vm.make Thu Apr 07 09:47:48 2016 -0700 @@ -118,6 +118,7 @@ CXX_INCLUDE_DIRS=/I "..\generated" +!ifndef OPENJDK !if exists($(ALTSRC)\share\vm) CXX_INCLUDE_DIRS=$(CXX_INCLUDE_DIRS) /I "$(ALTSRC)\share\vm" !endif @@ -133,6 +134,7 @@ !if exists($(ALTSRC)\cpu\$(Platform_arch)\vm) CXX_INCLUDE_DIRS=$(CXX_INCLUDE_DIRS) /I "$(ALTSRC)\cpu\$(Platform_arch)\vm" !endif +!endif # OPENJDK CXX_INCLUDE_DIRS=$(CXX_INCLUDE_DIRS) \ /I "$(COMMONSRC)\share\vm" \ @@ -187,10 +189,12 @@ VM_PATH=$(VM_PATH);$(WorkSpace)/src/cpu/$(Platform_arch)/vm VM_PATH=$(VM_PATH);$(WorkSpace)/src/share/vm/opto +!ifndef OPENJDK !if exists($(ALTSRC)\share\vm\jfr) VM_PATH=$(VM_PATH);$(ALTSRC)/share/vm/jfr VM_PATH=$(VM_PATH);$(ALTSRC)/share/vm/jfr/buffers !endif +!endif # OPENJDK VM_PATH={$(VM_PATH)} @@ -310,6 +314,7 @@ {$(COMMONSRC)\os_cpu\windows_$(Platform_arch)\vm}.cpp.obj:: $(CXX) $(CXX_FLAGS) $(CXX_USE_PCH) /c $< +!ifndef OPENJDK {$(ALTSRC)\share\vm\c1}.cpp.obj:: $(CXX) $(CXX_FLAGS) $(CXX_USE_PCH) /c $< @@ -392,6 +397,13 @@ {$(ALTSRC)\os_cpu\windows_$(Platform_arch)\vm}.cpp.obj:: $(CXX) $(CXX_FLAGS) $(CXX_USE_PCH) /c $< +{$(ALTSRC)\share\vm\jfr}.cpp.obj:: + $(CXX) $(CXX_FLAGS) $(CXX_USE_PCH) /c $< + +{$(ALTSRC)\share\vm\jfr\buffers}.cpp.obj:: + $(CXX) $(CXX_FLAGS) $(CXX_USE_PCH) /c $< +!endif + {..\generated\incls}.cpp.obj:: $(CXX) $(CXX_FLAGS) $(CXX_USE_PCH) /c $< @@ -404,12 +416,6 @@ {..\generated\tracefiles}.cpp.obj:: $(CXX) $(CXX_FLAGS) $(CXX_USE_PCH) /c $< -{$(ALTSRC)\share\vm\jfr}.cpp.obj:: - $(CXX) $(CXX_FLAGS) $(CXX_USE_PCH) /c $< - -{$(ALTSRC)\share\vm\jfr\buffers}.cpp.obj:: - $(CXX) $(CXX_FLAGS) $(CXX_USE_PCH) /c $< - default:: _build_pch_file.obj:
--- a/hotspot/src/cpu/aarch64/vm/sharedRuntime_aarch64.cpp Mon Apr 04 13:40:18 2016 -0700 +++ b/hotspot/src/cpu/aarch64/vm/sharedRuntime_aarch64.cpp Thu Apr 07 09:47:48 2016 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2014, 2015, Red Hat Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -31,6 +31,7 @@ #include "code/vtableStubs.hpp" #include "interpreter/interpreter.hpp" #include "interpreter/interp_masm.hpp" +#include "memory/resourceArea.hpp" #include "oops/compiledICHolder.hpp" #include "prims/jvmtiRedefineClassesTrace.hpp" #include "runtime/sharedRuntime.hpp"
--- a/hotspot/src/cpu/aarch64/vm/templateInterpreterGenerator_aarch64.cpp Mon Apr 04 13:40:18 2016 -0700 +++ b/hotspot/src/cpu/aarch64/vm/templateInterpreterGenerator_aarch64.cpp Thu Apr 07 09:47:48 2016 -0700 @@ -32,6 +32,7 @@ #include "interpreter/templateInterpreterGenerator.hpp" #include "interpreter/templateTable.hpp" #include "interpreter/bytecodeTracer.hpp" +#include "memory/resourceArea.hpp" #include "oops/arrayOop.hpp" #include "oops/methodData.hpp" #include "oops/method.hpp" @@ -1967,7 +1968,7 @@ __ push(RegSet::range(r0, r15), sp); __ mov(c_rarg2, r0); // Pass itos __ call_VM(noreg, - CAST_FROM_FN_PTR(address, SharedRuntime::trace_bytecode), + CAST_FROM_FN_PTR(address, InterpreterRuntime::trace_bytecode), c_rarg1, c_rarg2, c_rarg3); __ pop(RegSet::range(r0, r15), sp); __ pop(state);
--- a/hotspot/src/cpu/ppc/vm/methodHandles_ppc.cpp Mon Apr 04 13:40:18 2016 -0700 +++ b/hotspot/src/cpu/ppc/vm/methodHandles_ppc.cpp Thu Apr 07 09:47:48 2016 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012, 2015 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -28,6 +28,7 @@ #include "classfile/javaClasses.inline.hpp" #include "interpreter/interpreter.hpp" #include "memory/allocation.inline.hpp" +#include "memory/resourceArea.hpp" #include "prims/methodHandles.hpp" #define __ _masm->
--- a/hotspot/src/cpu/ppc/vm/runtime_ppc.cpp Mon Apr 04 13:40:18 2016 -0700 +++ b/hotspot/src/cpu/ppc/vm/runtime_ppc.cpp Thu Apr 07 09:47:48 2016 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012, 2015 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -31,6 +31,7 @@ #include "code/vmreg.hpp" #include "interpreter/interpreter.hpp" #include "interpreter/interp_masm.hpp" +#include "memory/resourceArea.hpp" #include "nativeInst_ppc.hpp" #include "opto/runtime.hpp" #include "runtime/interfaceSupport.hpp"
--- a/hotspot/src/cpu/ppc/vm/sharedRuntime_ppc.cpp Mon Apr 04 13:40:18 2016 -0700 +++ b/hotspot/src/cpu/ppc/vm/sharedRuntime_ppc.cpp Thu Apr 07 09:47:48 2016 -0700 @@ -31,6 +31,7 @@ #include "frame_ppc.hpp" #include "interpreter/interpreter.hpp" #include "interpreter/interp_masm.hpp" +#include "memory/resourceArea.hpp" #include "oops/compiledICHolder.hpp" #include "prims/jvmtiRedefineClassesTrace.hpp" #include "runtime/sharedRuntime.hpp"
--- a/hotspot/src/cpu/ppc/vm/templateInterpreterGenerator_ppc.cpp Mon Apr 04 13:40:18 2016 -0700 +++ b/hotspot/src/cpu/ppc/vm/templateInterpreterGenerator_ppc.cpp Thu Apr 07 09:47:48 2016 -0700 @@ -2211,7 +2211,7 @@ __ ld(R6_ARG4, tsize*Interpreter::stackElementSize, R15_esp); __ ld(R5_ARG3, Interpreter::stackElementSize, R15_esp); __ mflr(R31); - __ call_VM(noreg, CAST_FROM_FN_PTR(address, SharedRuntime::trace_bytecode), /* unused */ R4_ARG2, R5_ARG3, R6_ARG4, false); + __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::trace_bytecode), /* unused */ R4_ARG2, R5_ARG3, R6_ARG4, false); __ mtlr(R31); __ pop(state);
--- a/hotspot/src/cpu/sparc/vm/methodHandles_sparc.cpp Mon Apr 04 13:40:18 2016 -0700 +++ b/hotspot/src/cpu/sparc/vm/methodHandles_sparc.cpp Thu Apr 07 09:47:48 2016 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,6 +28,7 @@ #include "interpreter/interpreter.hpp" #include "interpreter/interp_masm.hpp" #include "memory/allocation.inline.hpp" +#include "memory/resourceArea.hpp" #include "prims/methodHandles.hpp" #define __ _masm->
--- a/hotspot/src/cpu/sparc/vm/runtime_sparc.cpp Mon Apr 04 13:40:18 2016 -0700 +++ b/hotspot/src/cpu/sparc/vm/runtime_sparc.cpp Thu Apr 07 09:47:48 2016 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,6 +28,7 @@ #include "classfile/systemDictionary.hpp" #include "code/vmreg.hpp" #include "interpreter/interpreter.hpp" +#include "memory/resourceArea.hpp" #include "nativeInst_sparc.hpp" #include "opto/runtime.hpp" #include "runtime/interfaceSupport.hpp"
--- a/hotspot/src/cpu/sparc/vm/sharedRuntime_sparc.cpp Mon Apr 04 13:40:18 2016 -0700 +++ b/hotspot/src/cpu/sparc/vm/sharedRuntime_sparc.cpp Thu Apr 07 09:47:48 2016 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,6 +28,7 @@ #include "code/icBuffer.hpp" #include "code/vtableStubs.hpp" #include "interpreter/interpreter.hpp" +#include "memory/resourceArea.hpp" #include "oops/compiledICHolder.hpp" #include "prims/jvmtiRedefineClassesTrace.hpp" #include "runtime/sharedRuntime.hpp"
--- a/hotspot/src/cpu/sparc/vm/templateInterpreterGenerator_sparc.cpp Mon Apr 04 13:40:18 2016 -0700 +++ b/hotspot/src/cpu/sparc/vm/templateInterpreterGenerator_sparc.cpp Thu Apr 07 09:47:48 2016 -0700 @@ -1966,7 +1966,7 @@ // Pass a 0 (not used in sparc) and the top of stack to the bytecode tracer __ mov( Otos_l2, G3_scratch ); - __ call_VM(noreg, CAST_FROM_FN_PTR(address, SharedRuntime::trace_bytecode), G0, Otos_l1, G3_scratch); + __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::trace_bytecode), G0, Otos_l1, G3_scratch); __ mov(Lscratch, O7); // restore return address __ pop(state); __ retl();
--- a/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp Mon Apr 04 13:40:18 2016 -0700 +++ b/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp Thu Apr 07 09:47:48 2016 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2016, 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 @@ -312,7 +312,7 @@ Register OSR_buf = osrBufferPointer()->as_pointer_register(); { assert(frame::interpreter_frame_monitor_size() == BasicObjectLock::size(), "adjust code below"); int monitor_offset = BytesPerWord * method()->max_locals() + - (2 * BytesPerWord) * (number_of_locks - 1); + (BasicObjectLock::size() * BytesPerWord) * (number_of_locks - 1); // SharedRuntime::OSR_migration_begin() packs BasicObjectLocks in // the OSR buffer using 2 word entries: first the lock and then // the oop.
--- a/hotspot/src/cpu/x86/vm/frame_x86.hpp Mon Apr 04 13:40:18 2016 -0700 +++ b/hotspot/src/cpu/x86/vm/frame_x86.hpp Thu Apr 07 09:47:48 2016 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -54,44 +54,6 @@ // <- sender sp // ------------------------------ Asm interpreter ---------------------------------------- -// ------------------------------ C++ interpreter ---------------------------------------- -// -// Layout of C++ interpreter frame: (While executing in BytecodeInterpreter::run) -// -// <- SP (current esp/rsp) -// [local variables ] BytecodeInterpreter::run local variables -// ... BytecodeInterpreter::run local variables -// [local variables ] BytecodeInterpreter::run local variables -// [old frame pointer ] fp [ BytecodeInterpreter::run's ebp/rbp ] -// [return pc ] (return to frame manager) -// [interpreter_state* ] (arg to BytecodeInterpreter::run) -------------- -// [expression stack ] <- last_Java_sp | -// [... ] * <- interpreter_state.stack | -// [expression stack ] * <- interpreter_state.stack_base | -// [monitors ] \ | -// ... | monitor block size | -// [monitors ] / <- interpreter_state.monitor_base | -// [struct interpretState ] <-----------------------------------------| -// [return pc ] (return to callee of frame manager [1] -// [locals and parameters ] -// <- sender sp - -// [1] When the C++ interpreter calls a new method it returns to the frame -// manager which allocates a new frame on the stack. In that case there -// is no real callee of this newly allocated frame. The frame manager is -// aware of the additional frame(s) and will pop them as nested calls -// complete. However, to make it look good in the debugger the frame -// manager actually installs a dummy pc pointing to RecursiveInterpreterActivation -// with a fake interpreter_state* parameter to make it easy to debug -// nested calls. - -// Note that contrary to the layout for the assembly interpreter the -// expression stack allocated for the C++ interpreter is full sized. -// However this is not as bad as it seems as the interpreter frame_manager -// will truncate the unused space on successive method calls. -// -// ------------------------------ C++ interpreter ---------------------------------------- - public: enum { pc_return_offset = 0,
--- a/hotspot/src/cpu/x86/vm/interp_masm_x86.cpp Mon Apr 04 13:40:18 2016 -0700 +++ b/hotspot/src/cpu/x86/vm/interp_masm_x86.cpp Thu Apr 07 09:47:48 2016 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, 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 @@ -296,7 +296,7 @@ Label L; cmpptr(Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize), (int32_t)NULL_WORD); jcc(Assembler::equal, L); - stop("InterpreterMacroAssembler::call_VM_leaf_base:" + stop("InterpreterMacroAssembler::call_VM_base:" " last_sp != NULL"); bind(L); } @@ -1099,7 +1099,7 @@ movptr(Address(lock_reg, mark_offset), swap_reg); assert(lock_offset == 0, - "displached header must be first word in BasicObjectLock"); + "displaced header must be first word in BasicObjectLock"); if (os::is_MP()) lock(); cmpxchgptr(lock_reg, Address(obj_reg, 0)); @@ -1154,7 +1154,7 @@ // Kills: // rax // c_rarg0, c_rarg1, c_rarg2, c_rarg3, ... (param regs) -// rscratch1, rscratch2 (scratch regs) +// rscratch1 (scratch reg) // rax, rbx, rcx, rdx void InterpreterMacroAssembler::unlock_object(Register lock_reg) { assert(lock_reg == LP64_ONLY(c_rarg1) NOT_LP64(rdx), @@ -1201,7 +1201,7 @@ if (os::is_MP()) lock(); cmpxchgptr(header_reg, Address(obj_reg, 0)); - // zero for recursive case + // zero for simple unlock of a stack-lock case jcc(Assembler::zero, done); // Call the runtime routine for slow case.
--- a/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp Mon Apr 04 13:40:18 2016 -0700 +++ b/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp Thu Apr 07 09:47:48 2016 -0700 @@ -1106,7 +1106,7 @@ assert_different_registers(lock_reg, obj_reg, swap_reg, tmp_reg); assert(markOopDesc::age_shift == markOopDesc::lock_bits + markOopDesc::biased_lock_bits, "biased locking makes assumptions about bit layout"); Address mark_addr (obj_reg, oopDesc::mark_offset_in_bytes()); - Address saved_mark_addr(lock_reg, 0); + NOT_LP64( Address saved_mark_addr(lock_reg, 0); ) if (PrintBiasedLockingStatistics && counters == NULL) { counters = BiasedLocking::counters(); @@ -1695,7 +1695,7 @@ RTMLockingCounters* stack_rtm_counters, Metadata* method_data, bool use_rtm, bool profile_rtm) { - // Ensure the register assignents are disjoint + // Ensure the register assignments are disjoint assert(tmpReg == rax, ""); if (use_rtm) { @@ -2194,8 +2194,8 @@ cmpptr(Address(tmpReg, OM_OFFSET_NO_MONITOR_VALUE_TAG(succ)), (int32_t)NULL_WORD); jccb (Assembler::zero, LGoSlowPath); + xorptr(boxReg, boxReg); if ((EmitSync & 16) && os::is_MP()) { - orptr(boxReg, boxReg); xchgptr(boxReg, Address(tmpReg, OM_OFFSET_NO_MONITOR_VALUE_TAG(owner))); } else { movptr(Address(tmpReg, OM_OFFSET_NO_MONITOR_VALUE_TAG(owner)), (int32_t)NULL_WORD); @@ -2227,7 +2227,6 @@ // box is really RAX -- the following CMPXCHG depends on that binding // cmpxchg R,[M] is equivalent to rax = CAS(M,rax,R) - movptr(boxReg, (int32_t)NULL_WORD); if (os::is_MP()) { lock(); } cmpxchgptr(r15_thread, Address(tmpReg, OM_OFFSET_NO_MONITOR_VALUE_TAG(owner))); // There's no successor so we tried to regrab the lock.
--- a/hotspot/src/cpu/x86/vm/methodHandles_x86.cpp Mon Apr 04 13:40:18 2016 -0700 +++ b/hotspot/src/cpu/x86/vm/methodHandles_x86.cpp Thu Apr 07 09:47:48 2016 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,6 +28,7 @@ #include "interpreter/interpreter.hpp" #include "interpreter/interpreterRuntime.hpp" #include "memory/allocation.inline.hpp" +#include "memory/resourceArea.hpp" #include "prims/methodHandles.hpp" #define __ _masm->
--- a/hotspot/src/cpu/x86/vm/runtime_x86_32.cpp Mon Apr 04 13:40:18 2016 -0700 +++ b/hotspot/src/cpu/x86/vm/runtime_x86_32.cpp Thu Apr 07 09:47:48 2016 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,6 +29,7 @@ #include "classfile/systemDictionary.hpp" #include "code/vmreg.hpp" #include "interpreter/interpreter.hpp" +#include "memory/resourceArea.hpp" #include "opto/runtime.hpp" #include "runtime/interfaceSupport.hpp" #include "runtime/sharedRuntime.hpp"
--- a/hotspot/src/cpu/x86/vm/sharedRuntime_x86_32.cpp Mon Apr 04 13:40:18 2016 -0700 +++ b/hotspot/src/cpu/x86/vm/sharedRuntime_x86_32.cpp Thu Apr 07 09:47:48 2016 -0700 @@ -29,6 +29,7 @@ #include "code/icBuffer.hpp" #include "code/vtableStubs.hpp" #include "interpreter/interpreter.hpp" +#include "memory/resourceArea.hpp" #include "oops/compiledICHolder.hpp" #include "prims/jvmtiRedefineClassesTrace.hpp" #include "runtime/sharedRuntime.hpp"
--- a/hotspot/src/cpu/x86/vm/sharedRuntime_x86_64.cpp Mon Apr 04 13:40:18 2016 -0700 +++ b/hotspot/src/cpu/x86/vm/sharedRuntime_x86_64.cpp Thu Apr 07 09:47:48 2016 -0700 @@ -32,6 +32,7 @@ #include "code/icBuffer.hpp" #include "code/vtableStubs.hpp" #include "interpreter/interpreter.hpp" +#include "memory/resourceArea.hpp" #include "oops/compiledICHolder.hpp" #include "prims/jvmtiRedefineClassesTrace.hpp" #include "runtime/sharedRuntime.hpp"
--- a/hotspot/src/cpu/x86/vm/templateInterpreterGenerator_x86.cpp Mon Apr 04 13:40:18 2016 -0700 +++ b/hotspot/src/cpu/x86/vm/templateInterpreterGenerator_x86.cpp Thu Apr 07 09:47:48 2016 -0700 @@ -1830,7 +1830,7 @@ __ push(state); // save tosca // pass tosca registers as arguments & call tracer - __ call_VM(noreg, CAST_FROM_FN_PTR(address, SharedRuntime::trace_bytecode), rcx, rax, rdx); + __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::trace_bytecode), rcx, rax, rdx); __ mov(rcx, rax); // make sure return address is not destroyed by pop(state) __ pop(state); // restore tosca @@ -1847,7 +1847,7 @@ __ movflt(xmm3, xmm0); // Pass ftos #endif __ call_VM(noreg, - CAST_FROM_FN_PTR(address, SharedRuntime::trace_bytecode), + CAST_FROM_FN_PTR(address, InterpreterRuntime::trace_bytecode), c_rarg1, c_rarg2, c_rarg3); __ pop(c_rarg3); __ pop(c_rarg2);
--- a/hotspot/src/cpu/zero/vm/methodHandles_zero.cpp Mon Apr 04 13:40:18 2016 -0700 +++ b/hotspot/src/cpu/zero/vm/methodHandles_zero.cpp Thu Apr 07 09:47:48 2016 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * Copyright 2009, 2010, 2011 Red Hat, Inc. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -27,6 +27,7 @@ #include "interpreter/cppInterpreterGenerator.hpp" #include "interpreter/interpreter.hpp" #include "memory/allocation.inline.hpp" +#include "memory/resourceArea.hpp" #include "oops/oop.inline.hpp" #include "prims/methodHandles.hpp"
--- a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/CommandProcessor.java Mon Apr 04 13:40:18 2016 -0700 +++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/CommandProcessor.java Thu Apr 07 09:47:48 2016 -0700 @@ -549,11 +549,9 @@ }, new Command("buildreplayjars", "buildreplayjars [ all | app | boot ] | [ prefix ]", false) { // This is used to dump jar files of all the classes - // loaded in the core. Everything on the bootclasspath + // loaded in the core. Everything with null classloader // will go in boot.jar and everything else will go in - // app.jar. Then the classes can be loaded by the replay - // jvm using -Xbootclasspath/p:boot.jar -cp app.jar. boot.jar usually - // not needed, unless changed by jvmti. + // app.jar. boot.jar usually not needed, unless changed by jvmti. public void doit(Tokens t) { int tcount = t.countTokens(); if (tcount > 2) {
--- a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/SAGetopt.java Mon Apr 04 13:40:18 2016 -0700 +++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/SAGetopt.java Thu Apr 07 09:47:48 2016 -0700 @@ -84,7 +84,11 @@ } else { // Mixed style options --file name - extractOptarg(ca[0]); + try { + extractOptarg(ca[0]); + } catch (ArrayIndexOutOfBoundsException e) { + throw new RuntimeException("Argument is expected for '" + ca[0] + "'"); + } } return ca[0];
--- a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/SALauncher.java Mon Apr 04 13:40:18 2016 -0700 +++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/SALauncher.java Thu Apr 07 09:47:48 2016 -0700 @@ -30,6 +30,7 @@ import sun.jvm.hotspot.tools.JStack; import sun.jvm.hotspot.tools.JMap; import sun.jvm.hotspot.tools.JInfo; +import sun.jvm.hotspot.tools.JSnap; public class SALauncher { @@ -39,6 +40,7 @@ System.out.println(" jstack --help\tto get more information"); System.out.println(" jmap --help\tto get more information"); System.out.println(" jinfo --help\tto get more information"); + System.out.println(" jsnap --help\tto get more information"); return false; } @@ -85,6 +87,11 @@ return commonHelp(); } + private static boolean jsnapHelp() { + System.out.println(" --all\tto print all performance counters"); + return commonHelp(); + } + private static boolean toolHelp(String toolName) { if (toolName.equals("jstack")) { return jstackHelp(); @@ -95,24 +102,62 @@ if (toolName.equals("jmap")) { return jmapHelp(); } + if (toolName.equals("jsnap")) { + return jsnapHelp(); + } if (toolName.equals("hsdb") || toolName.equals("clhsdb")) { return commonHelp(); } return launcherHelp(); } + private static void buildAttachArgs(ArrayList<String> newArgs, + String pid, String exe, String core) { + if ((pid == null) && (exe == null)) { + throw new IllegalArgumentException( + "You have to set --pid or --exe."); + } + + if (pid != null) { // Attach to live process + if (exe != null) { + throw new IllegalArgumentException( + "Unnecessary argument: --exe"); + } else if (core != null) { + throw new IllegalArgumentException( + "Unnecessary argument: --core"); + } else if (!pid.matches("^\\d+$")) { + throw new IllegalArgumentException("Invalid pid: " + pid); + } + + newArgs.add(pid); + } else { + if (exe.length() == 0) { + throw new IllegalArgumentException("You have to set --exe."); + } + + newArgs.add(exe); + + if ((core == null) || (core.length() == 0)) { + throw new IllegalArgumentException("You have to set --core."); + } + + newArgs.add(core); + } + } + private static void runCLHSDB(String[] oldArgs) { SAGetopt sg = new SAGetopt(oldArgs); String[] longOpts = {"exe=", "core=", "pid="}; ArrayList<String> newArgs = new ArrayList(); - String exeORpid = null; + String pid = null; + String exe = null; String core = null; String s = null; while((s = sg.next(null, longOpts)) != null) { if (s.equals("exe")) { - exeORpid = sg.getOptarg(); + exe = sg.getOptarg(); continue; } if (s.equals("core")) { @@ -120,17 +165,12 @@ continue; } if (s.equals("pid")) { - exeORpid = sg.getOptarg(); + pid = sg.getOptarg(); continue; } } - if (exeORpid != null) { - newArgs.add(exeORpid); - if (core != null) { - newArgs.add(core); - } - } + buildAttachArgs(newArgs, pid, exe, core); CLHSDB.main(newArgs.toArray(new String[newArgs.size()])); } @@ -139,13 +179,14 @@ String[] longOpts = {"exe=", "core=", "pid="}; ArrayList<String> newArgs = new ArrayList(); - String exeORpid = null; + String pid = null; + String exe = null; String core = null; String s = null; while((s = sg.next(null, longOpts)) != null) { if (s.equals("exe")) { - exeORpid = sg.getOptarg(); + exe = sg.getOptarg(); continue; } if (s.equals("core")) { @@ -153,17 +194,12 @@ continue; } if (s.equals("pid")) { - exeORpid = sg.getOptarg(); + pid = sg.getOptarg(); continue; } } - if (exeORpid != null) { - newArgs.add(exeORpid); - if (core != null) { - newArgs.add(core); - } - } + buildAttachArgs(newArgs, pid, exe, core); HSDB.main(newArgs.toArray(new String[newArgs.size()])); } @@ -173,13 +209,14 @@ "mixed", "locks"}; ArrayList<String> newArgs = new ArrayList(); - String exeORpid = null; + String pid = null; + String exe = null; String core = null; String s = null; while((s = sg.next(null, longOpts)) != null) { if (s.equals("exe")) { - exeORpid = sg.getOptarg(); + exe = sg.getOptarg(); continue; } if (s.equals("core")) { @@ -187,7 +224,7 @@ continue; } if (s.equals("pid")) { - exeORpid = sg.getOptarg(); + pid = sg.getOptarg(); continue; } if (s.equals("mixed")) { @@ -200,13 +237,7 @@ } } - if (exeORpid != null) { - newArgs.add(exeORpid); - if (core != null) { - newArgs.add(core); - } - } - + buildAttachArgs(newArgs, pid, exe, core); JStack.main(newArgs.toArray(new String[newArgs.size()])); } @@ -216,13 +247,14 @@ "heap", "binaryheap", "histo", "clstats", "finalizerinfo"}; ArrayList<String> newArgs = new ArrayList(); - String exeORpid = null; + String pid = null; + String exe = null; String core = null; String s = null; while((s = sg.next(null, longOpts)) != null) { if (s.equals("exe")) { - exeORpid = sg.getOptarg(); + exe = sg.getOptarg(); continue; } if (s.equals("core")) { @@ -230,7 +262,7 @@ continue; } if (s.equals("pid")) { - exeORpid = sg.getOptarg(); + pid = sg.getOptarg(); continue; } if (s.equals("heap")) { @@ -255,13 +287,7 @@ } } - if (exeORpid != null) { - newArgs.add(exeORpid); - if (core != null) { - newArgs.add(core); - } - } - + buildAttachArgs(newArgs, pid, exe, core); JMap.main(newArgs.toArray(new String[newArgs.size()])); } @@ -271,13 +297,14 @@ "flags", "sysprops"}; ArrayList<String> newArgs = new ArrayList(); - String exeORpid = null; + String exe = null; + String pid = null; String core = null; String s = null; while((s = sg.next(null, longOpts)) != null) { if (s.equals("exe")) { - exeORpid = sg.getOptarg(); + exe = sg.getOptarg(); continue; } if (s.equals("core")) { @@ -285,7 +312,7 @@ continue; } if (s.equals("pid")) { - exeORpid = sg.getOptarg(); + pid = sg.getOptarg(); continue; } if (s.equals("flags")) { @@ -298,14 +325,41 @@ } } - if (exeORpid != null) { - newArgs.add(exeORpid); - if (core != null) { - newArgs.add(core); + buildAttachArgs(newArgs, pid, exe, core); + JInfo.main(newArgs.toArray(new String[newArgs.size()])); + } + + private static void runJSNAP(String[] oldArgs) { + SAGetopt sg = new SAGetopt(oldArgs); + String[] longOpts = {"exe=", "core=", "pid=", "all"}; + + ArrayList<String> newArgs = new ArrayList(); + String exe = null; + String pid = null; + String core = null; + String s = null; + + while((s = sg.next(null, longOpts)) != null) { + if (s.equals("exe")) { + exe = sg.getOptarg(); + continue; + } + if (s.equals("core")) { + core = sg.getOptarg(); + continue; + } + if (s.equals("pid")) { + pid = sg.getOptarg(); + continue; + } + if (s.equals("all")) { + newArgs.add("-a"); + continue; } } - JInfo.main(newArgs.toArray(new String[newArgs.size()])); + buildAttachArgs(newArgs, pid, exe, core); + JSnap.main(newArgs.toArray(new String[newArgs.size()])); } public static void main(String[] args) { @@ -329,31 +383,43 @@ String[] oldArgs = Arrays.copyOfRange(args, 1, args.length); - // Run SA interactive mode - if (args[0].equals("clhsdb")) { - runCLHSDB(oldArgs); - return; - } + try { + // Run SA interactive mode + if (args[0].equals("clhsdb")) { + runCLHSDB(oldArgs); + return; + } - if (args[0].equals("hsdb")) { - runHSDB(oldArgs); - return; - } + if (args[0].equals("hsdb")) { + runHSDB(oldArgs); + return; + } + + // Run SA tmtools mode + if (args[0].equals("jstack")) { + runJSTACK(oldArgs); + return; + } - // Run SA tmtools mode - if (args[0].equals("jstack")) { - runJSTACK(oldArgs); - return; - } + if (args[0].equals("jmap")) { + runJMAP(oldArgs); + return; + } + + if (args[0].equals("jinfo")) { + runJINFO(oldArgs); + return; + } - if (args[0].equals("jmap")) { - runJMAP(oldArgs); - return; - } + if (args[0].equals("jsnap")) { + runJSNAP(oldArgs); + return; + } - if (args[0].equals("jinfo")) { - runJINFO(oldArgs); - return; + throw new IllegalArgumentException("Unknown tool: " + args[0]); + } catch (Exception e) { + System.err.println(e.getMessage()); + toolHelp(args[0]); } } }
--- a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/shared/GCCause.java Mon Apr 04 13:40:18 2016 -0700 +++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/shared/GCCause.java Thu Apr 07 09:47:48 2016 -0700 @@ -35,6 +35,11 @@ _gc_locker ("GCLocker Initiated GC"), _heap_inspection ("Heap Inspection Initiated GC"), _heap_dump ("Heap Dump Initiated GC"), + _wb_young_gc ("WhiteBox Initiated Young GC"), + _wb_conc_mark ("WhiteBox Initiated Concurrent Mark"), + _wb_full_gc ("WhiteBox Initiated Full GC"), + _update_allocation_context_stats_inc ("Update Allocation Context Stats"), + _update_allocation_context_stats_full ("Update Allocation Context Stats"), _no_gc ("No GC"), _no_cause_specified ("Unknown GCCause"), @@ -42,6 +47,7 @@ _tenured_generation_full ("Tenured Generation Full"), _metadata_GC_threshold ("Metadata GC Threshold"), + _metadata_GC_clear_soft_refs ("Metadata GC Clear Soft References"), _cms_generation_full ("CMS Generation Full"), _cms_initial_mark ("CMS Initial Mark"), @@ -55,7 +61,8 @@ _g1_inc_collection_pause ("G1 Evacuation Pause"), _g1_humongous_allocation ("G1 Humongous Allocation"), - _last_ditch_collection ("Last ditch collection"), + _dcmd_gc_run ("Diagnostic Command"), + _last_gc_cause ("ILLEGAL VALUE - last gc cause - ILLEGAL VALUE"); private final String value;
--- a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/jdi/VirtualMachineImpl.java Mon Apr 04 13:40:18 2016 -0700 +++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/jdi/VirtualMachineImpl.java Thu Apr 07 09:47:48 2016 -0700 @@ -780,8 +780,8 @@ return getPath("java.class.path"); } - public List bootClassPath() { - return getPath("sun.boot.class.path"); + public List<String> bootClassPath() { + return Collections.emptyList(); } public String baseDirectory() {
--- a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/Threads.java Mon Apr 04 13:40:18 2016 -0700 +++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/Threads.java Thu Apr 07 09:47:48 2016 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2016, 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 @@ -130,7 +130,7 @@ virtualConstructor.addMapping("CodeCacheSweeperThread", CodeCacheSweeperThread.class); } // for now, use JavaThread itself. fix it later with appropriate class if needed - virtualConstructor.addMapping("SurrogateLockerThread", JavaThread.class); + virtualConstructor.addMapping("ReferencePendingListLockerThread", JavaThread.class); virtualConstructor.addMapping("JvmtiAgentThread", JvmtiAgentThread.class); virtualConstructor.addMapping("ServiceThread", ServiceThread.class); } @@ -172,7 +172,7 @@ return thread; } catch (Exception e) { throw new RuntimeException("Unable to deduce type of thread from address " + threadAddr + - " (expected type JavaThread, CompilerThread, ServiceThread, JvmtiAgentThread, SurrogateLockerThread, or CodeCacheSweeperThread)", e); + " (expected type JavaThread, CompilerThread, ServiceThread, JvmtiAgentThread, ReferencePendingListLockerThread, or CodeCacheSweeperThread)", e); } }
--- a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/JSnap.java Mon Apr 04 13:40:18 2016 -0700 +++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/JSnap.java Thu Apr 07 09:47:48 2016 -0700 @@ -25,11 +25,15 @@ package sun.jvm.hotspot.tools; import java.io.*; +import java.util.*; +import java.util.stream.*; import sun.jvm.hotspot.debugger.JVMDebugger; import sun.jvm.hotspot.runtime.*; public class JSnap extends Tool { + private boolean all; + public JSnap() { super(); } @@ -45,7 +49,7 @@ if (prologue.accessible()) { PerfMemory.iterate(new PerfMemory.PerfDataEntryVisitor() { public boolean visit(PerfDataEntry pde) { - if (pde.supported()) { + if (all || pde.supported()) { out.print(pde.name()); out.print('='); out.println(pde.valueAsString()); @@ -62,8 +66,24 @@ } } + @Override + protected void printFlagsUsage() { + System.out.println(" -a\tto print all performance counters"); + super.printFlagsUsage(); + } + public static void main(String[] args) { JSnap js = new JSnap(); + js.all = Arrays.stream(args) + .anyMatch(s -> s.equals("-a")); + + if (js.all) { + args = Arrays.stream(args) + .filter(s -> !s.equals("-a")) + .collect(Collectors.toList()) + .toArray(new String[0]); + } + js.execute(args); } }
--- a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/CompactHashTable.java Mon Apr 04 13:40:18 2016 -0700 +++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/CompactHashTable.java Thu Apr 07 09:47:48 2016 -0700 @@ -81,6 +81,12 @@ } public Symbol probe(byte[] name, long hash) { + + if (bucketCount() == 0) { + // The table is invalid, so don't try to lookup + return null; + } + long symOffset; Symbol sym; Address baseAddress = baseAddressField.getValue(addr);
--- a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/soql/JSJavaVM.java Mon Apr 04 13:40:18 2016 -0700 +++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/soql/JSJavaVM.java Thu Apr 07 09:47:48 2016 -0700 @@ -75,8 +75,6 @@ return vm.getVMRelease(); case FIELD_CLASS_PATH: return getClassPath(); - case FIELD_BOOT_CLASS_PATH: - return getBootClassPath(); case FIELD_USER_DIR: return getUserDir(); case FIELD_UNDEFINED: @@ -143,7 +141,6 @@ addField("type", FIELD_TYPE); addField("version", FIELD_VERSION); addField("classPath", FIELD_CLASS_PATH); - addField("bootClassPath", FIELD_BOOT_CLASS_PATH); addField("userDir", FIELD_USER_DIR); } @@ -217,10 +214,6 @@ return vm.getSystemProperty("java.class.path"); } - private String getBootClassPath() { - return vm.getSystemProperty("sun.boot.class.path"); - } - private String getUserDir() { return vm.getSystemProperty("user.dir"); }
--- a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/soql/sa.js Mon Apr 04 13:40:18 2016 -0700 +++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/soql/sa.js Thu Apr 07 09:47:48 2016 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2016, 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 @@ -837,7 +837,7 @@ vmType2Class["JavaThread"] = sapkg.runtime.JavaThread; vmType2Class["CompilerThread"] = sapkg.runtime.CompilerThread; vmType2Class["CodeCacheSweeperThread"] = sapkg.runtime.CodeCacheSweeperThread; -vmType2Class["SurrogateLockerThread"] = sapkg.runtime.JavaThread; +vmType2Class["ReferencePendingListLockerThread"] = sapkg.runtime.JavaThread; vmType2Class["DebuggerThread"] = sapkg.runtime.DebuggerThread; // gc
--- a/hotspot/src/os/aix/vm/os_aix.cpp Mon Apr 04 13:40:18 2016 -0700 +++ b/hotspot/src/os/aix/vm/os_aix.cpp Thu Apr 07 09:47:48 2016 -0700 @@ -910,8 +910,8 @@ log_info(os, thread)("Thread started (pthread id: " UINTX_FORMAT ", attributes: %s). ", (uintx) tid, os::Posix::describe_pthread_attr(buf, sizeof(buf), &attr)); } else { - log_warning(os, thread)("Failed to start thread - pthread_create failed (%s) for attributes: %s.", - strerror(ret), os::Posix::describe_pthread_attr(buf, sizeof(buf), &attr)); + log_warning(os, thread)("Failed to start thread - pthread_create failed (%d=%s) for attributes: %s.", + ret, os::errno_name(ret), os::Posix::describe_pthread_attr(buf, sizeof(buf), &attr)); } pthread_attr_destroy(&attr); @@ -1178,7 +1178,7 @@ size_t os::lasterror(char *buf, size_t len) { if (errno == 0) return 0; - const char *s = ::strerror(errno); + const char *s = os::strerror(errno); size_t n = ::strlen(s); if (n >= len) { n = len - 1; @@ -1714,14 +1714,14 @@ if (os::Aix::on_aix()) { int rc = ::sem_post(&sig_sem); if (rc == -1 && !warn_only_once) { - trcVerbose("sem_post failed (errno = %d, %s)", errno, strerror(errno)); + trcVerbose("sem_post failed (errno = %d, %s)", errno, os::errno_name(errno)); warn_only_once = true; } } else { guarantee0(p_sig_msem != NULL); int rc = ::msem_unlock(p_sig_msem, 0); if (rc == -1 && !warn_only_once) { - trcVerbose("msem_unlock failed (errno = %d, %s)", errno, strerror(errno)); + trcVerbose("msem_unlock failed (errno = %d, %s)", errno, os::errno_name(errno)); warn_only_once = true; } } @@ -1732,14 +1732,14 @@ if (os::Aix::on_aix()) { int rc = ::sem_wait(&sig_sem); if (rc == -1 && !warn_only_once) { - trcVerbose("sem_wait failed (errno = %d, %s)", errno, strerror(errno)); + trcVerbose("sem_wait failed (errno = %d, %s)", errno, os::errno_name(errno)); warn_only_once = true; } } else { guarantee0(p_sig_msem != NULL); // must init before use int rc = ::msem_lock(p_sig_msem, 0); if (rc == -1 && !warn_only_once) { - trcVerbose("msem_lock failed (errno = %d, %s)", errno, strerror(errno)); + trcVerbose("msem_lock failed (errno = %d, %s)", errno, os::errno_name(errno)); warn_only_once = true; } } @@ -2203,7 +2203,7 @@ int err) { warning("INFO: os::commit_memory(" PTR_FORMAT ", " SIZE_FORMAT ", %d) failed; error='%s' (errno=%d)", addr, size, exec, - strerror(err), err); + os::errno_name(err), err); } #endif @@ -2412,7 +2412,7 @@ bool rc = ::mprotect(addr, size, prot) == 0 ? true : false; if (!rc) { - const char* const s_errno = strerror(errno); + const char* const s_errno = os::errno_name(errno); warning("mprotect(" PTR_FORMAT "-" PTR_FORMAT ", 0x%X) failed (%s).", addr, addr + size, prot, s_errno); return false; } @@ -2634,7 +2634,7 @@ if (ret != 0) { trcVerbose("Could not change priority for thread %d to %d (error %d, %s)", - (int)thr, newpri, ret, strerror(ret)); + (int)thr, newpri, ret, os::errno_name(ret)); } return (ret == 0) ? OS_OK : OS_ERR; }
--- a/hotspot/src/os/aix/vm/perfMemory_aix.cpp Mon Apr 04 13:40:18 2016 -0700 +++ b/hotspot/src/os/aix/vm/perfMemory_aix.cpp Thu Apr 07 09:47:48 2016 -0700 @@ -30,6 +30,7 @@ #include "oops/oop.inline.hpp" #include "os_aix.inline.hpp" #include "runtime/handles.inline.hpp" +#include "runtime/os.hpp" #include "runtime/perfMemory.hpp" #include "services/memTracker.hpp" #include "utilities/exceptions.hpp" @@ -101,7 +102,7 @@ if (result == OS_ERR) { if (PrintMiscellaneous && Verbose) { warning("Could not create Perfdata save file: %s: %s\n", - destfile, strerror(errno)); + destfile, os::strerror(errno)); } } else { int fd = result; @@ -112,7 +113,7 @@ if (result == OS_ERR) { if (PrintMiscellaneous && Verbose) { warning("Could not write Perfdata save file: %s: %s\n", - destfile, strerror(errno)); + destfile, os::strerror(errno)); } break; } @@ -124,7 +125,7 @@ result = ::close(fd); if (PrintMiscellaneous && Verbose) { if (result == OS_ERR) { - warning("Could not close %s: %s\n", destfile, strerror(errno)); + warning("Could not close %s: %s\n", destfile, os::strerror(errno)); } } } @@ -397,7 +398,7 @@ if (errno == ELOOP) { warning("directory %s is a symlink and is not secure\n", dirname); } else { - warning("could not open directory %s: %s\n", dirname, strerror(errno)); + warning("could not open directory %s: %s\n", dirname, os::strerror(errno)); } } return dirp; @@ -507,7 +508,7 @@ RESTARTABLE(::fstat(fd, &statbuf), result); if (result == OS_ERR) { if (PrintMiscellaneous && Verbose) { - warning("fstat failed on %s: %s\n", filename, strerror(errno)); + warning("fstat failed on %s: %s\n", filename, os::strerror(errno)); } return false; } @@ -543,7 +544,7 @@ if (PrintMiscellaneous && Verbose) { if (result != 0) { warning("Could not retrieve passwd entry: %s\n", - strerror(result)); + os::strerror(result)); } else if (p == NULL) { // this check is added to protect against an observed problem @@ -557,7 +558,7 @@ // Bug Id 89052 was opened with RedHat. // warning("Could not retrieve passwd entry: %s\n", - strerror(errno)); + os::strerror(errno)); } else { warning("Could not determine user name: %s\n", @@ -593,7 +594,7 @@ "Process not found"); } else /* EPERM */ { - THROW_MSG_0(vmSymbols::java_io_IOException(), strerror(errno)); + THROW_MSG_0(vmSymbols::java_io_IOException(), os::strerror(errno)); } } @@ -746,7 +747,7 @@ if (PrintMiscellaneous && Verbose && result == OS_ERR) { if (errno != ENOENT) { warning("Could not unlink shared memory backing" - " store file %s : %s\n", path, strerror(errno)); + " store file %s : %s\n", path, os::strerror(errno)); } } } @@ -849,7 +850,7 @@ // if (PrintMiscellaneous && Verbose) { warning("could not create directory %s: %s\n", - dirname, strerror(errno)); + dirname, os::strerror(errno)); } return false; } @@ -900,7 +901,7 @@ if (errno == ELOOP) { warning("file %s is a symlink and is not secure\n", filename); } else { - warning("could not create file %s: %s\n", filename, strerror(errno)); + warning("could not create file %s: %s\n", filename, os::strerror(errno)); } } // Close the directory and reset the current working directory. @@ -924,7 +925,7 @@ RESTARTABLE(::ftruncate(fd, (off_t)0), result); if (result == OS_ERR) { if (PrintMiscellaneous && Verbose) { - warning("could not truncate shared memory file: %s\n", strerror(errno)); + warning("could not truncate shared memory file: %s\n", os::strerror(errno)); } ::close(fd); return -1; @@ -933,7 +934,7 @@ RESTARTABLE(::ftruncate(fd, (off_t)size), result); if (result == OS_ERR) { if (PrintMiscellaneous && Verbose) { - warning("could not set shared memory file size: %s\n", strerror(errno)); + warning("could not set shared memory file size: %s\n", os::strerror(errno)); } ::close(fd); return -1; @@ -968,7 +969,7 @@ "Permission denied"); } else { - THROW_MSG_0(vmSymbols::java_io_IOException(), strerror(errno)); + THROW_MSG_0(vmSymbols::java_io_IOException(), os::strerror(errno)); } } int fd = result; @@ -1041,7 +1042,7 @@ if (mapAddress == MAP_FAILED) { if (PrintMiscellaneous && Verbose) { - warning("mmap failed - %s\n", strerror(errno)); + warning("mmap failed - %s\n", os::strerror(errno)); } remove_file(filename); FREE_C_HEAP_ARRAY(char, filename); @@ -1109,7 +1110,7 @@ RESTARTABLE(::fstat(fd, &statbuf), result); if (result == OS_ERR) { if (PrintMiscellaneous && Verbose) { - warning("fstat failed: %s\n", strerror(errno)); + warning("fstat failed: %s\n", os::strerror(errno)); } THROW_MSG_0(vmSymbols::java_io_IOException(), "Could not determine PerfMemory size"); @@ -1231,7 +1232,7 @@ if (mapAddress == MAP_FAILED) { if (PrintMiscellaneous && Verbose) { - warning("mmap failed: %s\n", strerror(errno)); + warning("mmap failed: %s\n", os::strerror(errno)); } THROW_MSG(vmSymbols::java_lang_OutOfMemoryError(), "Could not map PerfMemory");
--- a/hotspot/src/os/bsd/vm/os_bsd.cpp Mon Apr 04 13:40:18 2016 -0700 +++ b/hotspot/src/os/bsd/vm/os_bsd.cpp Thu Apr 07 09:47:48 2016 -0700 @@ -789,7 +789,7 @@ (uintx) tid, os::Posix::describe_pthread_attr(buf, sizeof(buf), &attr)); } else { log_warning(os, thread)("Failed to start thread - pthread_create failed (%s) for attributes: %s.", - strerror(ret), os::Posix::describe_pthread_attr(buf, sizeof(buf), &attr)); + os::errno_name(ret), os::Posix::describe_pthread_attr(buf, sizeof(buf), &attr)); } pthread_attr_destroy(&attr); @@ -1122,7 +1122,7 @@ size_t os::lasterror(char *buf, size_t len) { if (errno == 0) return 0; - const char *s = ::strerror(errno); + const char *s = os::strerror(errno); size_t n = ::strlen(s); if (n >= len) { n = len - 1; @@ -2141,7 +2141,7 @@ int err) { warning("INFO: os::commit_memory(" PTR_FORMAT ", " SIZE_FORMAT ", %d) failed; error='%s' (errno=%d)", addr, size, exec, - strerror(err), err); + os::errno_name(err), err); } // NOTE: Bsd kernel does not really reserve the pages for us. @@ -3422,7 +3422,7 @@ Bsd::set_page_size(getpagesize()); if (Bsd::page_size() == -1) { - fatal("os_bsd.cpp: os::init: sysconf failed (%s)", strerror(errno)); + fatal("os_bsd.cpp: os::init: sysconf failed (%s)", os::strerror(errno)); } init_page_sizes((size_t) Bsd::page_size());
--- a/hotspot/src/os/bsd/vm/perfMemory_bsd.cpp Mon Apr 04 13:40:18 2016 -0700 +++ b/hotspot/src/os/bsd/vm/perfMemory_bsd.cpp Thu Apr 07 09:47:48 2016 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,6 +29,7 @@ #include "oops/oop.inline.hpp" #include "os_bsd.inline.hpp" #include "runtime/handles.inline.hpp" +#include "runtime/os.hpp" #include "runtime/perfMemory.hpp" #include "services/memTracker.hpp" #include "utilities/exceptions.hpp" @@ -100,7 +101,7 @@ if (result == OS_ERR) { if (PrintMiscellaneous && Verbose) { warning("Could not create Perfdata save file: %s: %s\n", - destfile, strerror(errno)); + destfile, os::strerror(errno)); } } else { int fd = result; @@ -111,7 +112,7 @@ if (result == OS_ERR) { if (PrintMiscellaneous && Verbose) { warning("Could not write Perfdata save file: %s: %s\n", - destfile, strerror(errno)); + destfile, os::strerror(errno)); } break; } @@ -123,7 +124,7 @@ result = ::close(fd); if (PrintMiscellaneous && Verbose) { if (result == OS_ERR) { - warning("Could not close %s: %s\n", destfile, strerror(errno)); + warning("Could not close %s: %s\n", destfile, os::strerror(errno)); } } } @@ -309,7 +310,7 @@ if (errno == ELOOP) { warning("directory %s is a symlink and is not secure\n", dirname); } else { - warning("could not open directory %s: %s\n", dirname, strerror(errno)); + warning("could not open directory %s: %s\n", dirname, os::strerror(errno)); } } return dirp; @@ -420,7 +421,7 @@ RESTARTABLE(::fstat(fd, &statbuf), result); if (result == OS_ERR) { if (PrintMiscellaneous && Verbose) { - warning("fstat failed on %s: %s\n", filename, strerror(errno)); + warning("fstat failed on %s: %s\n", filename, os::strerror(errno)); } return false; } @@ -459,7 +460,7 @@ if (PrintMiscellaneous && Verbose) { if (result != 0) { warning("Could not retrieve passwd entry: %s\n", - strerror(result)); + os::strerror(result)); } else if (p == NULL) { // this check is added to protect against an observed problem @@ -473,7 +474,7 @@ // Bug Id 89052 was opened with RedHat. // warning("Could not retrieve passwd entry: %s\n", - strerror(errno)); + os::strerror(errno)); } else { warning("Could not determine user name: %s\n", @@ -509,7 +510,7 @@ "Process not found"); } else /* EPERM */ { - THROW_MSG_0(vmSymbols::java_io_IOException(), strerror(errno)); + THROW_MSG_0(vmSymbols::java_io_IOException(), os::strerror(errno)); } } @@ -652,7 +653,7 @@ if (PrintMiscellaneous && Verbose && result == OS_ERR) { if (errno != ENOENT) { warning("Could not unlink shared memory backing" - " store file %s : %s\n", path, strerror(errno)); + " store file %s : %s\n", path, os::strerror(errno)); } } } @@ -762,7 +763,7 @@ // if (PrintMiscellaneous && Verbose) { warning("could not create directory %s: %s\n", - dirname, strerror(errno)); + dirname, os::strerror(errno)); } return false; } @@ -804,7 +805,7 @@ if (errno == ELOOP) { warning("file %s is a symlink and is not secure\n", filename); } else { - warning("could not create file %s: %s\n", filename, strerror(errno)); + warning("could not create file %s: %s\n", filename, os::strerror(errno)); } } // close the directory and reset the current working directory @@ -828,7 +829,7 @@ RESTARTABLE(::ftruncate(fd, (off_t)0), result); if (result == OS_ERR) { if (PrintMiscellaneous && Verbose) { - warning("could not truncate shared memory file: %s\n", strerror(errno)); + warning("could not truncate shared memory file: %s\n", os::strerror(errno)); } ::close(fd); return -1; @@ -837,7 +838,7 @@ RESTARTABLE(::ftruncate(fd, (off_t)size), result); if (result == OS_ERR) { if (PrintMiscellaneous && Verbose) { - warning("could not set shared memory file size: %s\n", strerror(errno)); + warning("could not set shared memory file size: %s\n", os::strerror(errno)); } ::close(fd); return -1; @@ -887,7 +888,7 @@ "Permission denied", OS_ERR); } else { - THROW_MSG_(vmSymbols::java_io_IOException(), strerror(errno), OS_ERR); + THROW_MSG_(vmSymbols::java_io_IOException(), os::strerror(errno), OS_ERR); } } int fd = result; @@ -961,7 +962,7 @@ if (mapAddress == MAP_FAILED) { if (PrintMiscellaneous && Verbose) { - warning("mmap failed - %s\n", strerror(errno)); + warning("mmap failed - %s\n", os::strerror(errno)); } remove_file(filename); FREE_C_HEAP_ARRAY(char, filename); @@ -1025,7 +1026,7 @@ RESTARTABLE(::fstat(fd, &statbuf), result); if (result == OS_ERR) { if (PrintMiscellaneous && Verbose) { - warning("fstat failed: %s\n", strerror(errno)); + warning("fstat failed: %s\n", os::strerror(errno)); } THROW_MSG_0(vmSymbols::java_io_IOException(), "Could not determine PerfMemory size"); @@ -1136,7 +1137,7 @@ if (mapAddress == MAP_FAILED) { if (PrintMiscellaneous && Verbose) { - warning("mmap failed: %s\n", strerror(errno)); + warning("mmap failed: %s\n", os::strerror(errno)); } THROW_MSG(vmSymbols::java_lang_OutOfMemoryError(), "Could not map PerfMemory");
--- a/hotspot/src/os/linux/vm/os_linux.cpp Mon Apr 04 13:40:18 2016 -0700 +++ b/hotspot/src/os/linux/vm/os_linux.cpp Thu Apr 07 09:47:48 2016 -0700 @@ -594,15 +594,7 @@ // _expand_stack_to() assumes its frame size is less than page size, which // should always be true if the function is not inlined. -#if __GNUC__ < 3 // gcc 2.x does not support noinline attribute - #define NOINLINE -#else - #define NOINLINE __attribute__ ((noinline)) -#endif - -static void _expand_stack_to(address bottom) NOINLINE; - -static void _expand_stack_to(address bottom) { +static void NOINLINE _expand_stack_to(address bottom) { address sp; size_t size; volatile char *p; @@ -769,7 +761,7 @@ (uintx) tid, os::Posix::describe_pthread_attr(buf, sizeof(buf), &attr)); } else { log_warning(os, thread)("Failed to start thread - pthread_create failed (%s) for attributes: %s.", - strerror(ret), os::Posix::describe_pthread_attr(buf, sizeof(buf), &attr)); + os::errno_name(ret), os::Posix::describe_pthread_attr(buf, sizeof(buf), &attr)); } pthread_attr_destroy(&attr); @@ -890,6 +882,13 @@ assert(osthread != NULL, "osthread not set"); if (Thread::current()->osthread() == osthread) { +#ifdef ASSERT + sigset_t current; + sigemptyset(¤t); + pthread_sigmask(SIG_SETMASK, NULL, ¤t); + assert(!sigismember(¤t, SR_signum), "SR signal should not be blocked!"); +#endif + // Restore caller's signal mask sigset_t sigmask = osthread->caller_sigmask(); pthread_sigmask(SIG_SETMASK, &sigmask, NULL); @@ -1395,7 +1394,7 @@ size_t os::lasterror(char *buf, size_t len) { if (errno == 0) return 0; - const char *s = ::strerror(errno); + const char *s = os::strerror(errno); size_t n = ::strlen(s); if (n >= len) { n = len - 1; @@ -2601,7 +2600,7 @@ int err) { warning("INFO: os::commit_memory(" PTR_FORMAT ", " SIZE_FORMAT ", %d) failed; error='%s' (errno=%d)", p2i(addr), size, exec, - strerror(err), err); + os::strerror(err), err); } static void warn_fail_commit_memory(char* addr, size_t size, @@ -2609,7 +2608,7 @@ int err) { warning("INFO: os::commit_memory(" PTR_FORMAT ", " SIZE_FORMAT ", " SIZE_FORMAT ", %d) failed; error='%s' (errno=%d)", p2i(addr), size, - alignment_hint, exec, strerror(err), err); + alignment_hint, exec, os::strerror(err), err); } // NOTE: Linux kernel does not really reserve the pages for us. @@ -3912,7 +3911,8 @@ // after sigsuspend. int old_errno = errno; - Thread* thread = Thread::current(); + Thread* thread = Thread::current_or_null_safe(); + assert(thread != NULL, "Missing current thread in SR_handler"); OSThread* osthread = thread->osthread(); assert(thread->is_VM_thread() || thread->is_Java_thread(), "Must be VMThread or JavaThread"); @@ -3924,7 +3924,7 @@ os::SuspendResume::State state = osthread->sr.suspended(); if (state == os::SuspendResume::SR_SUSPENDED) { sigset_t suspend_set; // signals for sigsuspend() - + sigemptyset(&suspend_set); // get current set of blocked signals and unblock resume signal pthread_sigmask(SIG_BLOCK, NULL, &suspend_set); sigdelset(&suspend_set, SR_signum); @@ -4178,6 +4178,7 @@ // try to honor the signal mask sigset_t oset; + sigemptyset(&oset); pthread_sigmask(SIG_SETMASK, &(actp->sa_mask), &oset); // call into the chained handler @@ -4188,7 +4189,7 @@ } // restore the signal mask - pthread_sigmask(SIG_SETMASK, &oset, 0); + pthread_sigmask(SIG_SETMASK, &oset, NULL); } // Tell jvm's signal handler the signal is taken care of. return true; @@ -4615,7 +4616,7 @@ Linux::set_page_size(sysconf(_SC_PAGESIZE)); if (Linux::page_size() == -1) { fatal("os_linux.cpp: os::init: sysconf failed (%s)", - strerror(errno)); + os::strerror(errno)); } init_page_sizes((size_t) Linux::page_size()); @@ -4633,7 +4634,7 @@ int status; pthread_condattr_t* _condattr = os::Linux::condAttr(); if ((status = pthread_condattr_init(_condattr)) != 0) { - fatal("pthread_condattr_init: %s", strerror(status)); + fatal("pthread_condattr_init: %s", os::strerror(status)); } // Only set the clock if CLOCK_MONOTONIC is available if (os::supports_monotonic_clock()) { @@ -4642,7 +4643,7 @@ warning("Unable to use monotonic clock with relative timed-waits" \ " - changes to the time-of-day clock may have adverse affects"); } else { - fatal("pthread_condattr_setclock: %s", strerror(status)); + fatal("pthread_condattr_setclock: %s", os::strerror(status)); } } } @@ -4888,7 +4889,7 @@ log_trace(os)("active_processor_count: " "CPU_ALLOC failed (%s) - using " "online processor count: %d", - strerror(errno), online_cpus); + os::strerror(errno), online_cpus); return online_cpus; } } @@ -4918,7 +4919,7 @@ else { cpu_count = ::sysconf(_SC_NPROCESSORS_ONLN); warning("sched_getaffinity failed (%s)- using online processor count (%d) " - "which may exceed available processors", strerror(errno), cpu_count); + "which may exceed available processors", os::strerror(errno), cpu_count); } if (cpus_p != &cpus) { // can only be true when CPU_ALLOC used @@ -5769,6 +5770,7 @@ // Don't catch signals while blocked; let the running threads have the signals. // (This allows a debugger to break into the running thread.) sigset_t oldsigs; + sigemptyset(&oldsigs); sigset_t* allowdebug_blocked = os::Linux::allowdebug_blocked_signals(); pthread_sigmask(SIG_BLOCK, allowdebug_blocked, &oldsigs); #endif
--- a/hotspot/src/os/linux/vm/perfMemory_linux.cpp Mon Apr 04 13:40:18 2016 -0700 +++ b/hotspot/src/os/linux/vm/perfMemory_linux.cpp Thu Apr 07 09:47:48 2016 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,6 +29,7 @@ #include "oops/oop.inline.hpp" #include "os_linux.inline.hpp" #include "runtime/handles.inline.hpp" +#include "runtime/os.hpp" #include "runtime/perfMemory.hpp" #include "services/memTracker.hpp" #include "utilities/exceptions.hpp" @@ -100,7 +101,7 @@ if (result == OS_ERR) { if (PrintMiscellaneous && Verbose) { warning("Could not create Perfdata save file: %s: %s\n", - destfile, strerror(errno)); + destfile, os::strerror(errno)); } } else { int fd = result; @@ -111,7 +112,7 @@ if (result == OS_ERR) { if (PrintMiscellaneous && Verbose) { warning("Could not write Perfdata save file: %s: %s\n", - destfile, strerror(errno)); + destfile, os::strerror(errno)); } break; } @@ -123,7 +124,7 @@ result = ::close(fd); if (PrintMiscellaneous && Verbose) { if (result == OS_ERR) { - warning("Could not close %s: %s\n", destfile, strerror(errno)); + warning("Could not close %s: %s\n", destfile, os::strerror(errno)); } } } @@ -308,7 +309,7 @@ if (errno == ELOOP) { warning("directory %s is a symlink and is not secure\n", dirname); } else { - warning("could not open directory %s: %s\n", dirname, strerror(errno)); + warning("could not open directory %s: %s\n", dirname, os::strerror(errno)); } } return dirp; @@ -419,7 +420,7 @@ RESTARTABLE(::fstat(fd, &statbuf), result); if (result == OS_ERR) { if (PrintMiscellaneous && Verbose) { - warning("fstat failed on %s: %s\n", filename, strerror(errno)); + warning("fstat failed on %s: %s\n", filename, os::strerror(errno)); } return false; } @@ -459,7 +460,7 @@ if (PrintMiscellaneous && Verbose) { if (result != 0) { warning("Could not retrieve passwd entry: %s\n", - strerror(result)); + os::strerror(result)); } else if (p == NULL) { // this check is added to protect against an observed problem @@ -473,7 +474,7 @@ // Bug Id 89052 was opened with RedHat. // warning("Could not retrieve passwd entry: %s\n", - strerror(errno)); + os::strerror(errno)); } else { warning("Could not determine user name: %s\n", @@ -509,7 +510,7 @@ "Process not found"); } else /* EPERM */ { - THROW_MSG_0(vmSymbols::java_io_IOException(), strerror(errno)); + THROW_MSG_0(vmSymbols::java_io_IOException(), os::strerror(errno)); } } @@ -664,7 +665,7 @@ if (PrintMiscellaneous && Verbose && result == OS_ERR) { if (errno != ENOENT) { warning("Could not unlink shared memory backing" - " store file %s : %s\n", path, strerror(errno)); + " store file %s : %s\n", path, os::strerror(errno)); } } } @@ -772,7 +773,7 @@ // if (PrintMiscellaneous && Verbose) { warning("could not create directory %s: %s\n", - dirname, strerror(errno)); + dirname, os::strerror(errno)); } return false; } @@ -814,7 +815,7 @@ if (errno == ELOOP) { warning("file %s is a symlink and is not secure\n", filename); } else { - warning("could not create file %s: %s\n", filename, strerror(errno)); + warning("could not create file %s: %s\n", filename, os::strerror(errno)); } } // close the directory and reset the current working directory @@ -838,7 +839,7 @@ RESTARTABLE(::ftruncate(fd, (off_t)0), result); if (result == OS_ERR) { if (PrintMiscellaneous && Verbose) { - warning("could not truncate shared memory file: %s\n", strerror(errno)); + warning("could not truncate shared memory file: %s\n", os::strerror(errno)); } ::close(fd); return -1; @@ -847,7 +848,7 @@ RESTARTABLE(::ftruncate(fd, (off_t)size), result); if (result == OS_ERR) { if (PrintMiscellaneous && Verbose) { - warning("could not set shared memory file size: %s\n", strerror(errno)); + warning("could not set shared memory file size: %s\n", os::strerror(errno)); } ::close(fd); return -1; @@ -897,7 +898,7 @@ "Permission denied", OS_ERR); } else { - THROW_MSG_(vmSymbols::java_io_IOException(), strerror(errno), OS_ERR); + THROW_MSG_(vmSymbols::java_io_IOException(), os::strerror(errno), OS_ERR); } } int fd = result; @@ -970,7 +971,7 @@ if (mapAddress == MAP_FAILED) { if (PrintMiscellaneous && Verbose) { - warning("mmap failed - %s\n", strerror(errno)); + warning("mmap failed - %s\n", os::strerror(errno)); } remove_file(filename); FREE_C_HEAP_ARRAY(char, filename); @@ -1034,7 +1035,7 @@ RESTARTABLE(::fstat(fd, &statbuf), result); if (result == OS_ERR) { if (PrintMiscellaneous && Verbose) { - warning("fstat failed: %s\n", strerror(errno)); + warning("fstat failed: %s\n", os::strerror(errno)); } THROW_MSG_0(vmSymbols::java_io_IOException(), "Could not determine PerfMemory size"); @@ -1151,7 +1152,7 @@ if (mapAddress == MAP_FAILED) { if (PrintMiscellaneous && Verbose) { - warning("mmap failed: %s\n", strerror(errno)); + warning("mmap failed: %s\n", os::strerror(errno)); } THROW_MSG(vmSymbols::java_lang_OutOfMemoryError(), "Could not map PerfMemory");
--- a/hotspot/src/os/posix/vm/os_posix.cpp Mon Apr 04 13:40:18 2016 -0700 +++ b/hotspot/src/os/posix/vm/os_posix.cpp Thu Apr 07 09:47:48 2016 -0700 @@ -1144,7 +1144,8 @@ #define check_with_errno(check_type, cond, msg) \ do { \ int err = errno; \ - check_type(cond, "%s; error='%s' (errno=%d)", msg, strerror(err), err); \ + check_type(cond, "%s; error='%s' (errno=%s)", msg, os::strerror(err), \ + os::errno_name(err)); \ } while (false) #define assert_with_errno(cond, msg) check_with_errno(assert, cond, msg)
--- a/hotspot/src/os/solaris/vm/attachListener_solaris.cpp Mon Apr 04 13:40:18 2016 -0700 +++ b/hotspot/src/os/solaris/vm/attachListener_solaris.cpp Thu Apr 07 09:47:48 2016 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, 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 @@ -461,7 +461,7 @@ while ((res = ::sema_wait(wakeup())) == EINTR) ; if (res) { - warning("sema_wait failed: %s", strerror(res)); + warning("sema_wait failed: %s", os::strerror(res)); return NULL; }
--- a/hotspot/src/os/solaris/vm/os_solaris.cpp Mon Apr 04 13:40:18 2016 -0700 +++ b/hotspot/src/os/solaris/vm/os_solaris.cpp Thu Apr 07 09:47:48 2016 -0700 @@ -1009,7 +1009,7 @@ (uintx) tid, describe_thr_create_attributes(buf, sizeof(buf), stack_size, flags)); } else { log_warning(os, thread)("Failed to start thread - thr_create failed (%s) for attributes: %s.", - strerror(status), describe_thr_create_attributes(buf, sizeof(buf), stack_size, flags)); + os::errno_name(status), describe_thr_create_attributes(buf, sizeof(buf), stack_size, flags)); } if (status != 0) { @@ -1354,7 +1354,7 @@ jlong os::javaTimeMillis() { timeval t; if (gettimeofday(&t, NULL) == -1) { - fatal("os::javaTimeMillis: gettimeofday (%s)", strerror(errno)); + fatal("os::javaTimeMillis: gettimeofday (%s)", os::strerror(errno)); } return jlong(t.tv_sec) * 1000 + jlong(t.tv_usec) / 1000; } @@ -1362,7 +1362,7 @@ void os::javaTimeSystemUTC(jlong &seconds, jlong &nanos) { timeval t; if (gettimeofday(&t, NULL) == -1) { - fatal("os::javaTimeSystemUTC: gettimeofday (%s)", strerror(errno)); + fatal("os::javaTimeSystemUTC: gettimeofday (%s)", os::strerror(errno)); } seconds = jlong(t.tv_sec); nanos = jlong(t.tv_usec) * 1000; @@ -1892,21 +1892,39 @@ static bool check_addr0(outputStream* st) { jboolean status = false; + const int read_chunk = 200; + int ret = 0; + int nmap = 0; int fd = ::open("/proc/self/map",O_RDONLY); if (fd >= 0) { - prmap_t p; - while (::read(fd, &p, sizeof(p)) > 0) { - if (p.pr_vaddr == 0x0) { - st->print("Warning: Address: 0x%x, Size: %dK, ",p.pr_vaddr, p.pr_size/1024, p.pr_mapname); - st->print("Mapped file: %s, ", p.pr_mapname[0] == '\0' ? "None" : p.pr_mapname); - st->print("Access:"); - st->print("%s",(p.pr_mflags & MA_READ) ? "r" : "-"); - st->print("%s",(p.pr_mflags & MA_WRITE) ? "w" : "-"); - st->print("%s",(p.pr_mflags & MA_EXEC) ? "x" : "-"); - st->cr(); - status = true; + prmap_t *p = NULL; + char *mbuff = (char *) calloc(read_chunk, sizeof(prmap_t)); + if (NULL == mbuff) { + ::close(fd); + return status; + } + while ((ret = ::read(fd, mbuff, read_chunk*sizeof(prmap_t))) > 0) { + //check if read() has not read partial data + if( 0 != ret % sizeof(prmap_t)){ + break; + } + nmap = ret / sizeof(prmap_t); + p = (prmap_t *)mbuff; + for(int i = 0; i < nmap; i++){ + if (p->pr_vaddr == 0x0) { + st->print("Warning: Address: " PTR_FORMAT ", Size: " SIZE_FORMAT "K, ",p->pr_vaddr, p->pr_size/1024); + st->print("Mapped file: %s, ", p->pr_mapname[0] == '\0' ? "None" : p->pr_mapname); + st->print("Access: "); + st->print("%s",(p->pr_mflags & MA_READ) ? "r" : "-"); + st->print("%s",(p->pr_mflags & MA_WRITE) ? "w" : "-"); + st->print("%s",(p->pr_mflags & MA_EXEC) ? "x" : "-"); + st->cr(); + status = true; + } + p++; } } + free(mbuff); ::close(fd); } return status; @@ -2142,7 +2160,7 @@ size_t os::lasterror(char *buf, size_t len) { if (errno == 0) return 0; - const char *s = ::strerror(errno); + const char *s = os::strerror(errno); size_t n = ::strlen(s); if (n >= len) { n = len - 1; @@ -2351,7 +2369,7 @@ int err) { warning("INFO: os::commit_memory(" PTR_FORMAT ", " SIZE_FORMAT ", %d) failed; error='%s' (errno=%d)", addr, bytes, exec, - strerror(err), err); + os::strerror(err), err); } static void warn_fail_commit_memory(char* addr, size_t bytes, @@ -2359,7 +2377,7 @@ int err) { warning("INFO: os::commit_memory(" PTR_FORMAT ", " SIZE_FORMAT ", " SIZE_FORMAT ", %d) failed; error='%s' (errno=%d)", addr, bytes, - alignment_hint, exec, strerror(err), err); + alignment_hint, exec, os::strerror(err), err); } int os::Solaris::commit_memory_impl(char* addr, size_t bytes, bool exec) { @@ -2740,7 +2758,7 @@ char buf[256]; buf[0] = '\0'; if (addr == NULL) { - jio_snprintf(buf, sizeof(buf), ": %s", strerror(err)); + jio_snprintf(buf, sizeof(buf), ": %s", os::strerror(err)); } warning("attempt_reserve_memory_at: couldn't reserve " SIZE_FORMAT " bytes at " PTR_FORMAT ": reserve_memory_helper returned " PTR_FORMAT @@ -4354,7 +4372,7 @@ page_size = sysconf(_SC_PAGESIZE); if (page_size == -1) { - fatal("os_solaris.cpp: os::init: sysconf failed (%s)", strerror(errno)); + fatal("os_solaris.cpp: os::init: sysconf failed (%s)", os::strerror(errno)); } init_page_sizes((size_t) page_size); @@ -4366,7 +4384,7 @@ int fd = ::open("/dev/zero", O_RDWR); if (fd < 0) { - fatal("os::init: cannot open /dev/zero (%s)", strerror(errno)); + fatal("os::init: cannot open /dev/zero (%s)", os::strerror(errno)); } else { Solaris::set_dev_zero_fd(fd); @@ -5607,7 +5625,7 @@ if (pid < 0) { // fork failed - warning("fork failed: %s", strerror(errno)); + warning("fork failed: %s", os::strerror(errno)); return -1; } else if (pid == 0) {
--- a/hotspot/src/os/solaris/vm/perfMemory_solaris.cpp Mon Apr 04 13:40:18 2016 -0700 +++ b/hotspot/src/os/solaris/vm/perfMemory_solaris.cpp Thu Apr 07 09:47:48 2016 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2016, 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 @@ -102,7 +102,7 @@ if (result == OS_ERR) { if (PrintMiscellaneous && Verbose) { warning("Could not create Perfdata save file: %s: %s\n", - destfile, strerror(errno)); + destfile, os::strerror(errno)); } } else { @@ -114,7 +114,7 @@ if (result == OS_ERR) { if (PrintMiscellaneous && Verbose) { warning("Could not write Perfdata save file: %s: %s\n", - destfile, strerror(errno)); + destfile, os::strerror(errno)); } break; } @@ -125,7 +125,7 @@ result = ::close(fd); if (PrintMiscellaneous && Verbose) { if (result == OS_ERR) { - warning("Could not close %s: %s\n", destfile, strerror(errno)); + warning("Could not close %s: %s\n", destfile, os::strerror(errno)); } } } @@ -311,7 +311,7 @@ if (errno == ELOOP) { warning("directory %s is a symlink and is not secure\n", dirname); } else { - warning("could not open directory %s: %s\n", dirname, strerror(errno)); + warning("could not open directory %s: %s\n", dirname, os::strerror(errno)); } } return dirp; @@ -422,7 +422,7 @@ RESTARTABLE(::fstat(fd, &statbuf), result); if (result == OS_ERR) { if (PrintMiscellaneous && Verbose) { - warning("fstat failed on %s: %s\n", filename, strerror(errno)); + warning("fstat failed on %s: %s\n", filename, os::strerror(errno)); } return false; } @@ -464,7 +464,7 @@ if (PrintMiscellaneous && Verbose) { if (p == NULL) { warning("Could not retrieve passwd entry: %s\n", - strerror(errno)); + os::strerror(errno)); } else { warning("Could not determine user name: %s\n", @@ -500,7 +500,7 @@ "Process not found"); } else /* EPERM */ { - THROW_MSG_0(vmSymbols::java_io_IOException(), strerror(errno)); + THROW_MSG_0(vmSymbols::java_io_IOException(), os::strerror(errno)); } } @@ -657,7 +657,7 @@ // In this case, the psinfo file for the process id existed, // but we didn't have permission to access it. THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), - strerror(errno)); + os::strerror(errno)); } // at this point, we don't know if the process id itself doesn't @@ -703,7 +703,7 @@ if (PrintMiscellaneous && Verbose && result == OS_ERR) { if (errno != ENOENT) { warning("Could not unlink shared memory backing" - " store file %s : %s\n", path, strerror(errno)); + " store file %s : %s\n", path, os::strerror(errno)); } } } @@ -813,7 +813,7 @@ // if (PrintMiscellaneous && Verbose) { warning("could not create directory %s: %s\n", - dirname, strerror(errno)); + dirname, os::strerror(errno)); } return false; } @@ -855,7 +855,7 @@ if (errno == ELOOP) { warning("file %s is a symlink and is not secure\n", filename); } else { - warning("could not create file %s: %s\n", filename, strerror(errno)); + warning("could not create file %s: %s\n", filename, os::strerror(errno)); } } // close the directory and reset the current working directory @@ -879,7 +879,7 @@ RESTARTABLE(::ftruncate(fd, (off_t)0), result); if (result == OS_ERR) { if (PrintMiscellaneous && Verbose) { - warning("could not truncate shared memory file: %s\n", strerror(errno)); + warning("could not truncate shared memory file: %s\n", os::strerror(errno)); } ::close(fd); return -1; @@ -888,7 +888,7 @@ RESTARTABLE(::ftruncate(fd, (off_t)size), result); if (result == OS_ERR) { if (PrintMiscellaneous && Verbose) { - warning("could not set shared memory file size: %s\n", strerror(errno)); + warning("could not set shared memory file size: %s\n", os::strerror(errno)); } ::close(fd); return -1; @@ -916,7 +916,7 @@ "Permission denied", OS_ERR); } else { - THROW_MSG_(vmSymbols::java_io_IOException(), strerror(errno), OS_ERR); + THROW_MSG_(vmSymbols::java_io_IOException(), os::strerror(errno), OS_ERR); } } int fd = result; @@ -990,7 +990,7 @@ if (mapAddress == MAP_FAILED) { if (PrintMiscellaneous && Verbose) { - warning("mmap failed - %s\n", strerror(errno)); + warning("mmap failed - %s\n", os::strerror(errno)); } remove_file(filename); FREE_C_HEAP_ARRAY(char, filename); @@ -1055,7 +1055,7 @@ RESTARTABLE(::fstat(fd, &statbuf), result); if (result == OS_ERR) { if (PrintMiscellaneous && Verbose) { - warning("fstat failed: %s\n", strerror(errno)); + warning("fstat failed: %s\n", os::strerror(errno)); } THROW_MSG_0(vmSymbols::java_io_IOException(), "Could not determine PerfMemory size"); @@ -1172,7 +1172,7 @@ if (mapAddress == MAP_FAILED) { if (PrintMiscellaneous && Verbose) { - warning("mmap failed: %s\n", strerror(errno)); + warning("mmap failed: %s\n", os::strerror(errno)); } THROW_MSG(vmSymbols::java_lang_OutOfMemoryError(), "Could not map PerfMemory");
--- a/hotspot/src/os/solaris/vm/threadCritical_solaris.cpp Mon Apr 04 13:40:18 2016 -0700 +++ b/hotspot/src/os/solaris/vm/threadCritical_solaris.cpp Thu Apr 07 09:47:48 2016 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,6 +23,7 @@ */ #include "precompiled.hpp" +#include "runtime/os.hpp" #include "runtime/thread.inline.hpp" #include "runtime/threadCritical.hpp" @@ -49,7 +50,7 @@ if (global_mut_owner != owner) { if (os::Solaris::mutex_lock(&global_mut)) fatal("ThreadCritical::ThreadCritical: mutex_lock failed (%s)", - strerror(errno)); + os::strerror(errno)); assert(global_mut_count == 0, "must have clean count"); assert(global_mut_owner == -1, "must have clean owner"); } @@ -68,7 +69,7 @@ if (global_mut_count == 0) { global_mut_owner = -1; if (os::Solaris::mutex_unlock(&global_mut)) - fatal("ThreadCritical::~ThreadCritical: mutex_unlock failed (%s)", strerror(errno)); + fatal("ThreadCritical::~ThreadCritical: mutex_unlock failed (%s)", os::strerror(errno)); } } else { assert (Threads::number_of_threads() == 0, "valid only during initialization");
--- a/hotspot/src/os/windows/vm/os_windows.cpp Mon Apr 04 13:40:18 2016 -0700 +++ b/hotspot/src/os/windows/vm/os_windows.cpp Thu Apr 07 09:47:48 2016 -0700 @@ -642,7 +642,7 @@ thread_id, describe_beginthreadex_attributes(buf, sizeof(buf), stack_size, initflag)); } else { log_warning(os, thread)("Failed to start thread - _beginthreadex failed (%s) for attributes: %s.", - strerror(errno), describe_beginthreadex_attributes(buf, sizeof(buf), stack_size, initflag)); + os::errno_name(errno), describe_beginthreadex_attributes(buf, sizeof(buf), stack_size, initflag)); } if (thread_handle == NULL) { @@ -1898,7 +1898,7 @@ if (errno != 0) { // C runtime error that has no corresponding DOS error code - const char* s = strerror(errno); + const char* s = os::strerror(errno); size_t n = strlen(s); if (n >= len) n = len - 1; strncpy(buf, s, n); @@ -2186,13 +2186,6 @@ // Windows Vista/2008 heap corruption check #define EXCEPTION_HEAP_CORRUPTION 0xC0000374 -#define def_excpt(val) #val, val - -struct siglabel { - char *name; - int number; -}; - // All Visual C++ exceptions thrown from code generated by the Microsoft Visual // C++ compiler contain this error code. Because this is a compiler-generated // error, the code is not listed in the Win32 API header files. @@ -2202,8 +2195,9 @@ #define EXCEPTION_UNCAUGHT_CXX_EXCEPTION 0xE06D7363 - -struct siglabel exceptlabels[] = { +#define def_excpt(val) { #val, (val) } + +static const struct { char* name; uint number; } exceptlabels[] = { def_excpt(EXCEPTION_ACCESS_VIOLATION), def_excpt(EXCEPTION_DATATYPE_MISALIGNMENT), def_excpt(EXCEPTION_BREAKPOINT), @@ -2228,16 +2222,18 @@ def_excpt(EXCEPTION_GUARD_PAGE), def_excpt(EXCEPTION_INVALID_HANDLE), def_excpt(EXCEPTION_UNCAUGHT_CXX_EXCEPTION), - def_excpt(EXCEPTION_HEAP_CORRUPTION), + def_excpt(EXCEPTION_HEAP_CORRUPTION) #ifdef _M_IA64 - def_excpt(EXCEPTION_REG_NAT_CONSUMPTION), + , def_excpt(EXCEPTION_REG_NAT_CONSUMPTION) #endif - NULL, 0 }; +#undef def_excpt + const char* os::exception_name(int exception_code, char *buf, size_t size) { - for (int i = 0; exceptlabels[i].name != NULL; i++) { - if (exceptlabels[i].number == exception_code) { + uint code = static_cast<uint>(exception_code); + for (uint i = 0; i < ARRAY_SIZE(exceptlabels); ++i) { + if (exceptlabels[i].number == code) { jio_snprintf(buf, size, "%s", exceptlabels[i].name); return buf; } @@ -2445,7 +2441,7 @@ jio_snprintf(buf, sizeof(buf), "Execution protection violation " "at " INTPTR_FORMAT ", unguarding " INTPTR_FORMAT ": %s", addr, - page_start, (res ? "success" : strerror(errno))); + page_start, (res ? "success" : os::strerror(errno))); tty->print_raw_cr(buf); } @@ -5638,9 +5634,11 @@ "TERM", SIGTERM, // software term signal from kill "BREAK", SIGBREAK, // Ctrl-Break sequence "ILL", SIGILL}; // illegal instruction - for(int i=0;i<sizeof(siglabels)/sizeof(struct siglabel);i++) - if(!strcmp(name, siglabels[i].name)) + for (unsigned i = 0; i < ARRAY_SIZE(siglabels); ++i) { + if (strcmp(name, siglabels[i].name) == 0) { return siglabels[i].number; + } + } return -1; }
--- a/hotspot/src/os/windows/vm/perfMemory_windows.cpp Mon Apr 04 13:40:18 2016 -0700 +++ b/hotspot/src/os/windows/vm/perfMemory_windows.cpp Thu Apr 07 09:47:48 2016 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2016, 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 @@ -96,7 +96,7 @@ if (fd == OS_ERR) { if (PrintMiscellaneous && Verbose) { warning("Could not create Perfdata save file: %s: %s\n", - destfile, strerror(errno)); + destfile, os::strerror(errno)); } } else { for (size_t remaining = size; remaining > 0;) { @@ -105,7 +105,7 @@ if (nbytes == OS_ERR) { if (PrintMiscellaneous && Verbose) { warning("Could not write Perfdata save file: %s: %s\n", - destfile, strerror(errno)); + destfile, os::strerror(errno)); } break; } @@ -117,7 +117,7 @@ int result = ::_close(fd); if (PrintMiscellaneous && Verbose) { if (result == OS_ERR) { - warning("Could not close %s: %s\n", destfile, strerror(errno)); + warning("Could not close %s: %s\n", destfile, os::strerror(errno)); } } } @@ -497,7 +497,7 @@ if (PrintMiscellaneous && Verbose) { if (errno != ENOENT) { warning("Could not unlink shared memory backing" - " store file %s : %s\n", path, strerror(errno)); + " store file %s : %s\n", path, os::strerror(errno)); } } } @@ -1358,7 +1358,7 @@ if (ret_code == OS_ERR) { if (PrintMiscellaneous && Verbose) { warning("Could not get status information from file %s: %s\n", - filename, strerror(errno)); + filename, os::strerror(errno)); } CloseHandle(fmh); CloseHandle(fh); @@ -1553,7 +1553,7 @@ // if (::stat(filename, &statbuf) == OS_ERR) { if (PrintMiscellaneous && Verbose) { - warning("stat %s failed: %s\n", filename, strerror(errno)); + warning("stat %s failed: %s\n", filename, os::strerror(errno)); } THROW_MSG_0(vmSymbols::java_io_IOException(), "Could not determine PerfMemory size");
--- a/hotspot/src/os_cpu/windows_x86/vm/os_windows_x86.cpp Mon Apr 04 13:40:18 2016 -0700 +++ b/hotspot/src/os_cpu/windows_x86/vm/os_windows_x86.cpp Thu Apr 07 09:47:48 2016 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -33,6 +33,7 @@ #include "interpreter/interpreter.hpp" #include "jvm_windows.h" #include "memory/allocation.inline.hpp" +#include "memory/resourceArea.hpp" #include "mutex_windows.inline.hpp" #include "nativeInst_x86.hpp" #include "os_share_windows.hpp"
--- a/hotspot/src/share/vm/c1/c1_Compilation.cpp Mon Apr 04 13:40:18 2016 -0700 +++ b/hotspot/src/share/vm/c1/c1_Compilation.cpp Thu Apr 07 09:47:48 2016 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -35,7 +35,9 @@ #include "code/debugInfoRec.hpp" #include "compiler/compileLog.hpp" #include "compiler/compilerDirectives.hpp" +#include "memory/resourceArea.hpp" #include "runtime/sharedRuntime.hpp" +#include "runtime/timerTrace.hpp" typedef enum { _t_compile,
--- a/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp Mon Apr 04 13:40:18 2016 -0700 +++ b/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp Thu Apr 07 09:47:48 2016 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2016, 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 @@ -34,6 +34,7 @@ #include "ci/ciMemberName.hpp" #include "compiler/compileBroker.hpp" #include "interpreter/bytecode.hpp" +#include "memory/resourceArea.hpp" #include "oops/oop.inline.hpp" #include "runtime/sharedRuntime.hpp" #include "runtime/compilationPolicy.hpp"
--- a/hotspot/src/share/vm/c1/c1_IR.cpp Mon Apr 04 13:40:18 2016 -0700 +++ b/hotspot/src/share/vm/c1/c1_IR.cpp Thu Apr 07 09:47:48 2016 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,6 +29,7 @@ #include "c1/c1_IR.hpp" #include "c1/c1_InstructionPrinter.hpp" #include "c1/c1_Optimizer.hpp" +#include "memory/resourceArea.hpp" #include "utilities/bitMap.inline.hpp"
--- a/hotspot/src/share/vm/c1/c1_LinearScan.cpp Mon Apr 04 13:40:18 2016 -0700 +++ b/hotspot/src/share/vm/c1/c1_LinearScan.cpp Thu Apr 07 09:47:48 2016 -0700 @@ -32,6 +32,7 @@ #include "c1/c1_LinearScan.hpp" #include "c1/c1_ValueStack.hpp" #include "code/vmreg.inline.hpp" +#include "runtime/timerTrace.hpp" #include "utilities/bitMap.inline.hpp" #ifndef PRODUCT
--- a/hotspot/src/share/vm/c1/c1_Optimizer.cpp Mon Apr 04 13:40:18 2016 -0700 +++ b/hotspot/src/share/vm/c1/c1_Optimizer.cpp Thu Apr 07 09:47:48 2016 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,6 +28,7 @@ #include "c1/c1_ValueMap.hpp" #include "c1/c1_ValueSet.hpp" #include "c1/c1_ValueStack.hpp" +#include "memory/resourceArea.hpp" #include "utilities/bitMap.inline.hpp" #include "compiler/compileLog.hpp"
--- a/hotspot/src/share/vm/c1/c1_ValueType.cpp Mon Apr 04 13:40:18 2016 -0700 +++ b/hotspot/src/share/vm/c1/c1_ValueType.cpp Thu Apr 07 09:47:48 2016 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,6 +27,7 @@ #include "ci/ciArray.hpp" #include "ci/ciInstance.hpp" #include "ci/ciNullObject.hpp" +#include "memory/resourceArea.hpp" // predefined types
--- a/hotspot/src/share/vm/ci/ciEnv.cpp Mon Apr 04 13:40:18 2016 -0700 +++ b/hotspot/src/share/vm/ci/ciEnv.cpp Thu Apr 07 09:47:48 2016 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -43,6 +43,7 @@ #include "interpreter/linkResolver.hpp" #include "memory/allocation.inline.hpp" #include "memory/oopFactory.hpp" +#include "memory/resourceArea.hpp" #include "memory/universe.inline.hpp" #include "oops/methodData.hpp" #include "oops/objArrayKlass.hpp"
--- a/hotspot/src/share/vm/ci/ciInstanceKlass.cpp Mon Apr 04 13:40:18 2016 -0700 +++ b/hotspot/src/share/vm/ci/ciInstanceKlass.cpp Thu Apr 07 09:47:48 2016 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,6 +30,7 @@ #include "classfile/systemDictionary.hpp" #include "memory/allocation.hpp" #include "memory/allocation.inline.hpp" +#include "memory/resourceArea.hpp" #include "oops/oop.inline.hpp" #include "oops/fieldStreams.hpp" #include "runtime/fieldDescriptor.hpp"
--- a/hotspot/src/share/vm/ci/ciReplay.cpp Mon Apr 04 13:40:18 2016 -0700 +++ b/hotspot/src/share/vm/ci/ciReplay.cpp Thu Apr 07 09:47:48 2016 -0700 @@ -1,4 +1,5 @@ -/* Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. +/* + * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,6 +29,7 @@ #include "ci/ciKlass.hpp" #include "ci/ciUtilities.hpp" #include "compiler/compileBroker.hpp" +#include "gc/shared/referencePendingListLocker.hpp" #include "memory/allocation.inline.hpp" #include "memory/oopFactory.hpp" #include "memory/resourceArea.hpp" @@ -574,7 +576,7 @@ Method* method = parse_method(CHECK); if (had_error()) return; /* just copied from Method, to build interpret data*/ - if (InstanceRefKlass::owns_pending_list_lock((JavaThread*)THREAD)) { + if (ReferencePendingListLocker::is_locked_by_self()) { return; } // To be properly initialized, some profiling in the MDO needs the
--- a/hotspot/src/share/vm/ci/ciSignature.cpp Mon Apr 04 13:40:18 2016 -0700 +++ b/hotspot/src/share/vm/ci/ciSignature.cpp Thu Apr 07 09:47:48 2016 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,6 +27,7 @@ #include "ci/ciSignature.hpp" #include "ci/ciUtilities.hpp" #include "memory/allocation.inline.hpp" +#include "memory/resourceArea.hpp" #include "oops/oop.inline.hpp" #include "runtime/signature.hpp"
--- a/hotspot/src/share/vm/ci/ciType.cpp Mon Apr 04 13:40:18 2016 -0700 +++ b/hotspot/src/share/vm/ci/ciType.cpp Thu Apr 07 09:47:48 2016 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,6 +27,7 @@ #include "ci/ciType.hpp" #include "ci/ciUtilities.hpp" #include "classfile/systemDictionary.hpp" +#include "memory/resourceArea.hpp" #include "oops/oop.inline.hpp" ciType* ciType::_basic_types[T_CONFLICT+1];
--- a/hotspot/src/share/vm/ci/ciTypeFlow.cpp Mon Apr 04 13:40:18 2016 -0700 +++ b/hotspot/src/share/vm/ci/ciTypeFlow.cpp Thu Apr 07 09:47:48 2016 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -35,6 +35,7 @@ #include "interpreter/bytecode.hpp" #include "interpreter/bytecodes.hpp" #include "memory/allocation.inline.hpp" +#include "memory/resourceArea.hpp" #include "oops/oop.inline.hpp" #include "opto/compile.hpp" #include "opto/node.hpp"
--- a/hotspot/src/share/vm/classfile/classFileParser.cpp Mon Apr 04 13:40:18 2016 -0700 +++ b/hotspot/src/share/vm/classfile/classFileParser.cpp Thu Apr 07 09:47:48 2016 -0700 @@ -5372,12 +5372,12 @@ } } - if (log_is_enabled(Info, classresolve)) { + if (log_is_enabled(Debug, classresolve)) { ResourceMark rm; // print out the superclass. const char * from = ik->external_name(); if (ik->java_super() != NULL) { - log_info(classresolve)("%s %s (super)", + log_debug(classresolve)("%s %s (super)", from, ik->java_super()->external_name()); } @@ -5388,7 +5388,7 @@ for (int i = 0; i < length; i++) { const Klass* const k = local_interfaces->at(i); const char * to = k->external_name(); - log_info(classresolve)("%s %s (interface)", from, to); + log_debug(classresolve)("%s %s (interface)", from, to); } } } @@ -5698,15 +5698,16 @@ } if (!is_internal()) { - if (TraceClassLoadingPreorder) { - tty->print("[Loading %s", - _class_name->as_klass_external_name()); - + if (log_is_enabled(Debug, classload, preorder)){ + ResourceMark rm(THREAD); + outputStream* log = Log(classload, preorder)::debug_stream(); + log->print("%s", _class_name->as_klass_external_name()); if (stream->source() != NULL) { - tty->print(" from %s", stream->source()); + log->print(" source: %s", stream->source()); } - tty->print_cr("]"); + log->cr(); } + #if INCLUDE_CDS if (DumpLoadedClassList != NULL && stream->source() != NULL && classlist_file->is_open()) { // Only dump the classes that can be stored into CDS archive
--- a/hotspot/src/share/vm/classfile/classFileStream.cpp Mon Apr 04 13:40:18 2016 -0700 +++ b/hotspot/src/share/vm/classfile/classFileStream.cpp Thu Apr 07 09:47:48 2016 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,7 @@ #include "precompiled.hpp" #include "classfile/classFileStream.hpp" #include "classfile/vmSymbols.hpp" +#include "memory/resourceArea.hpp" const bool ClassFileStream::verify = true; const bool ClassFileStream::no_verification = false;
--- a/hotspot/src/share/vm/classfile/classLoader.cpp Mon Apr 04 13:40:18 2016 -0700 +++ b/hotspot/src/share/vm/classfile/classLoader.cpp Thu Apr 07 09:47:48 2016 -0700 @@ -44,6 +44,7 @@ #include "memory/allocation.inline.hpp" #include "memory/filemap.hpp" #include "memory/oopFactory.hpp" +#include "memory/resourceArea.hpp" #include "memory/universe.inline.hpp" #include "oops/instanceKlass.hpp" #include "oops/instanceRefKlass.hpp" @@ -226,11 +227,12 @@ return NULL; } -ClassPathZipEntry::ClassPathZipEntry(jzfile* zip, const char* zip_name) : ClassPathEntry() { +ClassPathZipEntry::ClassPathZipEntry(jzfile* zip, const char* zip_name, bool is_boot_append) : ClassPathEntry() { _zip = zip; char *copy = NEW_C_HEAP_ARRAY(char, strlen(zip_name)+1, mtClass); strcpy(copy, zip_name); _zip_name = copy; + _is_boot_append = is_boot_append; } ClassPathZipEntry::~ClassPathZipEntry() { @@ -274,11 +276,79 @@ return buffer; } +#if INCLUDE_CDS +u1* ClassPathZipEntry::open_versioned_entry(const char* name, jint* filesize, TRAPS) { + u1* buffer = NULL; + if (!_is_boot_append) { + assert(DumpSharedSpaces, "Should be called only for non-boot entries during dump time"); + // We presume default is multi-release enabled + const char* multi_ver = Arguments::get_property("jdk.util.jar.enableMultiRelease"); + const char* verstr = Arguments::get_property("jdk.util.jar.version"); + bool is_multi_ver = (multi_ver == NULL || + strcmp(multi_ver, "true") == 0 || + strcmp(multi_ver, "force") == 0) && + is_multiple_versioned(THREAD); + // command line version setting + int version = 0; + const int base_version = 8; // JDK8 + int cur_ver = JDK_Version::current().major_version(); + if (verstr != NULL) { + version = atoi(verstr); + if (version < base_version || version > cur_ver) { + is_multi_ver = false; + // print out warning, do not use assertion here since it will continue to look + // for proper version. + warning("JDK%d is not supported in multiple version jars", version); + } + } + + if (is_multi_ver) { + int n; + char entry_name[JVM_MAXPATHLEN]; + if (version > 0) { + n = jio_snprintf(entry_name, sizeof(entry_name), "META-INF/versions/%d/%s", version, name); + entry_name[n] = '\0'; + buffer = open_entry((const char*)entry_name, filesize, false, CHECK_NULL); + if (buffer == NULL) { + warning("Could not find %s in %s, try to find highest version instead", entry_name, _zip_name); + } + } + if (buffer == NULL) { + for (int i = cur_ver; i >= base_version; i--) { + n = jio_snprintf(entry_name, sizeof(entry_name), "META-INF/versions/%d/%s", i, name); + entry_name[n] = '\0'; + buffer = open_entry((const char*)entry_name, filesize, false, CHECK_NULL); + if (buffer != NULL) { + break; + } + } + } + } + } + return buffer; +} + +bool ClassPathZipEntry::is_multiple_versioned(TRAPS) { + assert(DumpSharedSpaces, "called only at dump time"); + jint size; + char* buffer = (char*)open_entry("META-INF/MANIFEST.MF", &size, false, CHECK_false); + if (buffer != NULL) { + if (strstr(buffer, "Multi-Release: true") != NULL) { + return true; + } + } + return false; +} +#endif // INCLUDE_CDS + ClassFileStream* ClassPathZipEntry::open_stream(const char* name, TRAPS) { jint filesize; - const u1* buffer = open_entry(name, &filesize, false, CHECK_NULL); + u1* buffer = open_versioned_entry(name, &filesize, CHECK_NULL); if (buffer == NULL) { - return NULL; + buffer = open_entry(name, &filesize, false, CHECK_NULL); + if (buffer == NULL) { + return NULL; + } } if (UsePerfData) { ClassLoader::perf_sys_classfile_bytes_read()->inc(filesize); @@ -466,7 +536,7 @@ void ClassLoader::trace_class_path(const char* msg, const char* name) { if (log_is_enabled(Info, classpath)) { ResourceMark rm; - outputStream* out = LogHandle(classpath)::info_stream(); + outputStream* out = Log(classpath)::info_stream(); if (msg) { out->print("%s", msg); } @@ -558,7 +628,7 @@ char* path = NEW_RESOURCE_ARRAY(char, end - start + 1); strncpy(path, &class_path[start], end - start); path[end - start] = '\0'; - update_class_path_entry_list(path, false, mark_append_entry, false); + update_class_path_entry_list(path, false, mark_append_entry, false, bootstrap_search); // Check on the state of the boot loader's append path if (mark_append_entry && (_first_append_entry == NULL)) { @@ -582,7 +652,8 @@ } ClassPathEntry* ClassLoader::create_class_path_entry(const char *path, const struct stat* st, - bool throw_exception, TRAPS) { + bool throw_exception, + bool is_boot_append, TRAPS) { JavaThread* thread = JavaThread::current(); ClassPathEntry* new_entry = NULL; if ((st->st_mode & S_IFREG) == S_IFREG) { @@ -611,7 +682,7 @@ zip = (*ZipOpen)(canonical_path, &error_msg); } if (zip != NULL && error_msg == NULL) { - new_entry = new ClassPathZipEntry(zip, path); + new_entry = new ClassPathZipEntry(zip, path, is_boot_append); } else { ResourceMark rm(thread); char *msg; @@ -644,7 +715,7 @@ // Create a class path zip entry for a given path (return NULL if not found // or zip/JAR file cannot be opened) -ClassPathZipEntry* ClassLoader::create_class_path_zip_entry(const char *path) { +ClassPathZipEntry* ClassLoader::create_class_path_zip_entry(const char *path, bool is_boot_append) { // check for a regular file struct stat st; if (os::stat(path, &st) == 0) { @@ -662,7 +733,7 @@ } if (zip != NULL && error_msg == NULL) { // create using canonical path - return new ClassPathZipEntry(zip, canonical_path); + return new ClassPathZipEntry(zip, canonical_path, is_boot_append); } } } @@ -720,11 +791,11 @@ } void ClassLoader::add_to_list(const char *apath) { - update_class_path_entry_list((char*)apath, false, false, false); + update_class_path_entry_list((char*)apath, false, false, false, false); } void ClassLoader::prepend_to_list(const char *apath) { - update_class_path_entry_list((char*)apath, false, false, true); + update_class_path_entry_list((char*)apath, false, false, true, false); } // Returns true IFF the file/dir exists and the entry was successfully created. @@ -732,13 +803,14 @@ bool check_for_duplicates, bool mark_append_entry, bool prepend_entry, + bool is_boot_append, bool throw_exception) { struct stat st; if (os::stat(path, &st) == 0) { // File or directory found ClassPathEntry* new_entry = NULL; Thread* THREAD = Thread::current(); - new_entry = create_class_path_entry(path, &st, throw_exception, CHECK_(false)); + new_entry = create_class_path_entry(path, &st, throw_exception, is_boot_append, CHECK_(false)); if (new_entry == NULL) { return false; }
--- a/hotspot/src/share/vm/classfile/classLoader.hpp Mon Apr 04 13:40:18 2016 -0700 +++ b/hotspot/src/share/vm/classfile/classLoader.hpp Thu Apr 07 09:47:48 2016 -0700 @@ -104,16 +104,19 @@ private: jzfile* _zip; // The zip archive const char* _zip_name; // Name of zip archive + bool _is_boot_append; // entry coming from -Xbootclasspath/a public: bool is_jrt() { return false; } bool is_jar_file() const { return true; } const char* name() const { return _zip_name; } JImageFile* jimage() const { return NULL; } - ClassPathZipEntry(jzfile* zip, const char* zip_name); + ClassPathZipEntry(jzfile* zip, const char* zip_name, bool is_boot_append); ~ClassPathZipEntry(); u1* open_entry(const char* name, jint* filesize, bool nul_terminate, TRAPS); + u1* open_versioned_entry(const char* name, jint* filesize, TRAPS) NOT_CDS_RETURN_(NULL); ClassFileStream* open_stream(const char* name, TRAPS); void contents_do(void f(const char* name, void* context), void* context); + bool is_multiple_versioned(TRAPS) NOT_CDS_RETURN_(false); // Debugging NOT_PRODUCT(void compile_the_world(Handle loader, TRAPS);) }; @@ -223,7 +226,8 @@ static void load_zip_library(); static void load_jimage_library(); static ClassPathEntry* create_class_path_entry(const char *path, const struct stat* st, - bool throw_exception, TRAPS); + bool throw_exception, + bool is_boot_append, TRAPS); public: @@ -249,6 +253,7 @@ bool check_for_duplicates, bool mark_append_entry, bool prepend_entry, + bool is_boot_append, bool throw_exception=true); static void print_bootclasspath(); @@ -394,7 +399,7 @@ static void prepend_to_list(ClassPathEntry* new_entry); // creates a class path zip entry (returns NULL if JAR file cannot be opened) - static ClassPathZipEntry* create_class_path_zip_entry(const char *apath); + static ClassPathZipEntry* create_class_path_zip_entry(const char *apath, bool is_boot_append); // add a path to class path list static void add_to_list(const char* apath);
--- a/hotspot/src/share/vm/classfile/classLoaderData.cpp Mon Apr 04 13:40:18 2016 -0700 +++ b/hotspot/src/share/vm/classfile/classLoaderData.cpp Thu Apr 07 09:47:48 2016 -0700 @@ -60,6 +60,7 @@ #include "memory/metadataFactory.hpp" #include "memory/metaspaceShared.hpp" #include "memory/oopFactory.hpp" +#include "memory/resourceArea.hpp" #include "oops/objArrayOop.inline.hpp" #include "oops/oop.inline.hpp" #include "runtime/atomic.inline.hpp" @@ -357,7 +358,7 @@ if (log_is_enabled(Debug, classloaderdata)) { ResourceMark rm; - outputStream* log = LogHandle(classloaderdata)::debug_stream(); + outputStream* log = Log(classloaderdata)::debug_stream(); log->print(": unload loader data " INTPTR_FORMAT, p2i(this)); log->print(" for instance " INTPTR_FORMAT " of %s", p2i((void *)class_loader()), loader_name()); @@ -717,7 +718,7 @@ } ResourceMark rm; - outputStream* log = LogHandle(classloaderdata)::debug_stream(); + outputStream* log = Log(classloaderdata)::debug_stream(); log->print("create class loader data " INTPTR_FORMAT, p2i(cld)); log->print(" for instance " INTPTR_FORMAT " of %s", p2i((void *)cld->class_loader()), cld->loader_name()); @@ -859,7 +860,7 @@ array->push(curr); if (log_is_enabled(Debug, classloaderdata)) { - outputStream* log = LogHandle(classloaderdata)::debug_stream(); + outputStream* log = Log(classloaderdata)::debug_stream(); log->print("found new CLD: "); curr->print_value_on(log); log->cr();
--- a/hotspot/src/share/vm/classfile/defaultMethods.cpp Mon Apr 04 13:40:18 2016 -0700 +++ b/hotspot/src/share/vm/classfile/defaultMethods.cpp Thu Apr 07 09:47:48 2016 -0700 @@ -437,7 +437,7 @@ _exception_name = vmSymbols::java_lang_IncompatibleClassChangeError(); if (log_is_enabled(Debug, defaultmethods)) { ResourceMark rm; - outputStream* logstream = LogHandle(defaultmethods)::debug_stream(); + outputStream* logstream = Log(defaultmethods)::debug_stream(); _exception_message->print_value_on(logstream); logstream->cr(); } @@ -663,7 +663,7 @@ if (log_is_enabled(Debug, defaultmethods)) { log_debug(defaultmethods)("Slots that need filling:"); ResourceMark rm; - outputStream* logstream = LogHandle(defaultmethods)::debug_stream(); + outputStream* logstream = Log(defaultmethods)::debug_stream(); streamIndentor si(logstream); for (int i = 0; i < slots->length(); ++i) { logstream->indent(); @@ -799,7 +799,7 @@ log_debug(defaultmethods)("%s %s requires default method processing", klass->is_interface() ? "Interface" : "Class", klass->name()->as_klass_external_name()); - PrintHierarchy printer(LogHandle(defaultmethods)::debug_stream()); + PrintHierarchy printer(Log(defaultmethods)::debug_stream()); printer.run(klass); } @@ -809,7 +809,7 @@ for (int i = 0; i < empty_slots->length(); ++i) { EmptyVtableSlot* slot = empty_slots->at(i); if (log_is_enabled(Debug, defaultmethods)) { - outputStream* logstream = LogHandle(defaultmethods)::debug_stream(); + outputStream* logstream = Log(defaultmethods)::debug_stream(); streamIndentor si(logstream, 2); logstream->indent().print("Looking for default methods for slot "); slot->print_on(logstream); @@ -917,7 +917,7 @@ if (log_is_enabled(Debug, defaultmethods)) { ResourceMark rm; - outputStream* logstream = LogHandle(defaultmethods)::debug_stream(); + outputStream* logstream = Log(defaultmethods)::debug_stream(); logstream->print("for slot: "); slot->print_on(logstream); logstream->cr();
--- a/hotspot/src/share/vm/classfile/dictionary.cpp Mon Apr 04 13:40:18 2016 -0700 +++ b/hotspot/src/share/vm/classfile/dictionary.cpp Thu Apr 07 09:47:48 2016 -0700 @@ -29,6 +29,7 @@ #include "classfile/systemDictionary.hpp" #include "classfile/systemDictionaryShared.hpp" #include "memory/iterator.hpp" +#include "memory/resourceArea.hpp" #include "oops/oop.inline.hpp" #include "prims/jvmtiRedefineClassesTrace.hpp" #include "runtime/orderAccess.inline.hpp" @@ -137,7 +138,7 @@ } if (log_is_enabled(Trace, protectiondomain)) { ResourceMark rm; - outputStream* log = LogHandle(protectiondomain)::trace_stream(); + outputStream* log = Log(protectiondomain)::trace_stream(); print_count(log); } }
--- a/hotspot/src/share/vm/classfile/javaClasses.cpp Mon Apr 04 13:40:18 2016 -0700 +++ b/hotspot/src/share/vm/classfile/javaClasses.cpp Thu Apr 07 09:47:48 2016 -0700 @@ -515,22 +515,6 @@ return result; } -unsigned int java_lang_String::hash_string(oop java_string) { - int length = java_lang_String::length(java_string); - // Zero length string doesn't necessarily hash to zero. - if (length == 0) { - return StringTable::hash_string((jchar*) NULL, 0); - } - - typeArrayOop value = java_lang_String::value(java_string); - bool is_latin1 = java_lang_String::is_latin1(java_string); - if (is_latin1) { - return StringTable::hash_string(value->byte_at_addr(0), length); - } else { - return StringTable::hash_string(value->char_at_addr(0), length); - } -} - Symbol* java_lang_String::as_symbol(Handle java_string, TRAPS) { oop obj = java_string(); typeArrayOop value = java_lang_String::value(obj); @@ -1473,6 +1457,12 @@ compute_offset(_ngroups_offset, k, vmSymbols::ngroups_name(), vmSymbols::int_signature()); } + +void java_lang_Throwable::compute_offsets() { + Klass* k = SystemDictionary::Throwable_klass(); + compute_offset(depth_offset, k, vmSymbols::depth_name(), vmSymbols::int_signature()); +} + oop java_lang_Throwable::unassigned_stacktrace() { InstanceKlass* ik = SystemDictionary::Throwable_klass(); address addr = ik->static_field_addr(static_unassigned_stacktrace_offset); @@ -1492,11 +1482,13 @@ throwable->release_obj_field_put(backtrace_offset, value); } - -oop java_lang_Throwable::message(oop throwable) { - return throwable->obj_field(detailMessage_offset); -} - +int java_lang_Throwable::depth(oop throwable) { + return throwable->int_field(depth_offset); +} + +void java_lang_Throwable::set_depth(oop throwable, int value) { + throwable->int_field_put(depth_offset, value); +} oop java_lang_Throwable::message(Handle throwable) { return throwable->obj_field(detailMessage_offset); @@ -1546,10 +1538,12 @@ return method != NULL && (method->constants()->version() == version); } + // This class provides a simple wrapper over the internal structure of // exception backtrace to insulate users of the backtrace from needing // to know what it looks like. class BacktraceBuilder: public StackObj { + friend class BacktraceIterator; private: Handle _backtrace; objArrayOop _head; @@ -1560,8 +1554,6 @@ int _index; NoSafepointVerifier _nsv; - public: - enum { trace_methods_offset = java_lang_Throwable::trace_methods_offset, trace_bcis_offset = java_lang_Throwable::trace_bcis_offset, @@ -1594,6 +1586,8 @@ return cprefs; } + public: + // constructor for new backtrace BacktraceBuilder(TRAPS): _methods(NULL), _bcis(NULL), _head(NULL), _mirrors(NULL), _cprefs(NULL) { expand(CHECK); @@ -1679,9 +1673,68 @@ }; +struct BacktraceElement : public StackObj { + int _method_id; + int _bci; + int _version; + int _cpref; + Handle _mirror; + BacktraceElement(Handle mirror, int mid, int version, int bci, int cpref) : + _mirror(mirror), _method_id(mid), _version(version), _bci(bci), _cpref(cpref) {} +}; + +class BacktraceIterator : public StackObj { + int _index; + objArrayHandle _result; + objArrayHandle _mirrors; + typeArrayHandle _methods; + typeArrayHandle _bcis; + typeArrayHandle _cprefs; + + void init(objArrayHandle result, Thread* thread) { + // Get method id, bci, version and mirror from chunk + _result = result; + if (_result.not_null()) { + _methods = typeArrayHandle(thread, BacktraceBuilder::get_methods(_result)); + _bcis = typeArrayHandle(thread, BacktraceBuilder::get_bcis(_result)); + _mirrors = objArrayHandle(thread, BacktraceBuilder::get_mirrors(_result)); + _cprefs = typeArrayHandle(thread, BacktraceBuilder::get_cprefs(_result)); + _index = 0; + } + } + public: + BacktraceIterator(objArrayHandle result, Thread* thread) { + init(result, thread); + assert(_methods.is_null() || _methods->length() == java_lang_Throwable::trace_chunk_size, "lengths don't match"); + } + + BacktraceElement next(Thread* thread) { + BacktraceElement e (Handle(thread, _mirrors->obj_at(_index)), + _methods->short_at(_index), + Backtrace::version_at(_bcis->int_at(_index)), + Backtrace::bci_at(_bcis->int_at(_index)), + _cprefs->short_at(_index)); + _index++; + + if (_index >= java_lang_Throwable::trace_chunk_size) { + int next_offset = java_lang_Throwable::trace_next_offset; + // Get next chunk + objArrayHandle result (thread, objArrayOop(_result->obj_at(next_offset))); + init(result, thread); + } + return e; + } + + bool repeat() { + return _result.not_null() && _mirrors->obj_at(_index) != NULL; + } +}; + + // Print stack trace element to resource allocated buffer -char* java_lang_Throwable::print_stack_element_to_buffer(Handle mirror, - int method_id, int version, int bci, int cpref) { +static void print_stack_element_to_stream(outputStream* st, Handle mirror, int method_id, + int version, int bci, int cpref) { + ResourceMark rm; // Get strings and string lengths InstanceKlass* holder = InstanceKlass::cast(java_lang_Class::as_Klass(mirror())); @@ -1752,13 +1805,6 @@ } } - return buf; -} - -void java_lang_Throwable::print_stack_element(outputStream *st, Handle mirror, - int method_id, int version, int bci, int cpref) { - ResourceMark rm; - char* buf = print_stack_element_to_buffer(mirror, method_id, version, bci, cpref); st->print_cr("%s", buf); } @@ -1767,11 +1813,7 @@ int method_id = method->orig_method_idnum(); int version = method->constants()->version(); int cpref = method->name_index(); - print_stack_element(st, mirror, method_id, version, bci, cpref); -} - -const char* java_lang_Throwable::no_stack_trace_message() { - return "\t<<no stack trace available>>"; + print_stack_element_to_stream(st, mirror, method_id, version, bci, cpref); } /** @@ -1788,32 +1830,17 @@ while (throwable.not_null()) { objArrayHandle result (THREAD, objArrayOop(backtrace(throwable()))); if (result.is_null()) { - st->print_raw_cr(no_stack_trace_message()); + st->print_raw_cr("\t<<no stack trace available>>"); return; } - - while (result.not_null()) { - // Get method id, bci, version and mirror from chunk - typeArrayHandle methods (THREAD, BacktraceBuilder::get_methods(result)); - typeArrayHandle bcis (THREAD, BacktraceBuilder::get_bcis(result)); - objArrayHandle mirrors (THREAD, BacktraceBuilder::get_mirrors(result)); - typeArrayHandle cprefs (THREAD, BacktraceBuilder::get_cprefs(result)); - - int length = methods()->length(); - for (int index = 0; index < length; index++) { - Handle mirror(THREAD, mirrors->obj_at(index)); - // NULL mirror means end of stack trace - if (mirror.is_null()) goto handle_cause; - int method = methods->short_at(index); - int version = Backtrace::version_at(bcis->int_at(index)); - int bci = Backtrace::bci_at(bcis->int_at(index)); - int cpref = cprefs->short_at(index); - print_stack_element(st, mirror, method, version, bci, cpref); - } - result = objArrayHandle(THREAD, objArrayOop(result->obj_at(trace_next_offset))); + BacktraceIterator iter(result, THREAD); + + while (iter.repeat()) { + BacktraceElement bte = iter.next(THREAD); + print_stack_element_to_stream(st, bte._mirror, bte._method_id, bte._version, bte._bci, bte._cpref); } - handle_cause: { + // Call getCause() which doesn't necessarily return the _cause field. EXCEPTION_MARK; JavaValue cause(T_OBJECT); JavaCalls::call_virtual(&cause, @@ -1865,6 +1892,7 @@ int max_depth = MaxJavaStackTraceDepth; JavaThread* thread = (JavaThread*)THREAD; + BacktraceBuilder bt(CHECK); // If there is no Java frame just return the method that was being called @@ -1872,6 +1900,8 @@ if (!thread->has_last_Java_frame()) { if (max_depth >= 1 && method() != NULL) { bt.push(method(), 0, CHECK); + log_info(stacktrace)("%s, %d", throwable->klass()->external_name(), 1); + set_depth(throwable(), 1); set_backtrace(throwable(), bt.backtrace()); } return; @@ -1979,8 +2009,11 @@ total_count++; } + log_info(stacktrace)("%s, %d", throwable->klass()->external_name(), total_count); + // Put completed stack trace into throwable object set_backtrace(throwable(), bt.backtrace()); + set_depth(throwable(), total_count); } void java_lang_Throwable::fill_in_stack_trace(Handle throwable, const methodHandle& method) { @@ -2034,94 +2067,60 @@ // methods as preallocated errors aren't created by "java" code. // fill in as much stack trace as possible - typeArrayOop methods = BacktraceBuilder::get_methods(backtrace); - int max_chunks = MIN2(methods->length(), (int)MaxJavaStackTraceDepth); int chunk_count = 0; - for (;!st.at_end(); st.next()) { bt.push(st.method(), st.bci(), CHECK); chunk_count++; // Bail-out for deep stacks - if (chunk_count >= max_chunks) break; + if (chunk_count >= trace_chunk_size) break; } + set_depth(throwable(), chunk_count); + log_info(stacktrace)("%s, %d", throwable->klass()->external_name(), chunk_count); // We support the Throwable immutability protocol defined for Java 7. java_lang_Throwable::set_stacktrace(throwable(), java_lang_Throwable::unassigned_stacktrace()); assert(java_lang_Throwable::unassigned_stacktrace() != NULL, "not initialized"); } - -int java_lang_Throwable::get_stack_trace_depth(oop throwable, TRAPS) { - if (throwable == NULL) { - THROW_0(vmSymbols::java_lang_NullPointerException()); +void java_lang_Throwable::get_stack_trace_elements(Handle throwable, + objArrayHandle stack_trace_array_h, TRAPS) { + + if (throwable.is_null() || stack_trace_array_h.is_null()) { + THROW(vmSymbols::java_lang_NullPointerException()); } - objArrayOop chunk = objArrayOop(backtrace(throwable)); - int depth = 0; - if (chunk != NULL) { - // Iterate over chunks and count full ones - while (true) { - objArrayOop next = objArrayOop(chunk->obj_at(trace_next_offset)); - if (next == NULL) break; - depth += trace_chunk_size; - chunk = next; - } - assert(chunk != NULL && chunk->obj_at(trace_next_offset) == NULL, "sanity check"); - // Count element in remaining partial chunk. NULL value for mirror - // marks the end of the stack trace elements that are saved. - objArrayOop mirrors = BacktraceBuilder::get_mirrors(chunk); - assert(mirrors != NULL, "sanity check"); - for (int i = 0; i < mirrors->length(); i++) { - if (mirrors->obj_at(i) == NULL) break; - depth++; - } - } - return depth; -} - - -oop java_lang_Throwable::get_stack_trace_element(oop throwable, int index, TRAPS) { - if (throwable == NULL) { - THROW_0(vmSymbols::java_lang_NullPointerException()); - } - if (index < 0) { - THROW_(vmSymbols::java_lang_IndexOutOfBoundsException(), NULL); + + assert(stack_trace_array_h->is_objArray(), "Stack trace array should be an array of StackTraceElenent"); + + if (stack_trace_array_h->length() != depth(throwable())) { + THROW(vmSymbols::java_lang_IndexOutOfBoundsException()); } - // Compute how many chunks to skip and index into actual chunk - objArrayOop chunk = objArrayOop(backtrace(throwable)); - int skip_chunks = index / trace_chunk_size; - int chunk_index = index % trace_chunk_size; - while (chunk != NULL && skip_chunks > 0) { - chunk = objArrayOop(chunk->obj_at(trace_next_offset)); - skip_chunks--; - } - if (chunk == NULL) { - THROW_(vmSymbols::java_lang_IndexOutOfBoundsException(), NULL); + + objArrayHandle result(THREAD, objArrayOop(backtrace(throwable()))); + BacktraceIterator iter(result, THREAD); + + int index = 0; + while (iter.repeat()) { + BacktraceElement bte = iter.next(THREAD); + + Handle stack_trace_element(THREAD, stack_trace_array_h->obj_at(index++)); + + if (stack_trace_element.is_null()) { + THROW(vmSymbols::java_lang_NullPointerException()); + } + + InstanceKlass* holder = InstanceKlass::cast(java_lang_Class::as_Klass(bte._mirror())); + methodHandle method (THREAD, holder->method_with_orig_idnum(bte._method_id, bte._version)); + + java_lang_StackTraceElement::fill_in(stack_trace_element, holder, + method, + bte._version, + bte._bci, + bte._cpref, CHECK); } - // Get method id, bci, version, mirror and cpref from chunk - typeArrayOop methods = BacktraceBuilder::get_methods(chunk); - typeArrayOop bcis = BacktraceBuilder::get_bcis(chunk); - objArrayOop mirrors = BacktraceBuilder::get_mirrors(chunk); - typeArrayOop cprefs = BacktraceBuilder::get_cprefs(chunk); - - assert(methods != NULL && bcis != NULL && mirrors != NULL, "sanity check"); - - int method = methods->short_at(chunk_index); - int version = Backtrace::version_at(bcis->int_at(chunk_index)); - int bci = Backtrace::bci_at(bcis->int_at(chunk_index)); - int cpref = cprefs->short_at(chunk_index); - Handle mirror(THREAD, mirrors->obj_at(chunk_index)); - - // Chunk can be partial full - if (mirror.is_null()) { - THROW_(vmSymbols::java_lang_IndexOutOfBoundsException(), NULL); - } - oop element = java_lang_StackTraceElement::create(mirror, method, version, bci, cpref, CHECK_0); - return element; -} - -oop java_lang_StackTraceElement::create(Handle mirror, int method_id, - int version, int bci, int cpref, TRAPS) { +} + +oop java_lang_StackTraceElement::create(const methodHandle& method, int bci, TRAPS) { // Allocate java.lang.StackTraceElement instance Klass* k = SystemDictionary::StackTraceElement_klass(); assert(k != NULL, "must be loaded in 1.4+"); @@ -2132,37 +2131,45 @@ Handle element = ik->allocate_instance_handle(CHECK_0); + int cpref = method->name_index(); + int version = method->constants()->version(); + fill_in(element, method->method_holder(), method, version, bci, cpref, CHECK_0); + return element(); +} + +void java_lang_StackTraceElement::fill_in(Handle element, + InstanceKlass* holder, const methodHandle& method, + int version, int bci, int cpref, TRAPS) { + assert(element->is_a(SystemDictionary::StackTraceElement_klass()), "sanity check"); + // Fill in class name ResourceMark rm(THREAD); - InstanceKlass* holder = InstanceKlass::cast(java_lang_Class::as_Klass(mirror())); const char* str = holder->external_name(); - oop classname = StringTable::intern((char*) str, CHECK_0); + oop classname = StringTable::intern((char*) str, CHECK); java_lang_StackTraceElement::set_declaringClass(element(), classname); - Method* method = holder->method_with_orig_idnum(method_id, version); - // The method can be NULL if the requested class version is gone - Symbol* sym = (method != NULL) ? method->name() : holder->constants()->symbol_at(cpref); + Symbol* sym = !method.is_null() ? method->name() : holder->constants()->symbol_at(cpref); // Fill in method name - oop methodname = StringTable::intern(sym, CHECK_0); + oop methodname = StringTable::intern(sym, CHECK); java_lang_StackTraceElement::set_methodName(element(), methodname); // Fill in module name and version ModuleEntry* module = holder->module(); if (module->is_named()) { - oop module_name = StringTable::intern(module->name(), CHECK_0); + oop module_name = StringTable::intern(module->name(), CHECK); java_lang_StackTraceElement::set_moduleName(element(), module_name); oop module_version; if (module->version() != NULL) { - module_version = StringTable::intern(module->version(), CHECK_0); + module_version = StringTable::intern(module->version(), CHECK); } else { module_version = NULL; } java_lang_StackTraceElement::set_moduleVersion(element(), module_version); } - if (!version_matches(method, version)) { + if (!version_matches(method(), version)) { // The method was redefined, accurate line number information isn't available java_lang_StackTraceElement::set_fileName(element(), NULL); java_lang_StackTraceElement::set_lineNumber(element(), -1); @@ -2171,20 +2178,12 @@ Symbol* source = Backtrace::get_source_file_name(holder, version); if (ShowHiddenFrames && source == NULL) source = vmSymbols::unknown_class_name(); - oop filename = StringTable::intern(source, CHECK_0); + oop filename = StringTable::intern(source, CHECK); java_lang_StackTraceElement::set_fileName(element(), filename); int line_number = Backtrace::get_line_number(method, bci); java_lang_StackTraceElement::set_lineNumber(element(), line_number); } - return element(); -} - -oop java_lang_StackTraceElement::create(const methodHandle& method, int bci, TRAPS) { - Handle mirror (THREAD, method->method_holder()->java_mirror()); - int method_id = method->orig_method_idnum(); - int cpref = method->name_index(); - return create(mirror, method_id, method->constants()->version(), bci, cpref, THREAD); } Method* java_lang_StackFrameInfo::get_method(Handle stackFrame, InstanceKlass* holder, TRAPS) { @@ -3629,8 +3628,8 @@ GrowableArray<Klass*>* java_lang_Class::_fixup_module_field_list = NULL; int java_lang_Throwable::backtrace_offset; int java_lang_Throwable::detailMessage_offset; -int java_lang_Throwable::cause_offset; int java_lang_Throwable::stackTrace_offset; +int java_lang_Throwable::depth_offset; int java_lang_Throwable::static_unassigned_stacktrace_offset; int java_lang_reflect_AccessibleObject::override_offset; int java_lang_reflect_Method::clazz_offset; @@ -3841,7 +3840,6 @@ // Throwable Class java_lang_Throwable::backtrace_offset = java_lang_Throwable::hc_backtrace_offset * x + header; java_lang_Throwable::detailMessage_offset = java_lang_Throwable::hc_detailMessage_offset * x + header; - java_lang_Throwable::cause_offset = java_lang_Throwable::hc_cause_offset * x + header; java_lang_Throwable::stackTrace_offset = java_lang_Throwable::hc_stackTrace_offset * x + header; java_lang_Throwable::static_unassigned_stacktrace_offset = java_lang_Throwable::hc_static_unassigned_stacktrace_offset * x; @@ -3894,6 +3892,7 @@ void JavaClasses::compute_offsets() { // java_lang_Class::compute_offsets was called earlier in bootstrap java_lang_ClassLoader::compute_offsets(); + java_lang_Throwable::compute_offsets(); java_lang_Thread::compute_offsets(); java_lang_ThreadGroup::compute_offsets(); java_lang_invoke_MethodHandle::compute_offsets(); @@ -4048,8 +4047,8 @@ CHECK_OFFSET("java/lang/Throwable", java_lang_Throwable, backtrace, "Ljava/lang/Object;"); CHECK_OFFSET("java/lang/Throwable", java_lang_Throwable, detailMessage, "Ljava/lang/String;"); - CHECK_OFFSET("java/lang/Throwable", java_lang_Throwable, cause, "Ljava/lang/Throwable;"); CHECK_OFFSET("java/lang/Throwable", java_lang_Throwable, stackTrace, "[Ljava/lang/StackTraceElement;"); + CHECK_OFFSET("java/lang/Throwable", java_lang_Throwable, depth, "I"); // Boxed primitive objects (java_lang_boxing_object)
--- a/hotspot/src/share/vm/classfile/javaClasses.hpp Mon Apr 04 13:40:18 2016 -0700 +++ b/hotspot/src/share/vm/classfile/javaClasses.hpp Thu Apr 07 09:47:48 2016 -0700 @@ -155,11 +155,6 @@ } static unsigned int hash_code(oop java_string); - static unsigned int latin1_hash_code(typeArrayOop value, int len); - - // This is the string hash code used by the StringTable, which may be - // the same as String.hashCode or an alternate hash code. - static unsigned int hash_string(oop java_string); static bool equals(oop java_string, jchar* chars, int len); static bool equals(oop str1, oop str2); @@ -456,6 +451,7 @@ class java_lang_Throwable: AllStatic { friend class BacktraceBuilder; + friend class BacktraceIterator; private: // Offsets @@ -481,16 +477,12 @@ static int backtrace_offset; static int detailMessage_offset; - static int cause_offset; static int stackTrace_offset; + static int depth_offset; static int static_unassigned_stacktrace_offset; - // Printing - static char* print_stack_element_to_buffer(Handle mirror, int method, int version, int bci, int cpref); // StackTrace (programmatic access, new since 1.4) static void clear_stacktrace(oop throwable); - // No stack trace available - static const char* no_stack_trace_message(); // Stacktrace (post JDK 1.7.0 to allow immutability protocol to be followed) static void set_stacktrace(oop throwable, oop st_element_array); static oop unassigned_stacktrace(); @@ -499,19 +491,20 @@ // Backtrace static oop backtrace(oop throwable); static void set_backtrace(oop throwable, oop value); + static int depth(oop throwable); + static void set_depth(oop throwable, int value); // Needed by JVMTI to filter out this internal field. static int get_backtrace_offset() { return backtrace_offset;} static int get_detailMessage_offset() { return detailMessage_offset;} // Message - static oop message(oop throwable); static oop message(Handle throwable); static void set_message(oop throwable, oop value); static Symbol* detail_message(oop throwable); - static void print_stack_element(outputStream *st, Handle mirror, int method, - int version, int bci, int cpref); static void print_stack_element(outputStream *st, const methodHandle& method, int bci); static void print_stack_usage(Handle stream); + static void compute_offsets(); + // Allocate space for backtrace (created but stack trace not filled in) static void allocate_backtrace(Handle throwable, TRAPS); // Fill in current stack trace for throwable with preallocated backtrace (no GC) @@ -520,8 +513,7 @@ static void fill_in_stack_trace(Handle throwable, const methodHandle& method, TRAPS); static void fill_in_stack_trace(Handle throwable, const methodHandle& method = methodHandle()); // Programmatic access to stack trace - static oop get_stack_trace_element(oop throwable, int index, TRAPS); - static int get_stack_trace_depth(oop throwable, TRAPS); + static void get_stack_trace_elements(Handle throwable, objArrayHandle stack_trace, TRAPS); // Printing static void print(Handle throwable, outputStream* st); static void print_stack_trace(Handle throwable, outputStream* st); @@ -1333,7 +1325,6 @@ static int fileName_offset; static int lineNumber_offset; - public: // Setters static void set_moduleName(oop element, oop value); static void set_moduleVersion(oop element, oop value); @@ -1342,10 +1333,13 @@ static void set_fileName(oop element, oop value); static void set_lineNumber(oop element, int value); + public: // Create an instance of StackTraceElement - static oop create(Handle mirror, int method, int version, int bci, int cpref, TRAPS); static oop create(const methodHandle& method, int bci, TRAPS); + static void fill_in(Handle element, InstanceKlass* holder, const methodHandle& method, + int version, int bci, int cpref, TRAPS); + // Debugging friend class JavaClasses; };
--- a/hotspot/src/share/vm/classfile/loaderConstraints.cpp Mon Apr 04 13:40:18 2016 -0700 +++ b/hotspot/src/share/vm/classfile/loaderConstraints.cpp Thu Apr 07 09:47:48 2016 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2016, 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 @@ -111,13 +111,14 @@ if (klass != NULL && klass->class_loader_data()->is_unloading()) { probe->set_klass(NULL); - if (TraceLoaderConstraints) { + if (log_is_enabled(Info, constraints)) { ResourceMark rm; - tty->print_cr("[Purging class object from constraint for name %s," + outputStream* out = Log(classload, constraints)::info_stream(); + out->print_cr("purging class object from constraint for name %s," " loader list:", probe->name()->as_C_string()); for (int i = 0; i < probe->num_loaders(); i++) { - tty->print_cr("[ [%d]: %s", i, + out->print_cr(" [%d]: %s", i, probe->loader_data(i)->loader_name()); } } @@ -126,9 +127,10 @@ int n = 0; while (n < probe->num_loaders()) { if (probe->loader_data(n)->is_unloading()) { - if (TraceLoaderConstraints) { + if (log_is_enabled(Info, classload, constraints)) { ResourceMark rm; - tty->print_cr("[Purging loader %s from constraint for name %s", + outputStream* out = Log(classload, constraints)::info_stream(); + out->print_cr("purging loader %s from constraint for name %s", probe->loader_data(n)->loader_name(), probe->name()->as_C_string() ); @@ -140,11 +142,12 @@ probe->set_loader_data(n, probe->loader_data(num)); probe->set_loader_data(num, NULL); - if (TraceLoaderConstraints) { + if (log_is_enabled(Info, classload, constraints)) { ResourceMark rm; - tty->print_cr("[New loader list:"); + outputStream* out = Log(classload, constraints)::info_stream(); + out->print_cr("new loader list:"); for (int i = 0; i < probe->num_loaders(); i++) { - tty->print_cr("[ [%d]: %s", i, + out->print_cr(" [%d]: %s", i, probe->loader_data(i)->loader_name()); } } @@ -156,9 +159,10 @@ } // Check whether entry should be purged if (probe->num_loaders() < 2) { - if (TraceLoaderConstraints) { + if (log_is_enabled(Info, classload, constraints)) { ResourceMark rm; - tty->print("[Purging complete constraint for name %s\n", + outputStream* out = Log(classload, constraints)::info_stream(); + out->print_cr("purging complete constraint for name %s", probe->name()->as_C_string()); } @@ -227,10 +231,11 @@ p->set_klass(klass); p->set_next(bucket(index)); set_entry(index, p); - if (TraceLoaderConstraints) { + if (log_is_enabled(Info, classload, constraints)) { ResourceMark rm; - tty->print("[Adding new constraint for name: %s, loader[0]: %s," - " loader[1]: %s ]\n", + outputStream* out = Log(classload, constraints)::info_stream(); + out->print_cr("adding new constraint for name: %s, loader[0]: %s," + " loader[1]: %s", class_name->as_C_string(), SystemDictionary::loader_name(class_loader1()), SystemDictionary::loader_name(class_loader2()) @@ -240,10 +245,11 @@ /* constraint already imposed */ if ((*pp1)->klass() == NULL) { (*pp1)->set_klass(klass); - if (TraceLoaderConstraints) { + if (log_is_enabled(Info, classload, constraints)) { ResourceMark rm; - tty->print("[Setting class object in existing constraint for" - " name: %s and loader %s ]\n", + outputStream* out = Log(classload, constraints)::info_stream(); + out->print_cr("setting class object in existing constraint for" + " name: %s and loader %s", class_name->as_C_string(), SystemDictionary::loader_name(class_loader1()) ); @@ -261,8 +267,9 @@ } } - if (failure_code != 0 && TraceLoaderConstraints) { + if (failure_code != 0 && log_is_enabled(Info, classload, constraints)) { ResourceMark rm; + outputStream* out = Log(classload, constraints)::info_stream(); const char* reason = ""; switch(failure_code) { case 1: reason = "the class objects presented by loader[0] and loader[1]" @@ -273,8 +280,8 @@ " the stored class object in the constraint"; break; default: reason = "unknown reason code"; } - tty->print("[Failed to add constraint for name: %s, loader[0]: %s," - " loader[1]: %s, Reason: %s ]\n", + out->print_cr("failed to add constraint for name: %s, loader[0]: %s," + " loader[1]: %s, Reason: %s", class_name->as_C_string(), SystemDictionary::loader_name(class_loader1()), SystemDictionary::loader_name(class_loader2()), @@ -293,10 +300,11 @@ Symbol* name) { LoaderConstraintEntry* p = *(find_loader_constraint(name, loader)); if (p && p->klass() != NULL && p->klass() != k()) { - if (TraceLoaderConstraints) { + if (log_is_enabled(Info, classload, constraints)) { ResourceMark rm; - tty->print("[Constraint check failed for name %s, loader %s: " - "the presented class object differs from that stored ]\n", + outputStream* out = Log(classload, constraints)::info_stream(); + out->print_cr("constraint check failed for name %s, loader %s: " + "the presented class object differs from that stored", name->as_C_string(), SystemDictionary::loader_name(loader())); } @@ -304,10 +312,11 @@ } else { if (p && p->klass() == NULL) { p->set_klass(k()); - if (TraceLoaderConstraints) { + if (log_is_enabled(Info, classload, constraints)) { ResourceMark rm; - tty->print("[Updating constraint for name %s, loader %s, " - "by setting class object ]\n", + outputStream* out = Log(classload, constraints)::info_stream(); + out->print_cr("updating constraint for name %s, loader %s, " + "by setting class object", name->as_C_string(), SystemDictionary::loader_name(loader())); } @@ -353,13 +362,14 @@ int num = p->num_loaders(); p->set_loader(num, loader()); p->set_num_loaders(num + 1); - if (TraceLoaderConstraints) { + if (log_is_enabled(Info, classload, constraints)) { ResourceMark rm; - tty->print("[Extending constraint for name %s by adding loader[%d]: %s %s", + outputStream* out = Log(classload, constraints)::info_stream(); + out->print_cr("extending constraint for name %s by adding loader[%d]: %s %s", p->name()->as_C_string(), num, SystemDictionary::loader_name(loader()), - (p->klass() == NULL ? " and setting class object ]\n" : " ]\n") + (p->klass() == NULL ? " and setting class object" : "") ); } if (p->klass() == NULL) { @@ -392,18 +402,19 @@ p1->set_num_loaders(num + 1); } - if (TraceLoaderConstraints) { + if (log_is_enabled(Info, classload, constraints)) { ResourceMark rm; - tty->print_cr("[Merged constraints for name %s, new loader list:", + outputStream* out = Log(classload, constraints)::info_stream(); + out->print_cr("merged constraints for name %s, new loader list:", p1->name()->as_C_string() ); for (int i = 0; i < p1->num_loaders(); i++) { - tty->print_cr("[ [%d]: %s", i, + out->print_cr(" [%d]: %s", i, p1->loader_data(i)->loader_name()); } if (p1->klass() == NULL) { - tty->print_cr("[... and setting class object]"); + out->print_cr("... and setting class object"); } } @@ -473,7 +484,6 @@ // Called with the system dictionary lock held void LoaderConstraintTable::print() { ResourceMark rm; - assert_locked_or_safepoint(SystemDictionary_lock); tty->print_cr("Java loader constraints (entries=%d)", _loader_constraint_size); for (int cindex = 0; cindex < _loader_constraint_size; cindex++) {
--- a/hotspot/src/share/vm/classfile/modules.cpp Mon Apr 04 13:40:18 2016 -0700 +++ b/hotspot/src/share/vm/classfile/modules.cpp Thu Apr 07 09:47:48 2016 -0700 @@ -36,6 +36,7 @@ #include "classfile/symbolTable.hpp" #include "classfile/vmSymbols.hpp" #include "logging/log.hpp" +#include "memory/resourceArea.hpp" #include "oops/instanceKlass.hpp" #include "oops/objArrayKlass.hpp" #include "oops/objArrayOop.inline.hpp" @@ -480,7 +481,7 @@ } if (log_is_enabled(Debug, modules)) { - outputStream* logst = LogHandle(modules)::debug_stream(); + outputStream* logst = Log(modules)::debug_stream(); logst->print("define_module(): creation of module: %s, version: %s, location: %s, ", module_name, module_version != NULL ? module_version : "NULL", module_location != NULL ? module_location : "NULL"); @@ -789,7 +790,7 @@ if (log_is_enabled(Debug, modules)) { ResourceMark rm(THREAD); - outputStream* logst = LogHandle(modules)::debug_stream(); + outputStream* logst = Log(modules)::debug_stream(); Klass* klass = java_lang_Class::as_Klass(mirror); oop module_name = java_lang_reflect_Module::name(module); if (module_name != NULL) {
--- a/hotspot/src/share/vm/classfile/sharedPathsMiscInfo.cpp Mon Apr 04 13:40:18 2016 -0700 +++ b/hotspot/src/share/vm/classfile/sharedPathsMiscInfo.cpp Thu Apr 07 09:47:48 2016 -0700 @@ -29,6 +29,7 @@ #include "logging/log.hpp" #include "memory/allocation.inline.hpp" #include "memory/metaspaceShared.hpp" +#include "memory/resourceArea.hpp" #include "runtime/arguments.hpp" #include "utilities/ostream.hpp" @@ -74,7 +75,7 @@ void SharedPathsMiscInfo::print_path(int type, const char* path) { ResourceMark rm; - outputStream* out = LogHandle(classpath)::info_stream(); + outputStream* out = Log(classpath)::info_stream(); switch (type) { case BOOT: out->print("Expecting BOOT path=%s", path);
--- a/hotspot/src/share/vm/classfile/stringTable.cpp Mon Apr 04 13:40:18 2016 -0700 +++ b/hotspot/src/share/vm/classfile/stringTable.cpp Thu Apr 07 09:47:48 2016 -0700 @@ -32,6 +32,7 @@ #include "gc/shared/gcLocker.inline.hpp" #include "memory/allocation.inline.hpp" #include "memory/filemap.hpp" +#include "memory/resourceArea.hpp" #include "oops/oop.inline.hpp" #include "runtime/atomic.inline.hpp" #include "runtime/mutexLocker.hpp" @@ -94,15 +95,27 @@ CompactHashtable<oop, char> StringTable::_shared_table; // Pick hashing algorithm -template<typename T> -unsigned int StringTable::hash_string(const T* s, int len) { +unsigned int StringTable::hash_string(const jchar* s, int len) { return use_alternate_hashcode() ? AltHashing::murmur3_32(seed(), s, len) : java_lang_String::hash_code(s, len); } -// Explicit instantiation for all supported types. -template unsigned int StringTable::hash_string<jchar>(const jchar* s, int len); -template unsigned int StringTable::hash_string<jbyte>(const jbyte* s, int len); +unsigned int StringTable::hash_string(oop string) { + EXCEPTION_MARK; + if (string == NULL) { + return hash_string((jchar*)NULL, 0); + } + ResourceMark rm(THREAD); + // All String oops are hashed as unicode + int length; + jchar* chars = java_lang_String::as_unicode_string(string, length, THREAD); + if (chars != NULL) { + return hash_string(chars, length); + } else { + vm_exit_out_of_memory(length, OOM_MALLOC_ERROR, "unable to create Unicode string for verification"); + return 0; + } +} oop StringTable::lookup_shared(jchar* name, int len) { // java_lang_String::hash_code() was used to compute hash values in the shared table. Don't @@ -398,7 +411,7 @@ for ( ; p != NULL; p = p->next()) { oop s = p->literal(); guarantee(s != NULL, "interned string is NULL"); - unsigned int h = java_lang_String::hash_string(s); + unsigned int h = hash_string(s); guarantee(p->hash() == h, "broken hash in string table entry"); guarantee(the_table()->hash_to_index(h) == i, "wrong index in string table"); @@ -498,7 +511,7 @@ return _verify_fail_done; } - unsigned int h = java_lang_String::hash_string(str); + unsigned int h = hash_string(str); if (e_ptr->hash() != h) { if (mesg_mode == _verify_with_mesgs) { tty->print_cr("ERROR: broken hash value in entry @ bucket[%d][%d], "
--- a/hotspot/src/share/vm/classfile/stringTable.hpp Mon Apr 04 13:40:18 2016 -0700 +++ b/hotspot/src/share/vm/classfile/stringTable.hpp Thu Apr 07 09:47:48 2016 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, 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 @@ -111,7 +111,8 @@ // Hashing algorithm, used as the hash value used by the // StringTable for bucket selection and comparison (stored in the // HashtableEntry structures). This is used in the String.intern() method. - template<typename T> static unsigned int hash_string(const T* s, int len); + static unsigned int hash_string(const jchar* s, int len); + static unsigned int hash_string(oop string); // Internal test. static void test_alt_hash() PRODUCT_RETURN;
--- a/hotspot/src/share/vm/classfile/symbolTable.cpp Mon Apr 04 13:40:18 2016 -0700 +++ b/hotspot/src/share/vm/classfile/symbolTable.cpp Thu Apr 07 09:47:48 2016 -0700 @@ -32,6 +32,7 @@ #include "gc/shared/gcLocker.inline.hpp" #include "memory/allocation.inline.hpp" #include "memory/filemap.hpp" +#include "memory/resourceArea.hpp" #include "oops/oop.inline.hpp" #include "runtime/atomic.inline.hpp" #include "runtime/mutexLocker.hpp" @@ -160,6 +161,11 @@ // Create a new table and using alternate hash code, populate the new table // with the existing strings. Set flag to use the alternate hash code afterwards. void SymbolTable::rehash_table() { + if (DumpSharedSpaces) { + tty->print_cr("Warning: rehash_table should not be called while dumping archive"); + return; + } + assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint"); // This should never happen with -Xshare:dump but it might in testing mode. if (DumpSharedSpaces) return; @@ -201,6 +207,11 @@ Symbol* SymbolTable::lookup_shared(const char* name, int len, unsigned int hash) { + if (use_alternate_hashcode()) { + // hash_code parameter may use alternate hashing algorithm but the shared table + // always uses the same original hash code. + hash = hash_shared_symbol(name, len); + } return _shared_table.lookup(name, hash, len); } @@ -234,6 +245,10 @@ java_lang_String::hash_code((const jbyte*)s, len); } +unsigned int SymbolTable::hash_shared_symbol(const char* s, int len) { + return java_lang_String::hash_code((const jbyte*)s, len); +} + // We take care not to be blocking while holding the // SymbolTable_lock. Otherwise, the system might deadlock, since the @@ -536,7 +551,7 @@ HashtableEntry<Symbol*, mtSymbol>* p = the_table()->bucket(i); for ( ; p != NULL; p = p->next()) { Symbol* s = (Symbol*)(p->literal()); - unsigned int fixed_hash = hash_symbol((char*)s->bytes(), s->utf8_length()); + unsigned int fixed_hash = hash_shared_symbol((char*)s->bytes(), s->utf8_length()); assert(fixed_hash == p->hash(), "must not rehash during dumping"); ch_table.add(fixed_hash, s); }
--- a/hotspot/src/share/vm/classfile/symbolTable.hpp Mon Apr 04 13:40:18 2016 -0700 +++ b/hotspot/src/share/vm/classfile/symbolTable.hpp Thu Apr 07 09:47:48 2016 -0700 @@ -175,6 +175,7 @@ } static unsigned int hash_symbol(const char* s, int len); + static unsigned int hash_shared_symbol(const char* s, int len); static Symbol* lookup(const char* name, int len, TRAPS); // lookup only, won't add. Also calculate hash.
--- a/hotspot/src/share/vm/classfile/systemDictionary.cpp Mon Apr 04 13:40:18 2016 -0700 +++ b/hotspot/src/share/vm/classfile/systemDictionary.cpp Thu Apr 07 09:47:48 2016 -0700 @@ -45,6 +45,7 @@ #include "interpreter/interpreter.hpp" #include "memory/filemap.hpp" #include "memory/oopFactory.hpp" +#include "memory/resourceArea.hpp" #include "oops/instanceKlass.hpp" #include "oops/instanceRefKlass.hpp" #include "oops/klass.inline.hpp" @@ -67,6 +68,7 @@ #include "runtime/signature.hpp" #include "services/classLoadingService.hpp" #include "services/threadService.hpp" +#include "trace/traceMacros.hpp" #include "utilities/macros.hpp" #include "utilities/ticks.hpp" #if INCLUDE_CDS @@ -435,7 +437,7 @@ if (log_is_enabled(Debug, protectiondomain)) { ResourceMark rm; // Print out trace information - outputStream* log = LogHandle(protectiondomain)::debug_stream(); + outputStream* log = Log(protectiondomain)::debug_stream(); log->print_cr("Checking package access"); log->print("class loader: "); class_loader()->print_value_on(log); log->print(" protection domain: "); protection_domain()->print_value_on(log); @@ -1650,6 +1652,8 @@ } + TRACE_KLASS_DEFINITION(k, THREAD); + } // Support parallel classloading
--- a/hotspot/src/share/vm/classfile/verificationType.cpp Mon Apr 04 13:40:18 2016 -0700 +++ b/hotspot/src/share/vm/classfile/verificationType.cpp Thu Apr 07 09:47:48 2016 -0700 @@ -61,7 +61,7 @@ Klass* obj = SystemDictionary::resolve_or_fail( name(), Handle(THREAD, klass->class_loader()), Handle(THREAD, klass->protection_domain()), true, CHECK_false); - if (log_is_enabled(Info, classresolve)) { + if (log_is_enabled(Debug, classresolve)) { Verifier::trace_class_resolution(obj, klass()); } @@ -80,7 +80,7 @@ Klass* from_class = SystemDictionary::resolve_or_fail( from.name(), Handle(THREAD, klass->class_loader()), Handle(THREAD, klass->protection_domain()), true, CHECK_false); - if (log_is_enabled(Info, classresolve)) { + if (log_is_enabled(Debug, classresolve)) { Verifier::trace_class_resolution(from_class, klass()); } return InstanceKlass::cast(from_class)->is_subclass_of(this_class());
--- a/hotspot/src/share/vm/classfile/verifier.cpp Mon Apr 04 13:40:18 2016 -0700 +++ b/hotspot/src/share/vm/classfile/verifier.cpp Thu Apr 07 09:47:48 2016 -0700 @@ -33,6 +33,7 @@ #include "classfile/vmSymbols.hpp" #include "interpreter/bytecodes.hpp" #include "interpreter/bytecodeStream.hpp" +#include "logging/log.hpp" #include "memory/oopFactory.hpp" #include "memory/resourceArea.hpp" #include "oops/instanceKlass.hpp" @@ -106,9 +107,9 @@ const char* resolve = resolve_class->external_name(); // print in a single call to reduce interleaving between threads if (source_file != NULL) { - log_info(classresolve)("%s %s %s (verification)", verify, resolve, source_file); + log_debug(classresolve)("%s %s %s (verification)", verify, resolve, source_file); } else { - log_info(classresolve)("%s %s (verification)", verify, resolve); + log_debug(classresolve)("%s %s (verification)", verify, resolve); } } @@ -176,9 +177,7 @@ if (can_failover && !HAS_PENDING_EXCEPTION && (exception_name == vmSymbols::java_lang_VerifyError() || exception_name == vmSymbols::java_lang_ClassFormatError())) { - if (VerboseVerification) { - tty->print_cr("Fail over class verification to old verifier for: %s", klassName); - } + log_info(verification)("Fail over class verification to old verifier for: %s", klassName); log_info(classinit)("Fail over class verification to old verifier for: %s", klassName); exception_name = inference_verify( klass, message_buffer, message_buffer_len, THREAD); @@ -192,10 +191,10 @@ } if (log_is_enabled(Info, classinit)){ - log_end_verification(LogHandle(classinit)::info_stream(), klassName, exception_name, THREAD); + log_end_verification(Log(classinit)::info_stream(), klassName, exception_name, THREAD); } - if (VerboseVerification){ - log_end_verification(tty, klassName, exception_name, THREAD); + if (log_is_enabled(Info, verification)){ + log_end_verification(Log(verification)::info_stream(), klassName, exception_name, THREAD); } if (HAS_PENDING_EXCEPTION) { @@ -206,7 +205,7 @@ ResourceMark rm(THREAD); instanceKlassHandle kls = SystemDictionary::resolve_or_fail(exception_name, true, CHECK_false); - if (log_is_enabled(Info, classresolve)) { + if (log_is_enabled(Debug, classresolve)) { Verifier::trace_class_resolution(kls(), klass()); } @@ -269,9 +268,7 @@ } ResourceMark rm(THREAD); - if (VerboseVerification) { - tty->print_cr("Verifying class %s with old format", klass->external_name()); - } + log_info(verification)("Verifying class %s with old format", klass->external_name()); jclass cls = (jclass) JNIHandles::make_local(env, klass->java_mirror()); jint result; @@ -583,10 +580,7 @@ } void ClassVerifier::verify_class(TRAPS) { - if (VerboseVerification) { - tty->print_cr("Verifying class %s with new format", - _klass->external_name()); - } + log_info(verification)("Verifying class %s with new format", _klass->external_name()); Array<Method*>* methods = _klass->methods(); int num_methods = methods->length(); @@ -606,10 +600,7 @@ } if (was_recursively_verified()){ - if (VerboseVerification){ - tty->print_cr("Recursive verification detected for: %s", - _klass->external_name()); - } + log_info(verification)("Recursive verification detected for: %s", _klass->external_name()); log_info(classinit)("Recursive verification detected for: %s", _klass->external_name()); } @@ -618,9 +609,7 @@ void ClassVerifier::verify_method(const methodHandle& m, TRAPS) { HandleMark hm(THREAD); _method = m; // initialize _method - if (VerboseVerification) { - tty->print_cr("Verifying method %s", m->name_and_sig_as_C_string()); - } + log_info(verification)("Verifying method %s", m->name_and_sig_as_C_string()); // For clang, the only good constant format string is a literal constant format string. #define bad_type_msg "Bad type on operand stack in %s" @@ -667,8 +656,9 @@ StackMapTable stackmap_table(&reader, ¤t_frame, max_locals, max_stack, code_data, code_length, CHECK_VERIFY(this)); - if (VerboseVerification) { - stackmap_table.print_on(tty); + if (log_is_enabled(Info, verification)) { + ResourceMark rm(THREAD); + stackmap_table.print_on(Log(verification)::info_stream()); } RawBytecodeStream bcs(m); @@ -708,12 +698,11 @@ VerificationType type, type2; VerificationType atype; -#ifndef PRODUCT - if (VerboseVerification) { - current_frame.print_on(tty); - tty->print_cr("offset = %d, opcode = %s", bci, Bytecodes::name(opcode)); + if (log_is_enabled(Info, verification)) { + ResourceMark rm(THREAD); + current_frame.print_on(Log(verification)::info_stream()); + log_info(verification)("offset = %d, opcode = %s", bci, Bytecodes::name(opcode)); } -#endif // Make sure wide instruction is in correct format if (bcs.is_wide()) { @@ -2005,7 +1994,7 @@ name, Handle(THREAD, loader), Handle(THREAD, protection_domain), true, THREAD); - if (log_is_enabled(Info, classresolve)) { + if (log_is_enabled(Debug, classresolve)) { instanceKlassHandle cur_class = current_class(); Verifier::trace_class_resolution(kls, cur_class()); } @@ -2533,11 +2522,10 @@ verify_error(ErrorContext::bad_code(bci), "Bad <init> method call from after the start of a try block"); return; - } else if (VerboseVerification) { - ResourceMark rm; - tty->print_cr( - "Survived call to ends_in_athrow(): %s", - current_class()->name()->as_C_string()); + } else if (log_is_enabled(Info, verification)) { + ResourceMark rm(THREAD); + log_info(verification)("Survived call to ends_in_athrow(): %s", + current_class()->name()->as_C_string()); } } }
--- a/hotspot/src/share/vm/classfile/vmSymbols.hpp Mon Apr 04 13:40:18 2016 -0700 +++ b/hotspot/src/share/vm/classfile/vmSymbols.hpp Thu Apr 07 09:47:48 2016 -0700 @@ -102,7 +102,6 @@ template(java_security_SecureClassLoader, "java/security/SecureClassLoader") \ template(java_net_URL, "java/net/URL") \ template(java_util_jar_Manifest, "java/util/jar/Manifest") \ - template(impliesCreateAccessControlContext_name, "impliesCreateAccessControlContext") \ template(java_io_OutputStream, "java/io/OutputStream") \ template(java_io_Reader, "java/io/Reader") \ template(java_io_BufferedReader, "java/io/BufferedReader") \ @@ -327,7 +326,6 @@ template(java_lang_StackFrameInfo, "java/lang/StackFrameInfo") \ template(java_lang_LiveStackFrameInfo, "java/lang/LiveStackFrameInfo") \ template(java_lang_StackStreamFactory_AbstractStackWalker, "java/lang/StackStreamFactory$AbstractStackWalker") \ - template(doStackWalk_name, "doStackWalk") \ template(doStackWalk_signature, "(JIIII)Ljava/lang/Object;") \ template(asPrimitive_name, "asPrimitive") \ template(asPrimitive_int_signature, "(I)Ljava/lang/LiveStackFrame$PrimitiveValue;") \ @@ -378,14 +376,13 @@ template(type_name, "type") \ template(findNative_name, "findNative") \ template(deadChild_name, "deadChild") \ - template(addClass_name, "addClass") \ - template(throwIllegalAccessError_name, "throwIllegalAccessError") \ template(getFromClass_name, "getFromClass") \ template(dispatch_name, "dispatch") \ template(getSystemClassLoader_name, "getSystemClassLoader") \ template(fillInStackTrace_name, "fillInStackTrace") \ template(getCause_name, "getCause") \ template(initCause_name, "initCause") \ + template(depth_name, "depth") \ template(setProperty_name, "setProperty") \ template(getProperty_name, "getProperty") \ template(context_name, "context") \ @@ -473,10 +470,6 @@ template(url_code_signer_array_void_signature, "(Ljava/net/URL;[Ljava/security/CodeSigner;)V") \ template(module_entry_name, "module_entry") \ \ - /* non-intrinsic name/signature pairs: */ \ - template(register_method_name, "register") \ - do_alias(register_method_signature, object_void_signature) \ - \ /* name symbols needed by intrinsics */ \ VM_INTRINSICS_DO(VM_INTRINSIC_IGNORE, VM_SYMBOL_IGNORE, template, VM_SYMBOL_IGNORE, VM_ALIAS_IGNORE) \ \
--- a/hotspot/src/share/vm/code/codeBlob.cpp Mon Apr 04 13:40:18 2016 -0700 +++ b/hotspot/src/share/vm/code/codeBlob.cpp Thu Apr 07 09:47:48 2016 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,6 +31,7 @@ #include "interpreter/bytecode.hpp" #include "memory/allocation.inline.hpp" #include "memory/heap.hpp" +#include "memory/resourceArea.hpp" #include "oops/oop.inline.hpp" #include "prims/forte.hpp" #include "runtime/handles.inline.hpp"
--- a/hotspot/src/share/vm/code/compiledIC.cpp Mon Apr 04 13:40:18 2016 -0700 +++ b/hotspot/src/share/vm/code/compiledIC.cpp Thu Apr 07 09:47:48 2016 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -33,6 +33,7 @@ #include "interpreter/linkResolver.hpp" #include "memory/metadataFactory.hpp" #include "memory/oopFactory.hpp" +#include "memory/resourceArea.hpp" #include "oops/method.hpp" #include "oops/oop.inline.hpp" #include "oops/symbol.hpp"
--- a/hotspot/src/share/vm/code/dependencies.cpp Mon Apr 04 13:40:18 2016 -0700 +++ b/hotspot/src/share/vm/code/dependencies.cpp Thu Apr 07 09:47:48 2016 -0700 @@ -30,6 +30,7 @@ #include "classfile/javaClasses.inline.hpp" #include "code/dependencies.hpp" #include "compiler/compileLog.hpp" +#include "memory/resourceArea.hpp" #include "oops/oop.inline.hpp" #include "oops/objArrayKlass.hpp" #include "runtime/handles.hpp"
--- a/hotspot/src/share/vm/code/nmethod.cpp Mon Apr 04 13:40:18 2016 -0700 +++ b/hotspot/src/share/vm/code/nmethod.cpp Thu Apr 07 09:47:48 2016 -0700 @@ -36,6 +36,7 @@ #include "compiler/directivesParser.hpp" #include "compiler/disassembler.hpp" #include "interpreter/bytecode.hpp" +#include "memory/resourceArea.hpp" #include "oops/methodData.hpp" #include "oops/oop.inline.hpp" #include "prims/jvmtiRedefineClassesTrace.hpp" @@ -1321,7 +1322,7 @@ // Break cycle between nmethod & method if (log_is_enabled(Trace, classunload)) { - outputStream* log = LogHandle(classunload)::trace_stream(); + outputStream* log = Log(classunload)::trace_stream(); log->print_cr("making nmethod " INTPTR_FORMAT " unloadable, Method*(" INTPTR_FORMAT "), cause(" INTPTR_FORMAT ")",
--- a/hotspot/src/share/vm/compiler/compileBroker.cpp Mon Apr 04 13:40:18 2016 -0700 +++ b/hotspot/src/share/vm/compiler/compileBroker.cpp Thu Apr 07 09:47:48 2016 -0700 @@ -32,8 +32,10 @@ #include "compiler/compileLog.hpp" #include "compiler/compilerOracle.hpp" #include "compiler/directivesParser.hpp" +#include "gc/shared/referencePendingListLocker.hpp" #include "interpreter/linkResolver.hpp" #include "memory/allocation.inline.hpp" +#include "memory/resourceArea.hpp" #include "oops/methodData.hpp" #include "oops/method.hpp" #include "oops/oop.inline.hpp" @@ -48,6 +50,7 @@ #include "runtime/os.hpp" #include "runtime/sharedRuntime.hpp" #include "runtime/sweeper.hpp" +#include "runtime/timerTrace.hpp" #include "trace/tracing.hpp" #include "utilities/dtrace.hpp" #include "utilities/events.hpp" @@ -901,7 +904,7 @@ // the pending list lock or a 3-way deadlock may occur // between the reference handler thread, a GC (instigated // by a compiler thread), and compiled method registration. - if (InstanceRefKlass::owns_pending_list_lock(JavaThread::current())) { + if (ReferencePendingListLocker::is_locked_by_self()) { return; }
--- a/hotspot/src/share/vm/compiler/compileTask.cpp Mon Apr 04 13:40:18 2016 -0700 +++ b/hotspot/src/share/vm/compiler/compileTask.cpp Thu Apr 07 09:47:48 2016 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,6 +27,7 @@ #include "compiler/compileLog.hpp" #include "compiler/compileBroker.hpp" #include "compiler/compilerDirectives.hpp" +#include "memory/resourceArea.hpp" CompileTask* CompileTask::_task_free_list = NULL; #ifdef ASSERT
--- a/hotspot/src/share/vm/compiler/compilerDirectives.cpp Mon Apr 04 13:40:18 2016 -0700 +++ b/hotspot/src/share/vm/compiler/compilerDirectives.cpp Thu Apr 07 09:47:48 2016 -0700 @@ -28,6 +28,7 @@ #include "compiler/abstractCompiler.hpp" #include "compiler/compilerDirectives.hpp" #include "compiler/compilerOracle.hpp" +#include "memory/resourceArea.hpp" CompilerDirectives::CompilerDirectives() :_match(NULL), _next(NULL), _ref_count(0) { _c1_store = new DirectiveSet(this);
--- a/hotspot/src/share/vm/compiler/directivesParser.cpp Mon Apr 04 13:40:18 2016 -0700 +++ b/hotspot/src/share/vm/compiler/directivesParser.cpp Thu Apr 07 09:47:48 2016 -0700 @@ -26,6 +26,7 @@ #include "compiler/compileBroker.hpp" #include "compiler/directivesParser.hpp" #include "memory/allocation.inline.hpp" +#include "memory/resourceArea.hpp" #include "runtime/os.hpp" #include <string.h>
--- a/hotspot/src/share/vm/compiler/disassembler.cpp Mon Apr 04 13:40:18 2016 -0700 +++ b/hotspot/src/share/vm/compiler/disassembler.cpp Thu Apr 07 09:47:48 2016 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,6 +28,7 @@ #include "compiler/disassembler.hpp" #include "gc/shared/cardTableModRefBS.hpp" #include "gc/shared/collectedHeap.hpp" +#include "memory/resourceArea.hpp" #include "oops/oop.inline.hpp" #include "runtime/fprofiler.hpp" #include "runtime/handles.inline.hpp"
--- a/hotspot/src/share/vm/compiler/methodLiveness.cpp Mon Apr 04 13:40:18 2016 -0700 +++ b/hotspot/src/share/vm/compiler/methodLiveness.cpp Thu Apr 07 09:47:48 2016 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,6 +30,8 @@ #include "interpreter/bytecode.hpp" #include "interpreter/bytecodes.hpp" #include "memory/allocation.inline.hpp" +#include "memory/resourceArea.hpp" +#include "runtime/timerTrace.hpp" #include "utilities/bitMap.inline.hpp" // The MethodLiveness class performs a simple liveness analysis on a method
--- a/hotspot/src/share/vm/compiler/methodMatcher.cpp Mon Apr 04 13:40:18 2016 -0700 +++ b/hotspot/src/share/vm/compiler/methodMatcher.cpp Thu Apr 07 09:47:48 2016 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,7 @@ #include "precompiled.hpp" #include "compiler/methodMatcher.hpp" #include "memory/oopFactory.hpp" +#include "memory/resourceArea.hpp" #include "oops/oop.inline.hpp" // The JVM specification defines the allowed characters.
--- a/hotspot/src/share/vm/gc/cms/compactibleFreeListSpace.cpp Mon Apr 04 13:40:18 2016 -0700 +++ b/hotspot/src/share/vm/gc/cms/compactibleFreeListSpace.cpp Thu Apr 07 09:47:48 2016 -0700 @@ -30,7 +30,6 @@ #include "gc/shared/blockOffsetTable.inline.hpp" #include "gc/shared/collectedHeap.inline.hpp" #include "gc/shared/genCollectedHeap.hpp" -#include "gc/shared/liveRange.hpp" #include "gc/shared/space.inline.hpp" #include "gc/shared/spaceDecorator.hpp" #include "memory/allocation.inline.hpp" @@ -501,7 +500,7 @@ void CompactibleFreeListSpace::reportFreeListStatistics(const char* title) const { assert_lock_strong(&_freelistLock); - LogHandle(gc, freelist, stats) log; + Log(gc, freelist, stats) log; if (!log.is_debug()) { return; } @@ -1931,11 +1930,6 @@ if (blk->_ptr == NULL) { refillLinearAllocBlock(blk); } - if (PrintMiscellaneous && Verbose) { - if (blk->_word_size == 0) { - warning("CompactibleFreeListSpace(prologue):: Linear allocation failure"); - } - } } void @@ -2205,7 +2199,7 @@ } } if (res == 0) { - LogHandle(gc, verify) log; + Log(gc, verify) log; log.error("Livelock: no rank reduction!"); log.error(" Current: addr = " PTR_FORMAT ", size = " SIZE_FORMAT ", obj = %s, live = %s \n" " Previous: addr = " PTR_FORMAT ", size = " SIZE_FORMAT ", obj = %s, live = %s \n", @@ -2379,14 +2373,14 @@ void CompactibleFreeListSpace::printFLCensus(size_t sweep_count) const { assert_lock_strong(&_freelistLock); - LogHandle(gc, freelist, census) log; - if (!log.is_debug()) { + LogTarget(Debug, gc, freelist, census) log; + if (!log.is_enabled()) { return; } AdaptiveFreeList<FreeChunk> total; - log.debug("end sweep# " SIZE_FORMAT, sweep_count); + log.print("end sweep# " SIZE_FORMAT, sweep_count); ResourceMark rm; - outputStream* out = log.debug_stream(); + outputStream* out = log.stream(); AdaptiveFreeList<FreeChunk>::print_labels_on(out, "size"); size_t total_free = 0; for (size_t i = IndexSetStart; i < IndexSetSize; i += IndexSetStride) { @@ -2408,8 +2402,8 @@ total.set_split_deaths(total.split_deaths() + fl->split_deaths()); } total.print_on(out, "TOTAL"); - log.debug("Total free in indexed lists " SIZE_FORMAT " words", total_free); - log.debug("growth: %8.5f deficit: %8.5f", + log.print("Total free in indexed lists " SIZE_FORMAT " words", total_free); + log.print("growth: %8.5f deficit: %8.5f", (double)(total.split_births()+total.coal_births()-total.split_deaths()-total.coal_deaths())/ (total.prev_sweep() != 0 ? (double)total.prev_sweep() : 1.0), (double)(total.desired() - total.count())/(total.desired() != 0 ? (double)total.desired() : 1.0)); @@ -2541,7 +2535,7 @@ _blocks_to_claim[i].sample( MAX2(CMSOldPLABMin, MIN2(CMSOldPLABMax, - _global_num_blocks[i]/(_global_num_workers[i]*CMSOldPLABNumRefills)))); + _global_num_blocks[i]/_global_num_workers[i]/CMSOldPLABNumRefills))); } // Reset counters for next round _global_num_workers[i] = 0;
--- a/hotspot/src/share/vm/gc/cms/concurrentMarkSweepGeneration.cpp Mon Apr 04 13:40:18 2016 -0700 +++ b/hotspot/src/share/vm/gc/cms/concurrentMarkSweepGeneration.cpp Thu Apr 07 09:47:48 2016 -0700 @@ -502,7 +502,7 @@ { MutexLockerEx x(_markBitMap.lock(), Mutex::_no_safepoint_check_flag); if (!_markBitMap.allocate(_span)) { - warning("Failed to allocate CMS Bit Map"); + log_warning(gc)("Failed to allocate CMS Bit Map"); return; } assert(_markBitMap.covers(_span), "_markBitMap inconsistency?"); @@ -513,7 +513,7 @@ } if (!_markStack.allocate(MarkStackSize)) { - warning("Failed to allocate CMS Marking Stack"); + log_warning(gc)("Failed to allocate CMS Marking Stack"); return; } @@ -527,8 +527,7 @@ _conc_workers = new YieldingFlexibleWorkGang("CMS Thread", ConcGCThreads, true); if (_conc_workers == NULL) { - warning("GC/CMS: _conc_workers allocation failure: " - "forcing -CMSConcurrentMTEnabled"); + log_warning(gc)("GC/CMS: _conc_workers allocation failure: forcing -CMSConcurrentMTEnabled"); CMSConcurrentMTEnabled = false; } else { _conc_workers->initialize_workers(); @@ -559,7 +558,7 @@ && num_queues > 0) { _task_queues = new OopTaskQueueSet(num_queues); if (_task_queues == NULL) { - warning("task_queues allocation failure."); + log_warning(gc)("task_queues allocation failure."); return; } _hash_seed = NEW_C_HEAP_ARRAY(int, num_queues, mtGC); @@ -567,7 +566,7 @@ for (i = 0; i < num_queues; i++) { PaddedOopTaskQueue *q = new PaddedOopTaskQueue(); if (q == NULL) { - warning("work_queue allocation failure."); + log_warning(gc)("work_queue allocation failure."); return; } _task_queues->register_queue(i, q); @@ -694,7 +693,7 @@ // At a promotion failure dump information on block layout in heap // (cms old generation). void ConcurrentMarkSweepGeneration::promotion_failure_occurred() { - LogHandle(gc, promotion) log; + Log(gc, promotion) log; if (log.is_trace()) { ResourceMark rm; cmsSpace()->dump_at_safepoint_with_locks(collector(), log.trace_stream()); @@ -753,7 +752,7 @@ size_t desired_capacity = (size_t)(used() / ((double) 1 - desired_free_percentage)); assert(desired_capacity >= capacity(), "invalid expansion size"); size_t expand_bytes = MAX2(desired_capacity - capacity(), MinHeapDeltaBytes); - LogHandle(gc) log; + Log(gc) log; if (log.is_trace()) { size_t desired_capacity = (size_t)(used() / ((double) 1 - desired_free_percentage)); log.trace("From compute_new_size: "); @@ -1118,7 +1117,7 @@ // ------------------------------------------------------------------ // Print out lots of information which affects the initiation of // a collection. - LogHandle(gc) log; + Log(gc) log; if (log.is_trace() && stats().valid()) { log.trace("CMSCollector shouldConcurrentCollect: "); ResourceMark rm; @@ -1413,7 +1412,7 @@ if (_foregroundGCShouldWait) { // We are going to be waiting for action for the CMS thread; // it had better not be gone (for instance at shutdown)! - assert(ConcurrentMarkSweepThread::cmst() != NULL, + assert(ConcurrentMarkSweepThread::cmst() != NULL && !ConcurrentMarkSweepThread::cmst()->has_terminated(), "CMS thread must be running"); // Wait here until the background collector gives us the go-ahead ConcurrentMarkSweepThread::clear_CMS_flag( @@ -1519,7 +1518,7 @@ gch->pre_full_gc_dump(gc_timer); - GCTraceTime(Trace, gc) t("CMS:MSC"); + GCTraceTime(Trace, gc, phases) t("CMS:MSC"); // Temporarily widen the span of the weak reference processing to // the entire heap. @@ -1606,7 +1605,7 @@ } void CMSCollector::print_eden_and_survivor_chunk_arrays() { - LogHandle(gc, heap) log; + Log(gc, heap) log; if (!log.is_trace()) { return; } @@ -2222,7 +2221,7 @@ bool do_bit(size_t offset) { HeapWord* addr = _marks->offsetToHeapWord(offset); if (!_marks->isMarked(addr)) { - LogHandle(gc, verify) log; + Log(gc, verify) log; ResourceMark rm; oop(addr)->print_on(log.error_stream()); log.error(" (" INTPTR_FORMAT " should have been marked)", p2i(addr)); @@ -2235,7 +2234,7 @@ }; bool CMSCollector::verify_after_remark() { - GCTraceTime(Info, gc, verify) tm("Verifying CMS Marking."); + GCTraceTime(Info, gc, phases, verify) tm("Verifying CMS Marking."); MutexLockerEx ml(verification_mark_bm()->lock(), Mutex::_no_safepoint_check_flag); static bool init = false; @@ -2287,17 +2286,16 @@ // all marking, then check if the new marks-vector is // a subset of the CMS marks-vector. verify_after_remark_work_1(); - } else if (CMSRemarkVerifyVariant == 2) { + } else { + guarantee(CMSRemarkVerifyVariant == 2, "Range checking for CMSRemarkVerifyVariant should guarantee 1 or 2"); // In this second variant of verification, we flag an error // (i.e. an object reachable in the new marks-vector not reachable // in the CMS marks-vector) immediately, also indicating the // identify of an object (A) that references the unmarked object (B) -- // presumably, a mutation to A failed to be picked up by preclean/remark? verify_after_remark_work_2(); - } else { - warning("Unrecognized value " UINTX_FORMAT " for CMSRemarkVerifyVariant", - CMSRemarkVerifyVariant); - } + } + return true; } @@ -2349,7 +2347,7 @@ VerifyMarkedClosure vcl(markBitMap()); verification_mark_bm()->iterate(&vcl); if (vcl.failed()) { - LogHandle(gc, verify) log; + Log(gc, verify) log; log.error("Failed marking verification after remark"); ResourceMark rm; gch->print_on(log.error_stream()); @@ -2820,7 +2818,7 @@ // CMS collection cycle. setup_cms_unloading_and_verification_state(); - GCTraceTime(Trace, gc) ts("checkpointRootsInitialWork", _gc_timer_cm); + GCTraceTime(Trace, gc, phases) ts("checkpointRootsInitialWork", _gc_timer_cm); // Reset all the PLAB chunk arrays if necessary. if (_survivor_plab_array != NULL && !CMSPLABRecordAlways) { @@ -3650,7 +3648,7 @@ // XXX FIX ME!!! YSR size_t loops = 0, workdone = 0, cumworkdone = 0, waited = 0; while (!(should_abort_preclean() || - ConcurrentMarkSweepThread::should_terminate())) { + ConcurrentMarkSweepThread::cmst()->should_terminate())) { workdone = preclean_work(CMSPrecleanRefLists2, CMSPrecleanSurvivors2); cumworkdone += workdone; loops++; @@ -4104,8 +4102,6 @@ // expect it to be false and set to true FlagSetting fl(gch->_is_gc_active, false); - GCTraceTime(Trace, gc) tm("Pause Scavenge Before Remark", _gc_timer_cm); - gch->do_collection(true, // full (i.e. force, see below) false, // !clear_all_soft_refs 0, // size @@ -4123,7 +4119,7 @@ } void CMSCollector::checkpointRootsFinalWork() { - GCTraceTime(Trace, gc) tm("checkpointRootsFinalWork", _gc_timer_cm); + GCTraceTime(Trace, gc, phases) tm("checkpointRootsFinalWork", _gc_timer_cm); assert(haveFreelistLocks(), "must have free list locks"); assert_lock_strong(bitMapLock()); @@ -4173,10 +4169,10 @@ // the most recent young generation GC, minus those cleaned up by the // concurrent precleaning. if (CMSParallelRemarkEnabled) { - GCTraceTime(Debug, gc) t("Rescan (parallel)", _gc_timer_cm); + GCTraceTime(Debug, gc, phases) t("Rescan (parallel)", _gc_timer_cm); do_remark_parallel(); } else { - GCTraceTime(Debug, gc) t("Rescan (non-parallel)", _gc_timer_cm); + GCTraceTime(Debug, gc, phases) t("Rescan (non-parallel)", _gc_timer_cm); do_remark_non_parallel(); } } @@ -4184,7 +4180,7 @@ verify_overflow_empty(); { - GCTraceTime(Trace, gc) ts("refProcessingWork", _gc_timer_cm); + GCTraceTime(Trace, gc, phases) ts("refProcessingWork", _gc_timer_cm); refProcessingWork(); } verify_work_stacks_empty(); @@ -4907,7 +4903,7 @@ NULL, // space is set further below &_markBitMap, &_markStack, &mrias_cl); { - GCTraceTime(Trace, gc) t("Grey Object Rescan", _gc_timer_cm); + GCTraceTime(Trace, gc, phases) t("Grey Object Rescan", _gc_timer_cm); // Iterate over the dirty cards, setting the corresponding bits in the // mod union table. { @@ -4941,7 +4937,7 @@ Universe::verify(); } { - GCTraceTime(Trace, gc) t("Root Rescan", _gc_timer_cm); + GCTraceTime(Trace, gc, phases) t("Root Rescan", _gc_timer_cm); verify_work_stacks_empty(); @@ -4963,7 +4959,7 @@ } { - GCTraceTime(Trace, gc) t("Visit Unhandled CLDs", _gc_timer_cm); + GCTraceTime(Trace, gc, phases) t("Visit Unhandled CLDs", _gc_timer_cm); verify_work_stacks_empty(); @@ -4982,7 +4978,7 @@ } { - GCTraceTime(Trace, gc) t("Dirty Klass Scan", _gc_timer_cm); + GCTraceTime(Trace, gc, phases) t("Dirty Klass Scan", _gc_timer_cm); verify_work_stacks_empty(); @@ -5186,7 +5182,7 @@ _span, &_markBitMap, &_markStack, &cmsKeepAliveClosure, false /* !preclean */); { - GCTraceTime(Debug, gc) t("Weak Refs Processing", _gc_timer_cm); + GCTraceTime(Debug, gc, phases) t("Reference Processing", _gc_timer_cm); ReferenceProcessorStats stats; if (rp->processing_is_mt()) { @@ -5228,7 +5224,7 @@ if (should_unload_classes()) { { - GCTraceTime(Debug, gc) t("Class Unloading", _gc_timer_cm); + GCTraceTime(Debug, gc, phases) t("Class Unloading", _gc_timer_cm); // Unload classes and purge the SystemDictionary. bool purged_class = SystemDictionary::do_unloading(&_is_alive_closure); @@ -5241,13 +5237,13 @@ } { - GCTraceTime(Debug, gc) t("Scrub Symbol Table", _gc_timer_cm); + GCTraceTime(Debug, gc, phases) t("Scrub Symbol Table", _gc_timer_cm); // Clean up unreferenced symbols in symbol table. SymbolTable::unlink(); } { - GCTraceTime(Debug, gc) t("Scrub String Table", _gc_timer_cm); + GCTraceTime(Debug, gc, phases) t("Scrub String Table", _gc_timer_cm); // Delete entries for dead interned strings. StringTable::unlink(&_is_alive_closure); } @@ -5657,13 +5653,13 @@ ReservedSpace brs(ReservedSpace::allocation_align_size_up( (_bmWordSize >> (_shifter + LogBitsPerByte)) + 1)); if (!brs.is_reserved()) { - warning("CMS bit map allocation failure"); + log_warning(gc)("CMS bit map allocation failure"); return false; } // For now we'll just commit all of the bit map up front. // Later on we'll try to be more parsimonious with swap. if (!_virtual_space.initialize(brs, brs.size())) { - warning("CMS bit map backing store failure"); + log_warning(gc)("CMS bit map backing store failure"); return false; } assert(_virtual_space.committed_size() == brs.size(), @@ -5749,11 +5745,11 @@ ReservedSpace rs(ReservedSpace::allocation_align_size_up( size * sizeof(oop))); if (!rs.is_reserved()) { - warning("CMSMarkStack allocation failure"); + log_warning(gc)("CMSMarkStack allocation failure"); return false; } if (!_virtual_space.initialize(rs, rs.size())) { - warning("CMSMarkStack backing store failure"); + log_warning(gc)("CMSMarkStack backing store failure"); return false; } assert(_virtual_space.committed_size() == rs.size(), @@ -5878,7 +5874,7 @@ if (_span.contains(addr)) { _verification_bm->mark(addr); if (!_cms_bm->isMarked(addr)) { - LogHandle(gc, verify) log; + Log(gc, verify) log; ResourceMark rm; oop(addr)->print_on(log.error_stream()); log.error(" (" INTPTR_FORMAT " should have been marked)", p2i(addr)); @@ -6659,7 +6655,7 @@ // Oop lies in _span and isn't yet grey or black _verification_bm->mark(addr); // now grey if (!_cms_bm->isMarked(addr)) { - LogHandle(gc, verify) log; + Log(gc, verify) log; ResourceMark rm; oop(addr)->print_on(log.error_stream()); log.error(" (" INTPTR_FORMAT " should have been marked)", p2i(addr)); @@ -7047,13 +7043,13 @@ } void SweepClosure::print_on(outputStream* st) const { - tty->print_cr("_sp = [" PTR_FORMAT "," PTR_FORMAT ")", - p2i(_sp->bottom()), p2i(_sp->end())); - tty->print_cr("_limit = " PTR_FORMAT, p2i(_limit)); - tty->print_cr("_freeFinger = " PTR_FORMAT, p2i(_freeFinger)); - NOT_PRODUCT(tty->print_cr("_last_fc = " PTR_FORMAT, p2i(_last_fc));) - tty->print_cr("_inFreeRange = %d, _freeRangeInFreeLists = %d, _lastFreeRangeCoalesced = %d", - _inFreeRange, _freeRangeInFreeLists, _lastFreeRangeCoalesced); + st->print_cr("_sp = [" PTR_FORMAT "," PTR_FORMAT ")", + p2i(_sp->bottom()), p2i(_sp->end())); + st->print_cr("_limit = " PTR_FORMAT, p2i(_limit)); + st->print_cr("_freeFinger = " PTR_FORMAT, p2i(_freeFinger)); + NOT_PRODUCT(st->print_cr("_last_fc = " PTR_FORMAT, p2i(_last_fc));) + st->print_cr("_inFreeRange = %d, _freeRangeInFreeLists = %d, _lastFreeRangeCoalesced = %d", + _inFreeRange, _freeRangeInFreeLists, _lastFreeRangeCoalesced); } #ifndef PRODUCT @@ -7066,8 +7062,10 @@ assert(_limit >= _sp->bottom() && _limit <= _sp->end(), "sweep _limit out of bounds"); if (inFreeRange()) { - warning("inFreeRange() should have been reset; dumping state of SweepClosure"); - print(); + Log(gc, sweep) log; + log.error("inFreeRange() should have been reset; dumping state of SweepClosure"); + ResourceMark rm; + print_on(log.error_stream()); ShouldNotReachHere(); }
--- a/hotspot/src/share/vm/gc/cms/concurrentMarkSweepThread.cpp Mon Apr 04 13:40:18 2016 -0700 +++ b/hotspot/src/share/vm/gc/cms/concurrentMarkSweepThread.cpp Thu Apr 07 09:47:48 2016 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,7 +28,7 @@ #include "gc/cms/concurrentMarkSweepThread.hpp" #include "gc/shared/gcId.hpp" #include "gc/shared/genCollectedHeap.hpp" -#include "oops/instanceRefKlass.hpp" +#include "gc/shared/referencePendingListLocker.hpp" #include "oops/oop.inline.hpp" #include "runtime/init.hpp" #include "runtime/interfaceSupport.hpp" @@ -42,16 +42,10 @@ ConcurrentMarkSweepThread* ConcurrentMarkSweepThread::_cmst = NULL; CMSCollector* ConcurrentMarkSweepThread::_collector = NULL; -bool ConcurrentMarkSweepThread::_should_terminate = false; int ConcurrentMarkSweepThread::_CMS_flag = CMS_nil; volatile jint ConcurrentMarkSweepThread::_pending_yields = 0; -SurrogateLockerThread* ConcurrentMarkSweepThread::_slt = NULL; -SurrogateLockerThread::SLT_msg_type - ConcurrentMarkSweepThread::_sltBuffer = SurrogateLockerThread::empty; -Monitor* ConcurrentMarkSweepThread::_sltMonitor = NULL; - ConcurrentMarkSweepThread::ConcurrentMarkSweepThread(CMSCollector* collector) : ConcurrentGCThread() { assert(UseConcMarkSweepGC, "UseConcMarkSweepGC should be set"); @@ -62,88 +56,58 @@ set_name("CMS Main Thread"); - if (os::create_thread(this, os::cgc_thread)) { - // An old comment here said: "Priority should be just less - // than that of VMThread". Since the VMThread runs at - // NearMaxPriority, the old comment was inaccurate, but - // changing the default priority to NearMaxPriority-1 - // could change current behavior, so the default of - // NearMaxPriority stays in place. - // - // Note that there's a possibility of the VMThread - // starving if UseCriticalCMSThreadPriority is on. - // That won't happen on Solaris for various reasons, - // but may well happen on non-Solaris platforms. - int native_prio; - if (UseCriticalCMSThreadPriority) { - native_prio = os::java_to_os_priority[CriticalPriority]; - } else { - native_prio = os::java_to_os_priority[NearMaxPriority]; - } - os::set_native_priority(this, native_prio); - - if (!DisableStartThread) { - os::start_thread(this); - } - } - _sltMonitor = SLT_lock; + // An old comment here said: "Priority should be just less + // than that of VMThread". Since the VMThread runs at + // NearMaxPriority, the old comment was inaccurate, but + // changing the default priority to NearMaxPriority-1 + // could change current behavior, so the default of + // NearMaxPriority stays in place. + // + // Note that there's a possibility of the VMThread + // starving if UseCriticalCMSThreadPriority is on. + // That won't happen on Solaris for various reasons, + // but may well happen on non-Solaris platforms. + create_and_start(UseCriticalCMSThreadPriority ? CriticalPriority : NearMaxPriority); } -void ConcurrentMarkSweepThread::run() { +void ConcurrentMarkSweepThread::run_service() { assert(this == cmst(), "just checking"); - initialize_in_thread(); - // From this time Thread::current() should be working. - assert(this == Thread::current(), "just checking"); if (BindCMSThreadToCPU && !os::bind_to_processor(CPUForCMSThread)) { - warning("Couldn't bind CMS thread to processor " UINTX_FORMAT, CPUForCMSThread); + log_warning(gc)("Couldn't bind CMS thread to processor " UINTX_FORMAT, CPUForCMSThread); } - // Wait until Universe::is_fully_initialized() + { - CMSLoopCountWarn loopX("CMS::run", "waiting for " - "Universe::is_fully_initialized()", 2); MutexLockerEx x(CGC_lock, true); set_CMS_flag(CMS_cms_wants_token); - // Wait until Universe is initialized and all initialization is completed. - while (!is_init_completed() && !Universe::is_fully_initialized() && - !_should_terminate) { - CGC_lock->wait(true, 200); - loopX.tick(); - } + assert(is_init_completed() && Universe::is_fully_initialized(), "ConcurrentGCThread::run() should have waited for this."); + // Wait until the surrogate locker thread that will do // pending list locking on our behalf has been created. // We cannot start the SLT thread ourselves since we need // to be a JavaThread to do so. CMSLoopCountWarn loopY("CMS::run", "waiting for SLT installation", 2); - while (_slt == NULL && !_should_terminate) { + while (!ReferencePendingListLocker::is_initialized() && !should_terminate()) { CGC_lock->wait(true, 200); loopY.tick(); } clear_CMS_flag(CMS_cms_wants_token); } - while (!_should_terminate) { + while (!should_terminate()) { sleepBeforeNextCycle(); - if (_should_terminate) break; + if (should_terminate()) break; GCIdMark gc_id_mark; GCCause::Cause cause = _collector->_full_gc_requested ? _collector->_full_gc_cause : GCCause::_cms_concurrent_mark; _collector->collect_in_background(cause); } - assert(_should_terminate, "just checking"); + // Check that the state of any protocol for synchronization // between background (CMS) and foreground collector is "clean" // (i.e. will not potentially block the foreground collector, // requiring action by us). verify_ok_to_terminate(); - // Signal that it is terminated - { - MutexLockerEx mu(Terminator_lock, - Mutex::_no_safepoint_check_flag); - assert(_cmst == this, "Weird!"); - _cmst = NULL; - Terminator_lock->notify(); - } } #ifndef PRODUCT @@ -157,39 +121,24 @@ // create and start a new ConcurrentMarkSweep Thread for given CMS generation ConcurrentMarkSweepThread* ConcurrentMarkSweepThread::start(CMSCollector* collector) { - if (!_should_terminate) { - assert(cmst() == NULL, "start() called twice?"); - ConcurrentMarkSweepThread* th = new ConcurrentMarkSweepThread(collector); - assert(cmst() == th, "Where did the just-created CMS thread go?"); - return th; - } - return NULL; + guarantee(_cmst == NULL, "start() called twice!"); + ConcurrentMarkSweepThread* th = new ConcurrentMarkSweepThread(collector); + assert(_cmst == th, "Where did the just-created CMS thread go?"); + return th; } -void ConcurrentMarkSweepThread::stop() { - // it is ok to take late safepoints here, if needed - { - MutexLockerEx x(Terminator_lock); - _should_terminate = true; - } - { // Now post a notify on CGC_lock so as to nudge - // CMS thread(s) that might be slumbering in - // sleepBeforeNextCycle. - MutexLockerEx x(CGC_lock, Mutex::_no_safepoint_check_flag); - CGC_lock->notify_all(); - } - { // Now wait until (all) CMS thread(s) have exited - MutexLockerEx x(Terminator_lock); - while(cmst() != NULL) { - Terminator_lock->wait(); - } - } +void ConcurrentMarkSweepThread::stop_service() { + // Now post a notify on CGC_lock so as to nudge + // CMS thread(s) that might be slumbering in + // sleepBeforeNextCycle. + MutexLockerEx x(CGC_lock, Mutex::_no_safepoint_check_flag); + CGC_lock->notify_all(); } void ConcurrentMarkSweepThread::threads_do(ThreadClosure* tc) { assert(tc != NULL, "Null ThreadClosure"); - if (_cmst != NULL) { - tc->do_thread(_cmst); + if (cmst() != NULL && !cmst()->has_terminated()) { + tc->do_thread(cmst()); } assert(Universe::is_fully_initialized(), "Called too early, make sure heap is fully initialized"); @@ -202,8 +151,8 @@ } void ConcurrentMarkSweepThread::print_all_on(outputStream* st) { - if (_cmst != NULL) { - _cmst->print_on(st); + if (cmst() != NULL && !cmst()->has_terminated()) { + cmst()->print_on(st); st->cr(); } if (_collector != NULL) { @@ -278,7 +227,7 @@ void ConcurrentMarkSweepThread::wait_on_cms_lock(long t_millis) { MutexLockerEx x(CGC_lock, Mutex::_no_safepoint_check_flag); - if (_should_terminate || _collector->_full_gc_requested) { + if (should_terminate() || _collector->_full_gc_requested) { return; } set_CMS_flag(CMS_cms_wants_token); // to provoke notifies @@ -307,7 +256,7 @@ unsigned int loop_count = 0; - while(!_should_terminate) { + while(!should_terminate()) { double now_time = os::elapsedTime(); long wait_time_millis; @@ -327,7 +276,7 @@ { MutexLockerEx x(CGC_lock, Mutex::_no_safepoint_check_flag); - if (_should_terminate || _collector->_full_gc_requested) { + if (should_terminate() || _collector->_full_gc_requested) { return; } set_CMS_flag(CMS_cms_wants_token); // to provoke notifies @@ -358,13 +307,13 @@ // Too many loops warning if(++loop_count == 0) { - warning("wait_on_cms_lock_for_scavenge() has looped %u times", loop_count - 1); + log_warning(gc)("wait_on_cms_lock_for_scavenge() has looped %u times", loop_count - 1); } } } void ConcurrentMarkSweepThread::sleepBeforeNextCycle() { - while (!_should_terminate) { + while (!should_terminate()) { if(CMSWaitDuration >= 0) { // Wait until the next synchronous GC, a concurrent full gc // request or a timeout, whichever is earlier. @@ -381,15 +330,3 @@ // and wait some more } } - -// Note: this method, although exported by the ConcurrentMarkSweepThread, -// which is a non-JavaThread, can only be called by a JavaThread. -// Currently this is done at vm creation time (post-vm-init) by the -// main/Primordial (Java)Thread. -// XXX Consider changing this in the future to allow the CMS thread -// itself to create this thread? -void ConcurrentMarkSweepThread::makeSurrogateLockerThread(TRAPS) { - assert(UseConcMarkSweepGC, "SLT thread needed only for CMS GC"); - assert(_slt == NULL, "SLT already created"); - _slt = SurrogateLockerThread::make(THREAD); -}
--- a/hotspot/src/share/vm/gc/cms/concurrentMarkSweepThread.hpp Mon Apr 04 13:40:18 2016 -0700 +++ b/hotspot/src/share/vm/gc/cms/concurrentMarkSweepThread.hpp Thu Apr 07 09:47:48 2016 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -37,17 +37,10 @@ friend class VMStructs; friend class ConcurrentMarkSweepGeneration; // XXX should remove friendship friend class CMSCollector; - public: - virtual void run(); private: - static ConcurrentMarkSweepThread* _cmst; - static CMSCollector* _collector; - static SurrogateLockerThread* _slt; - static SurrogateLockerThread::SLT_msg_type _sltBuffer; - static Monitor* _sltMonitor; - - static bool _should_terminate; + static ConcurrentMarkSweepThread* _cmst; + static CMSCollector* _collector; enum CMS_flag_type { CMS_nil = NoBits, @@ -72,13 +65,13 @@ // debugging void verify_ok_to_terminate() const PRODUCT_RETURN; + void run_service(); + void stop_service(); + public: // Constructor ConcurrentMarkSweepThread(CMSCollector* collector); - static void makeSurrogateLockerThread(TRAPS); - static SurrogateLockerThread* slt() { return _slt; } - static void threads_do(ThreadClosure* tc); // Printing @@ -91,8 +84,6 @@ // Create and start the CMS Thread, or stop it on shutdown static ConcurrentMarkSweepThread* start(CMSCollector* collector); - static void stop(); - static bool should_terminate() { return _should_terminate; } // Synchronization using CMS token static void synchronize(bool is_cms_thread); @@ -170,7 +161,7 @@ inline void tick() { _ticks++; if (CMSLoopWarn && _ticks % _threshold == 0) { - warning("%s has looped " INTX_FORMAT " times %s", _src, _ticks, _msg); + log_warning(gc)("%s has looped " INTX_FORMAT " times %s", _src, _ticks, _msg); } } };
--- a/hotspot/src/share/vm/gc/cms/parCardTableModRefBS.cpp Mon Apr 04 13:40:18 2016 -0700 +++ b/hotspot/src/share/vm/gc/cms/parCardTableModRefBS.cpp Thu Apr 07 09:47:48 2016 -0700 @@ -161,15 +161,6 @@ } } - -// If you want a talkative process_chunk_boundaries, -// then #define NOISY(x) x -#ifdef NOISY -#error "Encountered a global preprocessor flag, NOISY, which might clash with local definition to follow" -#else -#define NOISY(x) -#endif - void CardTableModRefBSForCTRS:: process_chunk_boundaries(Space* sp, @@ -197,10 +188,6 @@ assert(start_chunk_index >= lowest_non_clean_base_chunk_index, "Bounds error."); uintptr_t cur_chunk_index = start_chunk_index - lowest_non_clean_base_chunk_index; - NOISY(tty->print_cr("===========================================================================");) - NOISY(tty->print_cr(" process_chunk_boundary: Called with [" PTR_FORMAT "," PTR_FORMAT ")", - chunk_mr.start(), chunk_mr.end());) - // First, set "our" lowest_non_clean entry, which would be // used by the thread scanning an adjoining left chunk with // a non-array object straddling the mutual boundary. @@ -239,36 +226,18 @@ } } if (first_dirty_card != NULL) { - NOISY(tty->print_cr(" LNC: Found a dirty card at " PTR_FORMAT " in current chunk", - first_dirty_card);) assert(cur_chunk_index < lowest_non_clean_chunk_size, "Bounds error."); assert(lowest_non_clean[cur_chunk_index] == NULL, "Write exactly once : value should be stable hereafter for this round"); lowest_non_clean[cur_chunk_index] = first_dirty_card; - } NOISY(else { - tty->print_cr(" LNC: Found no dirty card in current chunk; leaving LNC entry NULL"); - // In the future, we could have this thread look for a non-NULL value to copy from its - // right neighbor (up to the end of the first object). - if (last_card_of_cur_chunk < last_card_of_first_obj) { - tty->print_cr(" LNC: BEWARE!!! first obj straddles past right end of chunk:\n" - " might be efficient to get value from right neighbor?"); - } - }) + } } else { // In this case we can help our neighbor by just asking them // to stop at our first card (even though it may not be dirty). - NOISY(tty->print_cr(" LNC: first block is not a non-array object; setting LNC to first card of current chunk");) assert(lowest_non_clean[cur_chunk_index] == NULL, "Write once : value should be stable hereafter"); jbyte* first_card_of_cur_chunk = byte_for(chunk_mr.start()); lowest_non_clean[cur_chunk_index] = first_card_of_cur_chunk; } - NOISY(tty->print_cr(" process_chunk_boundary: lowest_non_clean[" INTPTR_FORMAT "] = " PTR_FORMAT - " which corresponds to the heap address " PTR_FORMAT, - cur_chunk_index, lowest_non_clean[cur_chunk_index], - (lowest_non_clean[cur_chunk_index] != NULL) - ? addr_for(lowest_non_clean[cur_chunk_index]) - : NULL);) - NOISY(tty->print_cr("---------------------------------------------------------------------------");) // Next, set our own max_to_do, which will strictly/exclusively bound // the highest address that we will scan past the right end of our chunk. @@ -285,8 +254,6 @@ || oop(last_block)->is_objArray() // last_block is an array (precisely marked) || oop(last_block)->is_typeArray()) { max_to_do = chunk_mr.end(); - NOISY(tty->print_cr(" process_chunk_boundary: Last block on this card is not a non-array object;\n" - " max_to_do left at " PTR_FORMAT, max_to_do);) } else { assert(last_block < chunk_mr.end(), "Tautology"); // It is a non-array object that straddles the right boundary of this chunk. @@ -301,9 +268,6 @@ // subsequent cards still in this chunk must have been made // precisely; we can cap processing at the end of our chunk. max_to_do = chunk_mr.end(); - NOISY(tty->print_cr(" process_chunk_boundary: Head of last object on this card is not dirty;\n" - " max_to_do left at " PTR_FORMAT, - max_to_do);) } else { // The last object must be considered dirty, and extends onto the // following chunk. Look for a dirty card in that chunk that will @@ -323,8 +287,6 @@ cur <= last_card_of_last_obj; cur++) { const jbyte val = *cur; if (card_will_be_scanned(val)) { - NOISY(tty->print_cr(" Found a non-clean card " PTR_FORMAT " with value 0x%x", - cur, (int)val);) limit_card = cur; break; } else { assert(!card_may_have_been_dirty(val), "Error: card can't be skipped"); @@ -333,10 +295,6 @@ if (limit_card != NULL) { max_to_do = addr_for(limit_card); assert(limit_card != NULL && max_to_do != NULL, "Error"); - NOISY(tty->print_cr(" process_chunk_boundary: Found a dirty card at " PTR_FORMAT - " max_to_do set at " PTR_FORMAT " which is before end of last block in chunk: " - PTR_FORMAT " + " PTR_FORMAT " = " PTR_FORMAT, - limit_card, max_to_do, last_block, last_block_size, (last_block+last_block_size));) } else { // The following is a pessimistic value, because it's possible // that a dirty card on a subsequent chunk has been cleared by @@ -346,10 +304,6 @@ limit_card = last_card_of_last_obj; max_to_do = last_block + last_block_size; assert(limit_card != NULL && max_to_do != NULL, "Error"); - NOISY(tty->print_cr(" process_chunk_boundary: Found no dirty card before end of last block in chunk\n" - " Setting limit_card to " PTR_FORMAT - " and max_to_do " PTR_FORMAT " + " PTR_FORMAT " = " PTR_FORMAT, - limit_card, last_block, last_block_size, max_to_do);) } assert(0 < cur_chunk_index+1 && cur_chunk_index+1 < lowest_non_clean_chunk_size, "Bounds error."); @@ -382,7 +336,6 @@ "[" PTR_FORMAT "," PTR_FORMAT ") -> [" PTR_FORMAT "," PTR_FORMAT ")", p2i(sp->used_region().start()), p2i(sp->used_region().end()), p2i(used.start()), p2i(used.end())); - NOISY(tty->print_cr(" process_chunk_boundary: heap expanded; explicitly bounding last_chunk");) last_chunk_index_to_check = last_chunk_index; } for (uintptr_t lnc_index = cur_chunk_index + 1; @@ -392,9 +345,6 @@ if (lnc_card != NULL) { // we can stop at the first non-NULL entry we find if (lnc_card <= limit_card) { - NOISY(tty->print_cr(" process_chunk_boundary: LNC card " PTR_FORMAT " is lower than limit_card " PTR_FORMAT, - " max_to_do will be lowered to " PTR_FORMAT " from " PTR_FORMAT, - lnc_card, limit_card, addr_for(lnc_card), max_to_do);) limit_card = lnc_card; max_to_do = addr_for(limit_card); assert(limit_card != NULL && max_to_do != NULL, "Error"); @@ -410,9 +360,6 @@ assert(max_to_do != NULL, "OOPS 2!"); } else { max_to_do = used.end(); - NOISY(tty->print_cr(" process_chunk_boundary: Last chunk of this space;\n" - " max_to_do left at " PTR_FORMAT, - max_to_do);) } assert(max_to_do != NULL, "OOPS 3!"); // Now we can set the closure we're using so it doesn't to beyond @@ -421,11 +368,8 @@ #ifndef PRODUCT dcto_cl->set_last_bottom(max_to_do); #endif - NOISY(tty->print_cr("===========================================================================\n");) } -#undef NOISY - void CardTableModRefBSForCTRS:: get_LNC_array_for_space(Space* sp,
--- a/hotspot/src/share/vm/gc/cms/parNewGeneration.cpp Mon Apr 04 13:40:18 2016 -0700 +++ b/hotspot/src/share/vm/gc/cms/parNewGeneration.cpp Thu Apr 07 09:47:48 2016 -0700 @@ -233,11 +233,15 @@ if (word_sz * 100 < ParallelGCBufferWastePct * plab->word_sz()) { // Is small enough; abandon this buffer and start a new one. plab->retire(); - size_t buf_size = plab->word_sz(); + // The minimum size has to be twice SurvivorAlignmentInBytes to + // allow for padding used in the alignment of 1 word. A padding + // of 1 is too small for a filler word so the padding size will + // be increased by SurvivorAlignmentInBytes. + size_t min_usable_size = 2 * static_cast<size_t>(SurvivorAlignmentInBytes >> LogHeapWordSize); + size_t buf_size = MAX2(plab->word_sz(), min_usable_size); HeapWord* buf_space = sp->par_allocate(buf_size); if (buf_space == NULL) { - const size_t min_bytes = - PLAB::min_size() << LogHeapWordSize; + const size_t min_bytes = MAX2(PLAB::min_size(), min_usable_size) << LogHeapWordSize; size_t free_bytes = sp->free(); while(buf_space == NULL && free_bytes >= min_bytes) { buf_size = free_bytes >> LogHeapWordSize; @@ -253,7 +257,10 @@ // Note that we cannot compare buf_size < word_sz below // because of AlignmentReserve (see PLAB::allocate()). assert(obj != NULL || plab->words_remaining() < word_sz, - "Else should have been able to allocate"); + "Else should have been able to allocate requested object size " + SIZE_FORMAT ", PLAB size " SIZE_FORMAT ", SurvivorAlignmentInBytes " + SIZE_FORMAT ", words_remaining " SIZE_FORMAT, + word_sz, buf_size, SurvivorAlignmentInBytes, plab->words_remaining()); // It's conceivable that we may be able to use the // buffer we just grabbed for subsequent small requests // even if not for this one. @@ -391,7 +398,7 @@ } void ParScanThreadStateSet::print_termination_stats() { - LogHandle(gc, task, stats) log; + Log(gc, task, stats) log; if (!log.is_debug()) { return; } @@ -423,7 +430,7 @@ if (!log_develop_is_enabled(Trace, gc, task, stats)) { return; } - LogHandle(gc, task, stats) log; + Log(gc, task, stats) log; ResourceMark rm; outputStream* st = log.trace_stream(); print_taskqueue_stats_hdr(st); @@ -901,7 +908,7 @@ size_policy->minor_collection_begin(); } - GCTraceTime(Trace, gc) t1("ParNew", NULL, gch->gc_cause()); + GCTraceTime(Trace, gc, phases) t1("ParNew", NULL, gch->gc_cause()); age_table()->clear(); to()->clear(SpaceDecorator::Mangle);
--- a/hotspot/src/share/vm/gc/cms/parOopClosures.inline.hpp Mon Apr 04 13:40:18 2016 -0700 +++ b/hotspot/src/share/vm/gc/cms/parOopClosures.inline.hpp Thu Apr 07 09:47:48 2016 -0700 @@ -82,18 +82,19 @@ if ((HeapWord*)obj < _boundary) { #ifndef PRODUCT if (_g->to()->is_in_reserved(obj)) { - tty->print_cr("Scanning field (" PTR_FORMAT ") twice?", p2i(p)); + Log(gc) log; + log.error("Scanning field (" PTR_FORMAT ") twice?", p2i(p)); GenCollectedHeap* gch = GenCollectedHeap::heap(); Space* sp = gch->space_containing(p); oop obj = oop(sp->block_start(p)); assert((HeapWord*)obj < (HeapWord*)p, "Error"); - tty->print_cr("Object: " PTR_FORMAT, p2i((void *)obj)); - tty->print_cr("-------"); - obj->print(); - tty->print_cr("-----"); - tty->print_cr("Heap:"); - tty->print_cr("-----"); - gch->print(); + log.error("Object: " PTR_FORMAT, p2i((void *)obj)); + log.error("-------"); + obj->print_on(log.error_stream()); + log.error("-----"); + log.error("Heap:"); + log.error("-----"); + gch->print_on(log.error_stream()); ShouldNotReachHere(); } #endif
--- a/hotspot/src/share/vm/gc/cms/vmCMSOperations.cpp Mon Apr 04 13:40:18 2016 -0700 +++ b/hotspot/src/share/vm/gc/cms/vmCMSOperations.cpp Thu Apr 07 09:47:48 2016 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -38,27 +38,17 @@ // Methods in abstract class VM_CMS_Operation ////////////////////////////////////////////////////////// void VM_CMS_Operation::acquire_pending_list_lock() { - // The caller may block while communicating - // with the SLT thread in order to acquire/release the PLL. - SurrogateLockerThread* slt = ConcurrentMarkSweepThread::slt(); - if (slt != NULL) { - slt->manipulatePLL(SurrogateLockerThread::acquirePLL); - } else { - SurrogateLockerThread::report_missing_slt(); - } + _pending_list_locker.lock(); } void VM_CMS_Operation::release_and_notify_pending_list_lock() { - // The caller may block while communicating - // with the SLT thread in order to acquire/release the PLL. - ConcurrentMarkSweepThread::slt()-> - manipulatePLL(SurrogateLockerThread::releaseAndNotifyPLL); + _pending_list_locker.unlock(); } void VM_CMS_Operation::verify_before_gc() { if (VerifyBeforeGC && GenCollectedHeap::heap()->total_collections() >= VerifyGCStartAt) { - GCTraceTime(Info, gc, verify) tm("Verify Before", _collector->_gc_timer_cm); + GCTraceTime(Info, gc, phases, verify) tm("Verify Before", _collector->_gc_timer_cm); HandleMark hm; FreelistLocker x(_collector); MutexLockerEx y(_collector->bitMapLock(), Mutex::_no_safepoint_check_flag); @@ -70,7 +60,7 @@ void VM_CMS_Operation::verify_after_gc() { if (VerifyAfterGC && GenCollectedHeap::heap()->total_collections() >= VerifyGCStartAt) { - GCTraceTime(Info, gc, verify) tm("Verify After", _collector->_gc_timer_cm); + GCTraceTime(Info, gc, phases, verify) tm("Verify After", _collector->_gc_timer_cm); HandleMark hm; FreelistLocker x(_collector); MutexLockerEx y(_collector->bitMapLock(), Mutex::_no_safepoint_check_flag); @@ -95,7 +85,7 @@ assert(!ConcurrentMarkSweepThread::cms_thread_has_cms_token(), "Possible deadlock"); - if (needs_pll()) { + if (needs_pending_list_lock()) { acquire_pending_list_lock(); } // Get the Heap_lock after the pending_list_lock. @@ -103,7 +93,7 @@ if (lost_race()) { assert(_prologue_succeeded == false, "Initialized in c'tor"); Heap_lock->unlock(); - if (needs_pll()) { + if (needs_pending_list_lock()) { release_and_notify_pending_list_lock(); } } else { @@ -120,7 +110,7 @@ // Release the Heap_lock first. Heap_lock->unlock(); - if (needs_pll()) { + if (needs_pending_list_lock()) { release_and_notify_pending_list_lock(); } }
--- a/hotspot/src/share/vm/gc/cms/vmCMSOperations.hpp Mon Apr 04 13:40:18 2016 -0700 +++ b/hotspot/src/share/vm/gc/cms/vmCMSOperations.hpp Thu Apr 07 09:47:48 2016 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,6 +28,7 @@ #include "gc/cms/concurrentMarkSweepGeneration.hpp" #include "gc/shared/gcCause.hpp" #include "gc/shared/gcId.hpp" +#include "gc/shared/referencePendingListLocker.hpp" #include "gc/shared/vmGCOperations.hpp" #include "runtime/vm_operations.hpp" @@ -51,6 +52,9 @@ class CMSCollector; class VM_CMS_Operation: public VM_Operation { + private: + ReferencePendingListLocker _pending_list_locker; + protected: CMSCollector* _collector; // associated collector bool _prologue_succeeded; // whether doit_prologue succeeded @@ -73,7 +77,7 @@ virtual const CMSCollector::CollectorState legal_state() const = 0; // Whether the pending list lock needs to be held - virtual const bool needs_pll() const = 0; + virtual const bool needs_pending_list_lock() const = 0; // Execute operations in the context of the caller, // prior to execution of the vm operation itself. @@ -105,7 +109,7 @@ return CMSCollector::InitialMarking; } - virtual const bool needs_pll() const { + virtual const bool needs_pending_list_lock() const { return false; } }; @@ -122,7 +126,7 @@ return CMSCollector::FinalMarking; } - virtual const bool needs_pll() const { + virtual const bool needs_pending_list_lock() const { return true; } };
--- a/hotspot/src/share/vm/gc/cms/vmStructs_cms.hpp Mon Apr 04 13:40:18 2016 -0700 +++ b/hotspot/src/share/vm/gc/cms/vmStructs_cms.hpp Thu Apr 07 09:47:48 2016 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2016, 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 @@ -51,14 +51,12 @@ declare_type(ConcurrentMarkSweepGeneration,CardGeneration) \ declare_type(CompactibleFreeListSpace, CompactibleSpace) \ declare_type(ConcurrentMarkSweepThread, NamedThread) \ - declare_type(SurrogateLockerThread, JavaThread) \ declare_toplevel_type(CMSCollector) \ declare_toplevel_type(CMSBitMap) \ declare_toplevel_type(FreeChunk) \ declare_toplevel_type(Metablock) \ declare_toplevel_type(ConcurrentMarkSweepThread*) \ declare_toplevel_type(ConcurrentMarkSweepGeneration*) \ - declare_toplevel_type(SurrogateLockerThread*) \ declare_toplevel_type(CompactibleFreeListSpace*) \ declare_toplevel_type(CMSCollector*) \ declare_toplevel_type(AFLBinaryTreeDictionary) \
--- a/hotspot/src/share/vm/gc/g1/collectionSetChooser.cpp Mon Apr 04 13:40:18 2016 -0700 +++ b/hotspot/src/share/vm/gc/g1/collectionSetChooser.cpp Thu Apr 07 09:47:48 2016 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2016, 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 @@ -145,7 +145,6 @@ verify(); } - void CollectionSetChooser::add_region(HeapRegion* hr) { assert(!hr->is_pinned(), "Pinned region shouldn't be added to the collection set (index %u)", hr->hrm_index()); @@ -210,4 +209,67 @@ _front = 0; _end = 0; _remaining_reclaimable_bytes = 0; +} + +class ParKnownGarbageHRClosure: public HeapRegionClosure { + G1CollectedHeap* _g1h; + CSetChooserParUpdater _cset_updater; + +public: + ParKnownGarbageHRClosure(CollectionSetChooser* hrSorted, + uint chunk_size) : + _g1h(G1CollectedHeap::heap()), + _cset_updater(hrSorted, true /* parallel */, chunk_size) { } + + bool doHeapRegion(HeapRegion* r) { + // Do we have any marking information for this region? + if (r->is_marked()) { + // We will skip any region that's currently used as an old GC + // alloc region (we should not consider those for collection + // before we fill them up). + if (_cset_updater.should_add(r) && !_g1h->is_old_gc_alloc_region(r)) { + _cset_updater.add_region(r); + } + } + return false; + } }; + +class ParKnownGarbageTask: public AbstractGangTask { + CollectionSetChooser* _hrSorted; + uint _chunk_size; + G1CollectedHeap* _g1; + HeapRegionClaimer _hrclaimer; + +public: + ParKnownGarbageTask(CollectionSetChooser* hrSorted, uint chunk_size, uint n_workers) : + AbstractGangTask("ParKnownGarbageTask"), + _hrSorted(hrSorted), _chunk_size(chunk_size), + _g1(G1CollectedHeap::heap()), _hrclaimer(n_workers) {} + + void work(uint worker_id) { + ParKnownGarbageHRClosure parKnownGarbageCl(_hrSorted, _chunk_size); + _g1->heap_region_par_iterate(&parKnownGarbageCl, worker_id, &_hrclaimer); + } +}; + +uint CollectionSetChooser::calculate_parallel_work_chunk_size(uint n_workers, uint n_regions) const { + assert(n_workers > 0, "Active gc workers should be greater than 0"); + const uint overpartition_factor = 4; + const uint min_chunk_size = MAX2(n_regions / n_workers, 1U); + return MAX2(n_regions / (n_workers * overpartition_factor), min_chunk_size); +} + +void CollectionSetChooser::rebuild(WorkGang* workers, uint n_regions) { + clear(); + + uint n_workers = workers->active_workers(); + + uint chunk_size = calculate_parallel_work_chunk_size(n_workers, n_regions); + prepare_for_par_region_addition(n_workers, n_regions, chunk_size); + + ParKnownGarbageTask par_known_garbage_task(this, chunk_size, n_workers); + workers->run_task(&par_known_garbage_task); + + sort_regions(); +}
--- a/hotspot/src/share/vm/gc/g1/collectionSetChooser.hpp Mon Apr 04 13:40:18 2016 -0700 +++ b/hotspot/src/share/vm/gc/g1/collectionSetChooser.hpp Thu Apr 07 09:47:48 2016 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2016, 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 @@ -65,6 +65,9 @@ // The sum of reclaimable bytes over all the regions in the CSet chooser. size_t _remaining_reclaimable_bytes; + // Calculate and return chunk size (in number of regions) for parallel + // addition of regions + uint calculate_parallel_work_chunk_size(uint n_workers, uint n_regions) const; public: // Return the current candidate region to be considered for @@ -132,6 +135,8 @@ void clear(); + void rebuild(WorkGang* workers, uint n_regions); + // Return the number of candidate regions that remain to be collected. uint remaining_regions() { return _end - _front; }
--- a/hotspot/src/share/vm/gc/g1/concurrentG1Refine.cpp Mon Apr 04 13:40:18 2016 -0700 +++ b/hotspot/src/share/vm/gc/g1/concurrentG1Refine.cpp Thu Apr 07 09:47:48 2016 -0700 @@ -27,11 +27,13 @@ #include "gc/g1/concurrentG1RefineThread.hpp" #include "gc/g1/g1CollectedHeap.inline.hpp" #include "gc/g1/g1HotCardCache.hpp" +#include "gc/g1/g1Predictions.hpp" #include "runtime/java.hpp" -ConcurrentG1Refine::ConcurrentG1Refine(G1CollectedHeap* g1h) : +ConcurrentG1Refine::ConcurrentG1Refine(G1CollectedHeap* g1h, const G1Predictions* predictor) : _threads(NULL), _sample_thread(NULL), + _predictor_sigma(predictor->sigma()), _hot_card_cache(g1h) { // Ergonomically select initial concurrent refinement parameters @@ -49,10 +51,12 @@ FLAG_SET_DEFAULT(G1ConcRefinementRedZone, yellow_zone() * 2); } set_red_zone(MAX2(G1ConcRefinementRedZone, yellow_zone())); + } ConcurrentG1Refine* ConcurrentG1Refine::create(G1CollectedHeap* g1h, CardTableEntryClosure* refine_closure, jint* ecode) { - ConcurrentG1Refine* cg1r = new ConcurrentG1Refine(g1h); + G1CollectorPolicy* policy = g1h->g1_policy(); + ConcurrentG1Refine* cg1r = new ConcurrentG1Refine(g1h, &policy->predictor()); if (cg1r == NULL) { *ecode = JNI_ENOMEM; vm_shutdown_during_initialization("Could not create ConcurrentG1Refine"); @@ -155,3 +159,43 @@ _sample_thread->print_on(st); st->cr(); } + +void ConcurrentG1Refine::adjust(double update_rs_time, + double update_rs_processed_buffers, + double goal_ms) { + DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set(); + + if (G1UseAdaptiveConcRefinement) { + const int k_gy = 3, k_gr = 6; + const double inc_k = 1.1, dec_k = 0.9; + + size_t g = green_zone(); + if (update_rs_time > goal_ms) { + g = (size_t)(g * dec_k); // Can become 0, that's OK. That would mean a mutator-only processing. + } else { + if (update_rs_time < goal_ms && update_rs_processed_buffers > g) { + g = (size_t)MAX2(g * inc_k, g + 1.0); + } + } + // Change the refinement threads params + set_green_zone(g); + set_yellow_zone(g * k_gy); + set_red_zone(g * k_gr); + reinitialize_threads(); + + size_t processing_threshold_delta = MAX2<size_t>(green_zone() * _predictor_sigma, 1); + size_t processing_threshold = MIN2(green_zone() + processing_threshold_delta, + yellow_zone()); + // Change the barrier params + dcqs.set_process_completed_threshold((int)processing_threshold); + dcqs.set_max_completed_queue((int)red_zone()); + } + + size_t curr_queue_size = dcqs.completed_buffers_num(); + if (curr_queue_size >= yellow_zone()) { + dcqs.set_completed_queue_padding(curr_queue_size); + } else { + dcqs.set_completed_queue_padding(0); + } + dcqs.notify_if_necessary(); +}
--- a/hotspot/src/share/vm/gc/g1/concurrentG1Refine.hpp Mon Apr 04 13:40:18 2016 -0700 +++ b/hotspot/src/share/vm/gc/g1/concurrentG1Refine.hpp Thu Apr 07 09:47:48 2016 -0700 @@ -35,6 +35,7 @@ class ConcurrentG1RefineThread; class G1CollectedHeap; class G1HotCardCache; +class G1Predictions; class G1RegionToSpaceMapper; class G1RemSet; class DirtyCardQueue; @@ -67,13 +68,15 @@ size_t _thread_threshold_step; + double _predictor_sigma; + // We delay the refinement of 'hot' cards using the hot card cache. G1HotCardCache _hot_card_cache; // Reset the threshold step value based of the current zone boundaries. void reset_threshold_step(); - ConcurrentG1Refine(G1CollectedHeap* g1h); + ConcurrentG1Refine(G1CollectedHeap* g1h, const G1Predictions* predictions); public: ~ConcurrentG1Refine(); @@ -85,6 +88,8 @@ void init(G1RegionToSpaceMapper* card_counts_storage); void stop(); + void adjust(double update_rs_time, double update_rs_processed_buffers, double goal_ms); + void reinitialize_threads(); // Iterate over all concurrent refinement threads
--- a/hotspot/src/share/vm/gc/g1/concurrentG1RefineThread.cpp Mon Apr 04 13:40:18 2016 -0700 +++ b/hotspot/src/share/vm/gc/g1/concurrentG1RefineThread.cpp Thu Apr 07 09:47:48 2016 -0700 @@ -76,9 +76,8 @@ } void ConcurrentG1RefineThread::wait_for_completed_buffers() { - DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set(); MutexLockerEx x(_monitor, Mutex::_no_safepoint_check_flag); - while (!_should_terminate && !is_active()) { + while (!should_terminate() && !is_active()) { _monitor->wait(Mutex::_no_safepoint_check_flag); } } @@ -109,22 +108,13 @@ } } -void ConcurrentG1RefineThread::run() { - initialize_in_thread(); - wait_for_universe_init(); - - run_service(); - - terminate(); -} - void ConcurrentG1RefineThread::run_service() { _vtime_start = os::elapsedVTime(); - while (!_should_terminate) { + while (!should_terminate()) { // Wait for work wait_for_completed_buffers(); - if (_should_terminate) { + if (should_terminate()) { break; } @@ -135,7 +125,12 @@ { SuspendibleThreadSetJoiner sts_join; - do { + while (!should_terminate()) { + if (sts_join.should_yield()) { + sts_join.yield(); + continue; // Re-check for termination after yield delay. + } + size_t curr_buffer_num = dcqs.completed_buffers_num(); // If the number of the buffers falls down into the yellow zone, // that means that the transition period after the evacuation pause has ended. @@ -147,17 +142,23 @@ if (_next != NULL && !_next->is_active() && curr_buffer_num > _next->_threshold) { _next->activate(); } - } while (dcqs.apply_closure_to_completed_buffer(_refine_closure, - _worker_id + _worker_id_offset, - _deactivation_threshold, - false /* during_pause */)); - deactivate(); - log_debug(gc, refine)("Deactivated %d, off threshold: " SIZE_FORMAT ", current: " SIZE_FORMAT, - _worker_id, _deactivation_threshold, - dcqs.completed_buffers_num()); + // Process the next buffer, if there are enough left. + if (!dcqs.apply_closure_to_completed_buffer(_refine_closure, + _worker_id + _worker_id_offset, + _deactivation_threshold, + false /* during_pause */)) { + break; // Deactivate, number of buffers fell below threshold. + } + } } + deactivate(); + log_debug(gc, refine)("Deactivated %d, off threshold: " SIZE_FORMAT + ", current: " SIZE_FORMAT, + _worker_id, _deactivation_threshold, + dcqs.completed_buffers_num()); + if (os::supports_vtime()) { _vtime_accum = (os::elapsedVTime() - _vtime_start); } else { @@ -168,23 +169,6 @@ log_debug(gc, refine)("Stopping %d", _worker_id); } -void ConcurrentG1RefineThread::stop() { - // it is ok to take late safepoints here, if needed - { - MutexLockerEx mu(Terminator_lock); - _should_terminate = true; - } - - stop_service(); - - { - MutexLockerEx mu(Terminator_lock); - while (!_has_terminated) { - Terminator_lock->wait(); - } - } -} - void ConcurrentG1RefineThread::stop_service() { MutexLockerEx x(_monitor, Mutex::_no_safepoint_check_flag); _monitor->notify();
--- a/hotspot/src/share/vm/gc/g1/concurrentG1RefineThread.hpp Mon Apr 04 13:40:18 2016 -0700 +++ b/hotspot/src/share/vm/gc/g1/concurrentG1RefineThread.hpp Thu Apr 07 09:47:48 2016 -0700 @@ -72,7 +72,6 @@ void stop_service(); public: - virtual void run(); // Constructor ConcurrentG1RefineThread(ConcurrentG1Refine* cg1r, ConcurrentG1RefineThread* next, CardTableEntryClosure* refine_closure, @@ -84,9 +83,6 @@ double vtime_accum() { return _vtime_accum; } ConcurrentG1Refine* cg1r() { return _cg1r; } - - // shutdown - void stop(); }; #endif // SHARE_VM_GC_G1_CONCURRENTG1REFINETHREAD_HPP
--- a/hotspot/src/share/vm/gc/g1/concurrentMarkThread.cpp Mon Apr 04 13:40:18 2016 -0700 +++ b/hotspot/src/share/vm/gc/g1/concurrentMarkThread.cpp Thu Apr 07 09:47:48 2016 -0700 @@ -25,6 +25,7 @@ #include "precompiled.hpp" #include "classfile/classLoaderData.hpp" #include "gc/g1/concurrentMarkThread.inline.hpp" +#include "gc/g1/g1Analytics.hpp" #include "gc/g1/g1CollectedHeap.inline.hpp" #include "gc/g1/g1CollectorPolicy.hpp" #include "gc/g1/g1MMUTracker.hpp" @@ -41,9 +42,6 @@ // The CM thread is created when the G1 garbage collector is used -SurrogateLockerThread* - ConcurrentMarkThread::_slt = NULL; - ConcurrentMarkThread::ConcurrentMarkThread(G1ConcurrentMark* cm) : ConcurrentGCThread(), _cm(cm), @@ -82,60 +80,59 @@ // Marking pauses can be scheduled flexibly, so we might delay marking to meet MMU. void ConcurrentMarkThread::delay_to_keep_mmu(G1CollectorPolicy* g1_policy, bool remark) { + const G1Analytics* analytics = g1_policy->analytics(); if (g1_policy->adaptive_young_list_length()) { double now = os::elapsedTime(); - double prediction_ms = remark ? g1_policy->predict_remark_time_ms() - : g1_policy->predict_cleanup_time_ms(); + double prediction_ms = remark ? analytics->predict_remark_time_ms() + : analytics->predict_cleanup_time_ms(); G1MMUTracker *mmu_tracker = g1_policy->mmu_tracker(); jlong sleep_time_ms = mmu_tracker->when_ms(now, prediction_ms); os::sleep(this, sleep_time_ms, false); } } -class GCConcPhaseTimer : StackObj { +class G1ConcPhaseTimer : public GCTraceConcTimeImpl<LogLevel::Info, LOG_TAGS(gc, marking)> { G1ConcurrentMark* _cm; public: - GCConcPhaseTimer(G1ConcurrentMark* cm, const char* title) : _cm(cm) { - _cm->register_concurrent_phase_start(title); + G1ConcPhaseTimer(G1ConcurrentMark* cm, const char* title) : + GCTraceConcTimeImpl<LogLevel::Info, LogTag::_gc, LogTag::_marking>(title), + _cm(cm) { + _cm->gc_timer_cm()->register_gc_concurrent_start(title); } - ~GCConcPhaseTimer() { - _cm->register_concurrent_phase_end(); + ~G1ConcPhaseTimer() { + _cm->gc_timer_cm()->register_gc_concurrent_end(); } }; -void ConcurrentMarkThread::run() { - initialize_in_thread(); - wait_for_universe_init(); - - run_service(); - - terminate(); -} - void ConcurrentMarkThread::run_service() { _vtime_start = os::elapsedVTime(); G1CollectedHeap* g1h = G1CollectedHeap::heap(); G1CollectorPolicy* g1_policy = g1h->g1_policy(); - while (!_should_terminate) { + while (!should_terminate()) { // wait until started is set. sleepBeforeNextCycle(); - if (_should_terminate) { - _cm->root_regions()->cancel_scan(); + if (should_terminate()) { break; } + GCIdMark gc_id_mark; + + cm()->concurrent_cycle_start(); + assert(GCId::current() != GCId::undefined(), "GC id should have been set up by the initial mark GC."); + + GCTraceConcTime(Info, gc) tt("Concurrent Cycle"); { ResourceMark rm; HandleMark hm; double cycle_start = os::elapsedVTime(); { - GCConcPhaseTimer(_cm, "Concurrent Clearing of Claimed Marks"); + G1ConcPhaseTimer t(_cm, "Concurrent Clear Claimed Marks"); ClassLoaderDataGraph::clear_claimed_marks(); } @@ -148,22 +145,22 @@ // correctness issue. { - GCConcPhaseTimer(_cm, "Concurrent Root Region Scanning"); - _cm->scanRootRegions(); + G1ConcPhaseTimer t(_cm, "Concurrent Scan Root Regions"); + _cm->scan_root_regions(); } // It would be nice to use the GCTraceConcTime class here but // the "end" logging is inside the loop and not at the end of // a scope. Mimicking the same log output as GCTraceConcTime instead. jlong mark_start = os::elapsed_counter(); - log_info(gc)("Concurrent Mark (%.3fs)", TimeHelper::counter_to_seconds(mark_start)); + log_info(gc, marking)("Concurrent Mark (%.3fs)", TimeHelper::counter_to_seconds(mark_start)); int iter = 0; do { iter++; if (!cm()->has_aborted()) { - GCConcPhaseTimer(_cm, "Concurrent Mark"); - _cm->markFromRoots(); + G1ConcPhaseTimer t(_cm, "Concurrent Mark From Roots"); + _cm->mark_from_roots(); } double mark_end_time = os::elapsedVTime(); @@ -171,18 +168,18 @@ _vtime_mark_accum += (mark_end_time - cycle_start); if (!cm()->has_aborted()) { delay_to_keep_mmu(g1_policy, true /* remark */); - log_info(gc)("Concurrent Mark (%.3fs, %.3fs) %.3fms", - TimeHelper::counter_to_seconds(mark_start), - TimeHelper::counter_to_seconds(mark_end), - TimeHelper::counter_to_millis(mark_end - mark_start)); + log_info(gc, marking)("Concurrent Mark (%.3fs, %.3fs) %.3fms", + TimeHelper::counter_to_seconds(mark_start), + TimeHelper::counter_to_seconds(mark_end), + TimeHelper::counter_to_millis(mark_end - mark_start)); CMCheckpointRootsFinalClosure final_cl(_cm); VM_CGC_Operation op(&final_cl, "Pause Remark", true /* needs_pll */); VMThread::execute(&op); } if (cm()->restart_for_overflow()) { - log_debug(gc)("Restarting conc marking because of MS overflow in remark (restart #%d).", iter); - log_info(gc)("Concurrent Mark restart for overflow"); + log_debug(gc, marking)("Restarting Concurrent Marking because of Mark Stack Overflow in Remark (Iteration #%d).", iter); + log_info(gc, marking)("Concurrent Mark Restart due to overflow"); } } while (cm()->restart_for_overflow()); @@ -216,11 +213,9 @@ // place, it would wait for us to process the regions // reclaimed by cleanup. - GCTraceConcTime(Info, gc) tt("Concurrent Cleanup"); - GCConcPhaseTimer(_cm, "Concurrent Cleanup"); - + G1ConcPhaseTimer t(_cm, "Concurrent Complete Cleanup"); // Now do the concurrent cleanup operation. - _cm->completeCleanup(); + _cm->complete_cleanup(); // Notify anyone who's waiting that there are no more free // regions coming. We have to do this before we join the STS @@ -265,7 +260,7 @@ if (!cm()->has_aborted()) { g1_policy->record_concurrent_mark_cleanup_completed(); } else { - log_info(gc)("Concurrent Mark abort"); + log_info(gc, marking)("Concurrent Mark Abort"); } } @@ -274,8 +269,8 @@ // We may have aborted just before the remark. Do not bother clearing the // bitmap then, as it has been done during mark abort. if (!cm()->has_aborted()) { - GCConcPhaseTimer(_cm, "Concurrent Bitmap Clearing"); - _cm->clearNextBitmap(); + G1ConcPhaseTimer t(_cm, "Concurrent Cleanup for Next Mark"); + _cm->cleanup_for_next_mark(); } else { assert(!G1VerifyBitmaps || _cm->nextMarkBitmapIsClear(), "Next mark bitmap must be clear"); } @@ -288,25 +283,11 @@ { SuspendibleThreadSetJoiner sts_join; g1h->increment_old_marking_cycles_completed(true /* concurrent */); - g1h->register_concurrent_cycle_end(); + + cm()->concurrent_cycle_end(); } } -} - -void ConcurrentMarkThread::stop() { - { - MutexLockerEx ml(Terminator_lock); - _should_terminate = true; - } - - stop_service(); - - { - MutexLockerEx ml(Terminator_lock); - while (!_has_terminated) { - Terminator_lock->wait(); - } - } + _cm->root_regions()->cancel_scan(); } void ConcurrentMarkThread::stop_service() { @@ -320,7 +301,7 @@ assert(!in_progress(), "should have been cleared"); MutexLockerEx x(CGC_lock, Mutex::_no_safepoint_check_flag); - while (!started() && !_should_terminate) { + while (!started() && !should_terminate()) { CGC_lock->wait(Mutex::_no_safepoint_check_flag); } @@ -328,16 +309,3 @@ set_in_progress(); } } - -// Note: As is the case with CMS - this method, although exported -// by the ConcurrentMarkThread, which is a non-JavaThread, can only -// be called by a JavaThread. Currently this is done at vm creation -// time (post-vm-init) by the main/Primordial (Java)Thread. -// XXX Consider changing this in the future to allow the CM thread -// itself to create this thread? -void ConcurrentMarkThread::makeSurrogateLockerThread(TRAPS) { - assert(UseG1GC, "SLT thread needed only for concurrent GC"); - assert(THREAD->is_Java_thread(), "must be a Java thread"); - assert(_slt == NULL, "SLT already created"); - _slt = SurrogateLockerThread::make(THREAD); -}
--- a/hotspot/src/share/vm/gc/g1/concurrentMarkThread.hpp Mon Apr 04 13:40:18 2016 -0700 +++ b/hotspot/src/share/vm/gc/g1/concurrentMarkThread.hpp Thu Apr 07 09:47:48 2016 -0700 @@ -38,13 +38,8 @@ double _vtime_start; // Initial virtual time. double _vtime_accum; // Accumulated virtual time. - double _vtime_mark_accum; - public: - virtual void run(); - - private: G1ConcurrentMark* _cm; enum State { @@ -61,15 +56,10 @@ void run_service(); void stop_service(); - static SurrogateLockerThread* _slt; - public: // Constructor ConcurrentMarkThread(G1ConcurrentMark* cm); - static void makeSurrogateLockerThread(TRAPS); - static SurrogateLockerThread* slt() { return _slt; } - // Total virtual time so far for this thread and concurrent marking tasks. double vtime_accum(); // Marking virtual time so far this thread and concurrent marking tasks. @@ -93,9 +83,6 @@ // as the CM thread might take some time to wake up before noticing // that started() is set and set in_progress(). bool during_cycle() { return !idle(); } - - // shutdown - void stop(); }; #endif // SHARE_VM_GC_G1_CONCURRENTMARKTHREAD_HPP
--- a/hotspot/src/share/vm/gc/g1/dirtyCardQueue.cpp Mon Apr 04 13:40:18 2016 -0700 +++ b/hotspot/src/share/vm/gc/g1/dirtyCardQueue.cpp Thu Apr 07 09:47:48 2016 -0700 @@ -110,44 +110,6 @@ } } -bool DirtyCardQueue::apply_closure(CardTableEntryClosure* cl, - bool consume, - uint worker_i) { - bool res = true; - if (_buf != NULL) { - res = apply_closure_to_buffer(cl, _buf, _index, _sz, - consume, - worker_i); - if (res && consume) { - _index = _sz; - } - } - return res; -} - -bool DirtyCardQueue::apply_closure_to_buffer(CardTableEntryClosure* cl, - void** buf, - size_t index, size_t sz, - bool consume, - uint worker_i) { - if (cl == NULL) return true; - size_t limit = byte_index_to_index(sz); - for (size_t i = byte_index_to_index(index); i < limit; ++i) { - jbyte* card_ptr = static_cast<jbyte*>(buf[i]); - if (card_ptr != NULL) { - // Set the entry to null, so we don't do it again (via the test - // above) if we reconsider this buffer. - if (consume) { - buf[i] = NULL; - } - if (!cl->do_card_ptr(card_ptr, worker_i)) { - return false; - } - } - } - return true; -} - DirtyCardQueueSet::DirtyCardQueueSet(bool notify_when_complete) : PtrQueueSet(notify_when_complete), _mut_process_closure(NULL), @@ -188,22 +150,57 @@ t->dirty_card_queue().handle_zero_index(); } -bool DirtyCardQueueSet::mut_process_buffer(void** buf) { +bool DirtyCardQueueSet::apply_closure_to_buffer(CardTableEntryClosure* cl, + BufferNode* node, + bool consume, + uint worker_i) { + if (cl == NULL) return true; + bool result = true; + void** buf = BufferNode::make_buffer_from_node(node); + size_t limit = DirtyCardQueue::byte_index_to_index(buffer_size()); + size_t i = DirtyCardQueue::byte_index_to_index(node->index()); + for ( ; i < limit; ++i) { + jbyte* card_ptr = static_cast<jbyte*>(buf[i]); + assert(card_ptr != NULL, "invariant"); + if (!cl->do_card_ptr(card_ptr, worker_i)) { + result = false; // Incomplete processing. + break; + } + } + if (consume) { + size_t new_index = DirtyCardQueue::index_to_byte_index(i); + assert(new_index <= buffer_size(), "invariant"); + node->set_index(new_index); + } + return result; +} + +#ifndef ASSERT +#define assert_fully_consumed(node, buffer_size) +#else +#define assert_fully_consumed(node, buffer_size) \ + do { \ + size_t _afc_index = (node)->index(); \ + size_t _afc_size = (buffer_size); \ + assert(_afc_index == _afc_size, \ + "Buffer was not fully consumed as claimed: index: " \ + SIZE_FORMAT ", size: " SIZE_FORMAT, \ + _afc_index, _afc_size); \ + } while (0) +#endif // ASSERT + +bool DirtyCardQueueSet::mut_process_buffer(BufferNode* node) { guarantee(_free_ids != NULL, "must be"); - // claim a par id - uint worker_i = _free_ids->claim_par_id(); + uint worker_i = _free_ids->claim_par_id(); // temporarily claim an id + bool result = apply_closure_to_buffer(_mut_process_closure, node, true, worker_i); + _free_ids->release_par_id(worker_i); // release the id - bool b = DirtyCardQueue::apply_closure_to_buffer(_mut_process_closure, buf, 0, - _sz, true, worker_i); - if (b) { + if (result) { + assert_fully_consumed(node, buffer_size()); Atomic::inc(&_processed_buffers_mut); } - - // release the id - _free_ids->release_par_id(worker_i); - - return b; + return result; } @@ -239,49 +236,31 @@ if (nd == NULL) { return false; } else { - void** buf = BufferNode::make_buffer_from_node(nd); - size_t index = nd->index(); - if (DirtyCardQueue::apply_closure_to_buffer(cl, - buf, index, _sz, - true, worker_i)) { + if (apply_closure_to_buffer(cl, nd, true, worker_i)) { + assert_fully_consumed(nd, buffer_size()); // Done with fully processed buffer. - deallocate_buffer(buf); + deallocate_buffer(nd); Atomic::inc(&_processed_buffers_rs_thread); - return true; } else { // Return partially processed buffer to the queue. - enqueue_complete_buffer(buf, index); - return false; + guarantee(!during_pause, "Should never stop early"); + enqueue_complete_buffer(nd); } - } -} - -void DirtyCardQueueSet::apply_closure_to_all_completed_buffers(CardTableEntryClosure* cl) { - BufferNode* nd = _completed_buffers_head; - while (nd != NULL) { - bool b = - DirtyCardQueue::apply_closure_to_buffer(cl, - BufferNode::make_buffer_from_node(nd), - 0, _sz, false); - guarantee(b, "Should not stop early."); - nd = nd->next(); + return true; } } void DirtyCardQueueSet::par_apply_closure_to_all_completed_buffers(CardTableEntryClosure* cl) { BufferNode* nd = _cur_par_buffer_node; while (nd != NULL) { - BufferNode* next = (BufferNode*)nd->next(); - BufferNode* actual = (BufferNode*)Atomic::cmpxchg_ptr((void*)next, (volatile void*)&_cur_par_buffer_node, (void*)nd); + BufferNode* next = nd->next(); + void* actual = Atomic::cmpxchg_ptr(next, &_cur_par_buffer_node, nd); if (actual == nd) { - bool b = - DirtyCardQueue::apply_closure_to_buffer(cl, - BufferNode::make_buffer_from_node(actual), - 0, _sz, false); + bool b = apply_closure_to_buffer(cl, nd, false); guarantee(b, "Should not stop early."); nd = next; } else { - nd = actual; + nd = static_cast<BufferNode*>(actual); } } } @@ -304,7 +283,7 @@ while (buffers_to_delete != NULL) { BufferNode* nd = buffers_to_delete; buffers_to_delete = nd->next(); - deallocate_buffer(BufferNode::make_buffer_from_node(nd)); + deallocate_buffer(nd); } } @@ -320,6 +299,13 @@ shared_dirty_card_queue()->reset(); } +void DirtyCardQueueSet::concatenate_log(DirtyCardQueue& dcq) { + if (!dcq.is_empty()) { + enqueue_complete_buffer( + BufferNode::make_node_from_buffer(dcq.get_buf(), dcq.get_index())); + dcq.reinitialize(); + } +} void DirtyCardQueueSet::concatenate_logs() { // Iterate over all the threads, if we find a partial log add it to @@ -329,23 +315,9 @@ _max_completed_queue = max_jint; assert(SafepointSynchronize::is_at_safepoint(), "Must be at safepoint."); for (JavaThread* t = Threads::first(); t; t = t->next()) { - DirtyCardQueue& dcq = t->dirty_card_queue(); - if (dcq.size() != 0) { - void** buf = dcq.get_buf(); - // We must NULL out the unused entries, then enqueue. - size_t limit = dcq.byte_index_to_index(dcq.get_index()); - for (size_t i = 0; i < limit; ++i) { - buf[i] = NULL; - } - enqueue_complete_buffer(dcq.get_buf(), dcq.get_index()); - dcq.reinitialize(); - } + concatenate_log(t->dirty_card_queue()); } - if (_shared_dirty_card_queue.size() != 0) { - enqueue_complete_buffer(_shared_dirty_card_queue.get_buf(), - _shared_dirty_card_queue.get_index()); - _shared_dirty_card_queue.reinitialize(); - } + concatenate_log(_shared_dirty_card_queue); // Restore the completed buffer queue limit. _max_completed_queue = save_max_completed_queue; }
--- a/hotspot/src/share/vm/gc/g1/dirtyCardQueue.hpp Mon Apr 04 13:40:18 2016 -0700 +++ b/hotspot/src/share/vm/gc/g1/dirtyCardQueue.hpp Thu Apr 07 09:47:48 2016 -0700 @@ -37,7 +37,7 @@ public: // Process the card whose card table entry is "card_ptr". If returns // "false", terminate the iteration early. - virtual bool do_card_ptr(jbyte* card_ptr, uint worker_i = 0) = 0; + virtual bool do_card_ptr(jbyte* card_ptr, uint worker_i) = 0; }; // A ptrQueue whose elements are "oops", pointers to object heads. @@ -52,23 +52,6 @@ // Process queue entries and release resources. void flush() { flush_impl(); } - // Apply the closure to all elements, and reset the index to make the - // buffer empty. If a closure application returns "false", return - // "false" immediately, halting the iteration. If "consume" is true, - // deletes processed entries from logs. - bool apply_closure(CardTableEntryClosure* cl, - bool consume = true, - uint worker_i = 0); - - // Apply the closure to all elements of "buf", down to "index" - // (inclusive.) If returns "false", then a closure application returned - // "false", and we return immediately. If "consume" is true, entries are - // set to NULL as they are processed, so they will not be processed again - // later. - static bool apply_closure_to_buffer(CardTableEntryClosure* cl, - void** buf, size_t index, size_t sz, - bool consume = true, - uint worker_i = 0); void **get_buf() { return _buf;} size_t get_index() { return _index;} void reinitialize() { _buf = 0; _sz = 0; _index = 0;} @@ -94,8 +77,19 @@ DirtyCardQueue _shared_dirty_card_queue; - // Override. - bool mut_process_buffer(void** buf); + // Apply the closure to the elements of "node" from it's index to + // buffer_size. If all closure applications return true, then + // returns true. Stops processing after the first closure + // application that returns false, and returns false from this + // function. If "consume" is true, the node's index is updated to + // exclude the processed elements, e.g. up to the element for which + // the closure returned false. + bool apply_closure_to_buffer(CardTableEntryClosure* cl, + BufferNode* node, + bool consume, + uint worker_i = 0); + + bool mut_process_buffer(BufferNode* node); // Protected by the _cbl_mon. FreeIdSet* _free_ids; @@ -107,6 +101,9 @@ // Current buffer node used for parallel iteration. BufferNode* volatile _cur_par_buffer_node; + + void concatenate_log(DirtyCardQueue& dcq); + public: DirtyCardQueueSet(bool notify_when_complete = true); @@ -125,13 +122,18 @@ static void handle_zero_index_for_thread(JavaThread* t); - // If there exists some completed buffer, pop it, then apply the - // specified closure to all its elements, nulling out those elements - // processed. If all elements are processed, returns "true". If no - // completed buffers exist, returns false. If a completed buffer exists, - // but is only partially completed before a "yield" happens, the - // partially completed buffer (with its processed elements set to NULL) - // is returned to the completed buffer set, and this call returns false. + // If there are more than stop_at completed buffers, pop one, apply + // the specified closure to its active elements, and return true. + // Otherwise return false. + // + // A completely processed buffer is freed. However, if a closure + // invocation returns false, processing is stopped and the partially + // processed buffer (with its index updated to exclude the processed + // elements, e.g. up to the element for which the closure returned + // false) is returned to the completed buffer set. + // + // If during_pause is true, stop_at must be zero, and the closure + // must never return false. bool apply_closure_to_completed_buffer(CardTableEntryClosure* cl, uint worker_i, size_t stop_at, @@ -139,13 +141,10 @@ BufferNode* get_completed_buffer(size_t stop_at); - // Applies the current closure to all completed buffers, - // non-consumptively. - void apply_closure_to_all_completed_buffers(CardTableEntryClosure* cl); - void reset_for_par_iteration() { _cur_par_buffer_node = _completed_buffers_head; } // Applies the current closure to all completed buffers, non-consumptively. - // Parallel version. + // Can be used in parallel, all callers using the iteration state initialized + // by reset_for_par_iteration. void par_apply_closure_to_all_completed_buffers(CardTableEntryClosure* cl); DirtyCardQueue* shared_dirty_card_queue() {
--- a/hotspot/src/share/vm/gc/g1/g1AllocRegion.cpp Mon Apr 04 13:40:18 2016 -0700 +++ b/hotspot/src/share/vm/gc/g1/g1AllocRegion.cpp Thu Apr 07 09:47:48 2016 -0700 @@ -26,6 +26,7 @@ #include "gc/g1/g1AllocRegion.inline.hpp" #include "gc/g1/g1EvacStats.inline.hpp" #include "gc/g1/g1CollectedHeap.inline.hpp" +#include "memory/resourceArea.hpp" #include "runtime/orderAccess.inline.hpp" G1CollectedHeap* G1AllocRegion::_g1h = NULL; @@ -194,44 +195,53 @@ return (alloc_region == _dummy_region) ? NULL : alloc_region; } -#if G1_ALLOC_REGION_TRACING +#ifndef PRODUCT void G1AllocRegion::trace(const char* str, size_t min_word_size, size_t desired_word_size, size_t actual_word_size, HeapWord* result) { // All the calls to trace that set either just the size or the size - // and the result are considered part of level 2 tracing and are - // skipped during level 1 tracing. - if ((actual_word_size == 0 && result == NULL) || (G1_ALLOC_REGION_TRACING > 1)) { - const size_t buffer_length = 128; - char hr_buffer[buffer_length]; - char rest_buffer[buffer_length]; + // and the result are considered part of detailed tracing and are + // skipped during other tracing. + + Log(gc, alloc, region) log; + + if (!log.is_debug()) { + return; + } - HeapRegion* alloc_region = _alloc_region; - if (alloc_region == NULL) { - jio_snprintf(hr_buffer, buffer_length, "NULL"); - } else if (alloc_region == _dummy_region) { - jio_snprintf(hr_buffer, buffer_length, "DUMMY"); + bool detailed_info = log.is_trace(); + + if ((actual_word_size == 0 && result == NULL) || detailed_info) { + ResourceMark rm; + outputStream* out; + if (detailed_info) { + out = log.trace_stream(); } else { - jio_snprintf(hr_buffer, buffer_length, - HR_FORMAT, HR_FORMAT_PARAMS(alloc_region)); + out = log.debug_stream(); } - if (G1_ALLOC_REGION_TRACING > 1) { - if (result != NULL) { - jio_snprintf(rest_buffer, buffer_length, "min " SIZE_FORMAT " desired " SIZE_FORMAT " actual " SIZE_FORMAT " " PTR_FORMAT, - min_word_size, desired_word_size, actual_word_size, result); - } else if (min_word_size != 0) { - jio_snprintf(rest_buffer, buffer_length, "min " SIZE_FORMAT " desired " SIZE_FORMAT, min_word_size, desired_word_size); - } else { - jio_snprintf(rest_buffer, buffer_length, ""); - } + out->print("%s: %u ", _name, _count); + + if (_alloc_region == NULL) { + out->print("NULL"); + } else if (_alloc_region == _dummy_region) { + out->print("DUMMY"); } else { - jio_snprintf(rest_buffer, buffer_length, ""); + out->print(HR_FORMAT, HR_FORMAT_PARAMS(_alloc_region)); } - tty->print_cr("[%s] %u %s : %s %s", - _name, _count, hr_buffer, str, rest_buffer); + out->print(" : %s", str); + + if (detailed_info) { + if (result != NULL) { + out->print(" min " SIZE_FORMAT " desired " SIZE_FORMAT " actual " SIZE_FORMAT " " PTR_FORMAT, + min_word_size, desired_word_size, actual_word_size, p2i(result)); + } else if (min_word_size != 0) { + out->print(" min " SIZE_FORMAT " desired " SIZE_FORMAT, min_word_size, desired_word_size); + } + } + out->cr(); } } -#endif // G1_ALLOC_REGION_TRACING +#endif // PRODUCT G1AllocRegion::G1AllocRegion(const char* name, bool bot_updates) @@ -253,7 +263,7 @@ HeapRegion* G1GCAllocRegion::allocate_new_region(size_t word_size, bool force) { assert(!force, "not supported for GC alloc regions"); - return _g1h->new_gc_alloc_region(word_size, count(), _purpose); + return _g1h->new_gc_alloc_region(word_size, _purpose); } void G1GCAllocRegion::retire_region(HeapRegion* alloc_region,
--- a/hotspot/src/share/vm/gc/g1/g1AllocRegion.hpp Mon Apr 04 13:40:18 2016 -0700 +++ b/hotspot/src/share/vm/gc/g1/g1AllocRegion.hpp Thu Apr 07 09:47:48 2016 -0700 @@ -31,9 +31,6 @@ class G1CollectedHeap; -// 0 -> no tracing, 1 -> basic tracing, 2 -> basic + allocation tracing -#define G1_ALLOC_REGION_TRACING 0 - // A class that holds a region that is active in satisfying allocation // requests, potentially issued in parallel. When the active region is // full it will be retired and replaced with a new one. The @@ -213,19 +210,11 @@ // is returned after it's been retired. virtual HeapRegion* release(); -#if G1_ALLOC_REGION_TRACING void trace(const char* str, size_t min_word_size = 0, size_t desired_word_size = 0, size_t actual_word_size = 0, - HeapWord* result = NULL); -#else // G1_ALLOC_REGION_TRACING - void trace(const char* str, - size_t min_word_size = 0, - size_t desired_word_size = 0, - size_t actual_word_size = 0, - HeapWord* result = NULL) { } -#endif // G1_ALLOC_REGION_TRACING + HeapWord* result = NULL) PRODUCT_RETURN; }; class MutatorAllocRegion : public G1AllocRegion {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/src/share/vm/gc/g1/g1Analytics.cpp Thu Apr 07 09:47:48 2016 -0700 @@ -0,0 +1,329 @@ +/* + * Copyright (c) 2016, 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/g1/g1Analytics.hpp" +#include "gc/g1/g1Predictions.hpp" +#include "runtime/os.hpp" +#include "utilities/debug.hpp" +#include "utilities/numberSeq.hpp" + +// Different defaults for different number of GC threads +// They were chosen by running GCOld and SPECjbb on debris with different +// numbers of GC threads and choosing them based on the results + +// all the same +static double rs_length_diff_defaults[] = { + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 +}; + +static double cost_per_card_ms_defaults[] = { + 0.01, 0.005, 0.005, 0.003, 0.003, 0.002, 0.002, 0.0015 +}; + +// all the same +static double young_cards_per_entry_ratio_defaults[] = { + 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0 +}; + +static double cost_per_entry_ms_defaults[] = { + 0.015, 0.01, 0.01, 0.008, 0.008, 0.0055, 0.0055, 0.005 +}; + +static double cost_per_byte_ms_defaults[] = { + 0.00006, 0.00003, 0.00003, 0.000015, 0.000015, 0.00001, 0.00001, 0.000009 +}; + +// these should be pretty consistent +static double constant_other_time_ms_defaults[] = { + 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0 +}; + + +static double young_other_cost_per_region_ms_defaults[] = { + 0.3, 0.2, 0.2, 0.15, 0.15, 0.12, 0.12, 0.1 +}; + +static double non_young_other_cost_per_region_ms_defaults[] = { + 1.0, 0.7, 0.7, 0.5, 0.5, 0.42, 0.42, 0.30 +}; + +G1Analytics::G1Analytics(const G1Predictions* predictor) : + _predictor(predictor), + _recent_gc_times_ms(new TruncatedSeq(NumPrevPausesForHeuristics)), + _concurrent_mark_remark_times_ms(new TruncatedSeq(NumPrevPausesForHeuristics)), + _concurrent_mark_cleanup_times_ms(new TruncatedSeq(NumPrevPausesForHeuristics)), + _alloc_rate_ms_seq(new TruncatedSeq(TruncatedSeqLength)), + _prev_collection_pause_end_ms(0.0), + _rs_length_diff_seq(new TruncatedSeq(TruncatedSeqLength)), + _cost_per_card_ms_seq(new TruncatedSeq(TruncatedSeqLength)), + _cost_scan_hcc_seq(new TruncatedSeq(TruncatedSeqLength)), + _young_cards_per_entry_ratio_seq(new TruncatedSeq(TruncatedSeqLength)), + _mixed_cards_per_entry_ratio_seq(new TruncatedSeq(TruncatedSeqLength)), + _cost_per_entry_ms_seq(new TruncatedSeq(TruncatedSeqLength)), + _mixed_cost_per_entry_ms_seq(new TruncatedSeq(TruncatedSeqLength)), + _cost_per_byte_ms_seq(new TruncatedSeq(TruncatedSeqLength)), + _cost_per_byte_ms_during_cm_seq(new TruncatedSeq(TruncatedSeqLength)), + _constant_other_time_ms_seq(new TruncatedSeq(TruncatedSeqLength)), + _young_other_cost_per_region_ms_seq(new TruncatedSeq(TruncatedSeqLength)), + _non_young_other_cost_per_region_ms_seq(new TruncatedSeq(TruncatedSeqLength)), + _pending_cards_seq(new TruncatedSeq(TruncatedSeqLength)), + _rs_lengths_seq(new TruncatedSeq(TruncatedSeqLength)), + _recent_prev_end_times_for_all_gcs_sec(new TruncatedSeq(NumPrevPausesForHeuristics)) { + + // Seed sequences with initial values. + _recent_prev_end_times_for_all_gcs_sec->add(os::elapsedTime()); + _prev_collection_pause_end_ms = os::elapsedTime() * 1000.0; + + int index = MIN2(ParallelGCThreads - 1, 7u); + + _rs_length_diff_seq->add(rs_length_diff_defaults[index]); + _cost_per_card_ms_seq->add(cost_per_card_ms_defaults[index]); + _cost_scan_hcc_seq->add(0.0); + _young_cards_per_entry_ratio_seq->add(young_cards_per_entry_ratio_defaults[index]); + _cost_per_entry_ms_seq->add(cost_per_entry_ms_defaults[index]); + _cost_per_byte_ms_seq->add(cost_per_byte_ms_defaults[index]); + _constant_other_time_ms_seq->add(constant_other_time_ms_defaults[index]); + _young_other_cost_per_region_ms_seq->add(young_other_cost_per_region_ms_defaults[index]); + _non_young_other_cost_per_region_ms_seq->add(non_young_other_cost_per_region_ms_defaults[index]); + + // start conservatively (around 50ms is about right) + _concurrent_mark_remark_times_ms->add(0.05); + _concurrent_mark_cleanup_times_ms->add(0.20); +} + +double G1Analytics::get_new_prediction(TruncatedSeq const* seq) const { + return _predictor->get_new_prediction(seq); +} + +size_t G1Analytics::get_new_size_prediction(TruncatedSeq const* seq) const { + return (size_t)get_new_prediction(seq); +} + +int G1Analytics::num_alloc_rate_ms() const { + return _alloc_rate_ms_seq->num(); +} + +void G1Analytics::report_concurrent_mark_remark_times_ms(double ms) { + _concurrent_mark_remark_times_ms->add(ms); +} + +void G1Analytics::report_alloc_rate_ms(double alloc_rate) { + _alloc_rate_ms_seq->add(alloc_rate); +} + +void G1Analytics::compute_pause_time_ratio(double interval_ms, double pause_time_ms) { + _recent_avg_pause_time_ratio = _recent_gc_times_ms->sum() / interval_ms; + if (_recent_avg_pause_time_ratio < 0.0 || + (_recent_avg_pause_time_ratio - 1.0 > 0.0)) { + // Clip ratio between 0.0 and 1.0, and continue. This will be fixed in + // CR 6902692 by redoing the manner in which the ratio is incrementally computed. + if (_recent_avg_pause_time_ratio < 0.0) { + _recent_avg_pause_time_ratio = 0.0; + } else { + assert(_recent_avg_pause_time_ratio - 1.0 > 0.0, "Ctl-point invariant"); + _recent_avg_pause_time_ratio = 1.0; + } + } + + // Compute the ratio of just this last pause time to the entire time range stored + // in the vectors. Comparing this pause to the entire range, rather than only the + // most recent interval, has the effect of smoothing over a possible transient 'burst' + // of more frequent pauses that don't really reflect a change in heap occupancy. + // This reduces the likelihood of a needless heap expansion being triggered. + _last_pause_time_ratio = + (pause_time_ms * _recent_prev_end_times_for_all_gcs_sec->num()) / interval_ms; +} + +void G1Analytics::report_cost_per_card_ms(double cost_per_card_ms) { + _cost_per_card_ms_seq->add(cost_per_card_ms); +} + +void G1Analytics::report_cost_scan_hcc(double cost_scan_hcc) { + _cost_scan_hcc_seq->add(cost_scan_hcc); +} + +void G1Analytics::report_cost_per_entry_ms(double cost_per_entry_ms, bool last_gc_was_young) { + if (last_gc_was_young) { + _cost_per_entry_ms_seq->add(cost_per_entry_ms); + } else { + _mixed_cost_per_entry_ms_seq->add(cost_per_entry_ms); + } +} + +void G1Analytics::report_cards_per_entry_ratio(double cards_per_entry_ratio, bool last_gc_was_young) { + if (last_gc_was_young) { + _young_cards_per_entry_ratio_seq->add(cards_per_entry_ratio); + } else { + _mixed_cards_per_entry_ratio_seq->add(cards_per_entry_ratio); + } +} + +void G1Analytics::report_rs_length_diff(double rs_length_diff) { + _rs_length_diff_seq->add(rs_length_diff); +} + +void G1Analytics::report_cost_per_byte_ms(double cost_per_byte_ms, bool in_marking_window) { + if (in_marking_window) { + _cost_per_byte_ms_during_cm_seq->add(cost_per_byte_ms); + } else { + _cost_per_byte_ms_seq->add(cost_per_byte_ms); + } +} + +void G1Analytics::report_young_other_cost_per_region_ms(double other_cost_per_region_ms) { + _young_other_cost_per_region_ms_seq->add(other_cost_per_region_ms); +} + +void G1Analytics::report_non_young_other_cost_per_region_ms(double other_cost_per_region_ms) { + _non_young_other_cost_per_region_ms_seq->add(other_cost_per_region_ms); +} + +void G1Analytics::report_constant_other_time_ms(double constant_other_time_ms) { + _constant_other_time_ms_seq->add(constant_other_time_ms); +} + +void G1Analytics::report_pending_cards(double pending_cards) { + _pending_cards_seq->add(pending_cards); +} + +void G1Analytics::report_rs_lengths(double rs_lengths) { + _rs_lengths_seq->add(rs_lengths); +} + +size_t G1Analytics::predict_rs_length_diff() const { + return get_new_size_prediction(_rs_length_diff_seq); +} + +double G1Analytics::predict_alloc_rate_ms() const { + return get_new_prediction(_alloc_rate_ms_seq); +} + +double G1Analytics::predict_cost_per_card_ms() const { + return get_new_prediction(_cost_per_card_ms_seq); +} + +double G1Analytics::predict_scan_hcc_ms() const { + return get_new_prediction(_cost_scan_hcc_seq); +} + +double G1Analytics::predict_rs_update_time_ms(size_t pending_cards) const { + return pending_cards * predict_cost_per_card_ms() + predict_scan_hcc_ms(); +} + +double G1Analytics::predict_young_cards_per_entry_ratio() const { + return get_new_prediction(_young_cards_per_entry_ratio_seq); +} + +double G1Analytics::predict_mixed_cards_per_entry_ratio() const { + if (_mixed_cards_per_entry_ratio_seq->num() < 2) { + return predict_young_cards_per_entry_ratio(); + } else { + return get_new_prediction(_mixed_cards_per_entry_ratio_seq); + } +} + +size_t G1Analytics::predict_card_num(size_t rs_length, bool gcs_are_young) const { + if (gcs_are_young) { + return (size_t) (rs_length * predict_young_cards_per_entry_ratio()); + } else { + return (size_t) (rs_length * predict_mixed_cards_per_entry_ratio()); + } +} + +double G1Analytics::predict_rs_scan_time_ms(size_t card_num, bool gcs_are_young) const { + if (gcs_are_young) { + return card_num * get_new_prediction(_cost_per_entry_ms_seq); + } else { + return predict_mixed_rs_scan_time_ms(card_num); + } +} + +double G1Analytics::predict_mixed_rs_scan_time_ms(size_t card_num) const { + if (_mixed_cost_per_entry_ms_seq->num() < 3) { + return card_num * get_new_prediction(_cost_per_entry_ms_seq); + } else { + return card_num * get_new_prediction(_mixed_cost_per_entry_ms_seq); + } +} + +double G1Analytics::predict_object_copy_time_ms_during_cm(size_t bytes_to_copy) const { + if (_cost_per_byte_ms_during_cm_seq->num() < 3) { + return (1.1 * bytes_to_copy) * get_new_prediction(_cost_per_byte_ms_seq); + } else { + return bytes_to_copy * get_new_prediction(_cost_per_byte_ms_during_cm_seq); + } +} + +double G1Analytics::predict_object_copy_time_ms(size_t bytes_to_copy, bool during_concurrent_mark) const { + if (during_concurrent_mark) { + return predict_object_copy_time_ms_during_cm(bytes_to_copy); + } else { + return bytes_to_copy * get_new_prediction(_cost_per_byte_ms_seq); + } +} + +double G1Analytics::predict_constant_other_time_ms() const { + return get_new_prediction(_constant_other_time_ms_seq); +} + +double G1Analytics::predict_young_other_time_ms(size_t young_num) const { + return young_num * get_new_prediction(_young_other_cost_per_region_ms_seq); +} + +double G1Analytics::predict_non_young_other_time_ms(size_t non_young_num) const { + return non_young_num * get_new_prediction(_non_young_other_cost_per_region_ms_seq); +} + +double G1Analytics::predict_remark_time_ms() const { + return get_new_prediction(_concurrent_mark_remark_times_ms); +} + +double G1Analytics::predict_cleanup_time_ms() const { + return get_new_prediction(_concurrent_mark_cleanup_times_ms); +} + +size_t G1Analytics::predict_rs_lengths() const { + return get_new_size_prediction(_rs_lengths_seq); +} + +size_t G1Analytics::predict_pending_cards() const { + return get_new_size_prediction(_pending_cards_seq); +} + +double G1Analytics::last_known_gc_end_time_sec() const { + return _recent_prev_end_times_for_all_gcs_sec->oldest(); +} + +void G1Analytics::update_recent_gc_times(double end_time_sec, + double pause_time_ms) { + _recent_gc_times_ms->add(pause_time_ms); + _recent_prev_end_times_for_all_gcs_sec->add(end_time_sec); + _prev_collection_pause_end_ms = end_time_sec * 1000.0; +} + +void G1Analytics::report_concurrent_mark_cleanup_times_ms(double ms) { + _concurrent_mark_cleanup_times_ms->add(ms); +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/src/share/vm/gc/g1/g1Analytics.hpp Thu Apr 07 09:47:48 2016 -0700 @@ -0,0 +1,159 @@ +/* + * Copyright (c) 2016, 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_G1_G1MEASUREMENTS_HPP +#define SHARE_VM_GC_G1_G1MEASUREMENTS_HPP + +#include "memory/allocation.hpp" +#include "utilities/globalDefinitions.hpp" + +class TruncatedSeq; +class G1Predictions; + +class G1Analytics: public CHeapObj<mtGC> { + const static int TruncatedSeqLength = 10; + const static int NumPrevPausesForHeuristics = 10; + const G1Predictions* _predictor; + + // These exclude marking times. + TruncatedSeq* _recent_gc_times_ms; + + TruncatedSeq* _concurrent_mark_remark_times_ms; + TruncatedSeq* _concurrent_mark_cleanup_times_ms; + + TruncatedSeq* _alloc_rate_ms_seq; + double _prev_collection_pause_end_ms; + + TruncatedSeq* _rs_length_diff_seq; + TruncatedSeq* _cost_per_card_ms_seq; + TruncatedSeq* _cost_scan_hcc_seq; + TruncatedSeq* _young_cards_per_entry_ratio_seq; + TruncatedSeq* _mixed_cards_per_entry_ratio_seq; + TruncatedSeq* _cost_per_entry_ms_seq; + TruncatedSeq* _mixed_cost_per_entry_ms_seq; + TruncatedSeq* _cost_per_byte_ms_seq; + TruncatedSeq* _constant_other_time_ms_seq; + TruncatedSeq* _young_other_cost_per_region_ms_seq; + TruncatedSeq* _non_young_other_cost_per_region_ms_seq; + + TruncatedSeq* _pending_cards_seq; + TruncatedSeq* _rs_lengths_seq; + + TruncatedSeq* _cost_per_byte_ms_during_cm_seq; + + // Statistics kept per GC stoppage, pause or full. + TruncatedSeq* _recent_prev_end_times_for_all_gcs_sec; + + // The ratio of gc time to elapsed time, computed over recent pauses, + // and the ratio for just the last pause. + double _recent_avg_pause_time_ratio; + double _last_pause_time_ratio; + + double get_new_prediction(TruncatedSeq const* seq) const; + size_t get_new_size_prediction(TruncatedSeq const* seq) const; + +public: + G1Analytics(const G1Predictions* predictor); + + double prev_collection_pause_end_ms() const { + return _prev_collection_pause_end_ms; + } + + double recent_avg_pause_time_ratio() const { + return _recent_avg_pause_time_ratio; + } + + double last_pause_time_ratio() const { + return _last_pause_time_ratio; + } + + uint number_of_recorded_pause_times() const { + return NumPrevPausesForHeuristics; + } + + void append_prev_collection_pause_end_ms(double ms) { + _prev_collection_pause_end_ms += ms; + } + + void report_concurrent_mark_remark_times_ms(double ms); + void report_concurrent_mark_cleanup_times_ms(double ms); + void report_alloc_rate_ms(double alloc_rate); + void report_cost_per_card_ms(double cost_per_card_ms); + void report_cost_scan_hcc(double cost_scan_hcc); + void report_cost_per_entry_ms(double cost_per_entry_ms, bool last_gc_was_young); + void report_cards_per_entry_ratio(double cards_per_entry_ratio, bool last_gc_was_young); + void report_rs_length_diff(double rs_length_diff); + void report_cost_per_byte_ms(double cost_per_byte_ms, bool in_marking_window); + void report_young_other_cost_per_region_ms(double other_cost_per_region_ms); + void report_non_young_other_cost_per_region_ms(double other_cost_per_region_ms); + void report_constant_other_time_ms(double constant_other_time_ms); + void report_pending_cards(double pending_cards); + void report_rs_lengths(double rs_lengths); + + size_t predict_rs_length_diff() const; + + double predict_alloc_rate_ms() const; + int num_alloc_rate_ms() const; + + double predict_cost_per_card_ms() const; + + double predict_scan_hcc_ms() const; + + double predict_rs_update_time_ms(size_t pending_cards) const; + + double predict_young_cards_per_entry_ratio() const; + + double predict_mixed_cards_per_entry_ratio() const; + + size_t predict_card_num(size_t rs_length, bool gcs_are_young) const; + + double predict_rs_scan_time_ms(size_t card_num, bool gcs_are_young) const; + + double predict_mixed_rs_scan_time_ms(size_t card_num) const; + + double predict_object_copy_time_ms_during_cm(size_t bytes_to_copy) const; + + double predict_object_copy_time_ms(size_t bytes_to_copy, bool during_concurrent_mark) const; + + double predict_constant_other_time_ms() const; + + double predict_young_other_time_ms(size_t young_num) const; + + double predict_non_young_other_time_ms(size_t non_young_num) const; + + double predict_remark_time_ms() const; + + double predict_cleanup_time_ms() const; + + size_t predict_rs_lengths() const; + size_t predict_pending_cards() const; + + // Add a new GC of the given duration and end time to the record. + void update_recent_gc_times(double end_time_sec, double elapsed_ms); + void compute_pause_time_ratio(double interval_ms, double pause_time_ms); + + double last_known_gc_end_time_sec() const; +}; + +#endif // SHARE_VM_GC_G1_G1MEASUREMENTS_HPP
--- a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp Mon Apr 04 13:40:18 2016 -0700 +++ b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp Thu Apr 07 09:47:48 2016 -0700 @@ -34,10 +34,12 @@ #include "gc/g1/concurrentMarkThread.inline.hpp" #include "gc/g1/g1Allocator.inline.hpp" #include "gc/g1/g1CollectedHeap.inline.hpp" +#include "gc/g1/g1CollectionSet.hpp" #include "gc/g1/g1CollectorPolicy.hpp" #include "gc/g1/g1CollectorState.hpp" #include "gc/g1/g1EvacStats.inline.hpp" #include "gc/g1/g1GCPhaseTimes.hpp" +#include "gc/g1/g1HeapSizingPolicy.hpp" #include "gc/g1/g1HeapTransition.hpp" #include "gc/g1/g1HeapVerifier.hpp" #include "gc/g1/g1MarkSweep.hpp" @@ -67,6 +69,7 @@ #include "logging/log.hpp" #include "memory/allocation.hpp" #include "memory/iterator.hpp" +#include "memory/resourceArea.hpp" #include "oops/oop.inline.hpp" #include "runtime/atomic.inline.hpp" #include "runtime/init.hpp" @@ -566,7 +569,7 @@ // Give a warning if we seem to be looping forever. if ((QueuedAllocationWarningCount > 0) && (try_count % QueuedAllocationWarningCount == 0)) { - warning("G1CollectedHeap::mem_allocate retries %d times", try_count); + log_warning(gc)("G1CollectedHeap::mem_allocate retries %d times", try_count); } } @@ -675,8 +678,8 @@ // Give a warning if we seem to be looping forever. if ((QueuedAllocationWarningCount > 0) && (try_count % QueuedAllocationWarningCount == 0)) { - warning("G1CollectedHeap::attempt_allocation_slow() " - "retries %d times", try_count); + log_warning(gc)("G1CollectedHeap::attempt_allocation_slow() " + "retries %d times", try_count); } } @@ -1091,8 +1094,8 @@ if ((QueuedAllocationWarningCount > 0) && (try_count % QueuedAllocationWarningCount == 0)) { - warning("G1CollectedHeap::attempt_allocation_humongous() " - "retries %d times", try_count); + log_warning(gc)("G1CollectedHeap::attempt_allocation_humongous() " + "retries %d times", try_count); } } @@ -1228,6 +1231,7 @@ ResourceMark rm; print_heap_before_gc(); + print_heap_regions(); trace_heap_before_gc(gc_tracer); size_t metadata_prev_used = MetaspaceAux::used_bytes(); @@ -1302,9 +1306,9 @@ // set between the last GC or pause and now. We need to clear the // incremental collection set and then start rebuilding it afresh // after this full GC. - abandon_collection_set(g1_policy()->inc_cset_head()); - g1_policy()->clear_incremental_cset(); - g1_policy()->stop_incremental_cset_building(); + abandon_collection_set(collection_set()->inc_head()); + collection_set()->clear_incremental(); + collection_set()->stop_incremental_building(); tear_down_region_sets(false /* free_list_only */); collector_state()->set_gcs_are_young(true); @@ -1421,13 +1425,13 @@ // the full GC has compacted objects and updated TAMS but not updated // the prev bitmap. if (G1VerifyBitmaps) { - ((G1CMBitMap*) concurrent_mark()->prevMarkBitMap())->clearAll(); + _cm->clear_prev_bitmap(workers()); } _verifier->check_bitmaps("Full GC End"); // Start a new incremental collection set for the next pause - assert(g1_policy()->collection_set() == NULL, "must be"); - g1_policy()->start_incremental_cset_building(); + assert(collection_set()->head() == NULL, "must be"); + collection_set()->start_incremental_building(); clear_cset_fast_test(); @@ -1446,6 +1450,7 @@ heap_transition.print(); print_heap_after_gc(); + print_heap_regions(); trace_heap_after_gc(gc_tracer); post_full_gc_dump(gc_timer); @@ -1741,6 +1746,7 @@ G1CollectedHeap::G1CollectedHeap(G1CollectorPolicy* policy_) : CollectedHeap(), _g1_policy(policy_), + _collection_set(this), _dirty_card_queue_set(false), _is_alive_closure_cm(this), _is_alive_closure_stw(this), @@ -1765,15 +1771,12 @@ _expand_heap_after_alloc_failure(true), _old_marking_cycles_started(0), _old_marking_cycles_completed(0), - _heap_summary_sent(false), _in_cset_fast_test(), _dirty_cards_region_list(NULL), _worker_cset_start_region(NULL), _worker_cset_start_region_time_stamp(NULL), _gc_timer_stw(new (ResourceObj::C_HEAP, mtGC) STWGCTimer()), - _gc_timer_cm(new (ResourceObj::C_HEAP, mtGC) ConcurrentGCTimer()), - _gc_tracer_stw(new (ResourceObj::C_HEAP, mtGC) G1NewTracer()), - _gc_tracer_cm(new (ResourceObj::C_HEAP, mtGC) G1OldTracer()) { + _gc_tracer_stw(new (ResourceObj::C_HEAP, mtGC) G1NewTracer()) { _workers = new WorkGang("GC Thread", ParallelGCThreads, /* are_GC_task_threads */true, @@ -1782,6 +1785,9 @@ _verifier = new G1HeapVerifier(this); _allocator = G1Allocator::create_allocator(this); + + _heap_sizing_policy = G1HeapSizingPolicy::create(this, _g1_policy->analytics()); + _humongous_object_threshold_in_words = humongous_threshold_for(HeapRegion::GrainWords); // Override the default _filler_array_max_size so that no humongous filler @@ -2314,52 +2320,6 @@ FullGCCount_lock->notify_all(); } -void G1CollectedHeap::register_concurrent_cycle_start(const Ticks& start_time) { - GCIdMarkAndRestore conc_gc_id_mark; - collector_state()->set_concurrent_cycle_started(true); - _gc_timer_cm->register_gc_start(start_time); - - _gc_tracer_cm->report_gc_start(gc_cause(), _gc_timer_cm->gc_start()); - trace_heap_before_gc(_gc_tracer_cm); - _cmThread->set_gc_id(GCId::current()); -} - -void G1CollectedHeap::register_concurrent_cycle_end() { - if (collector_state()->concurrent_cycle_started()) { - GCIdMarkAndRestore conc_gc_id_mark(_cmThread->gc_id()); - if (_cm->has_aborted()) { - _gc_tracer_cm->report_concurrent_mode_failure(); - - // ConcurrentGCTimer will be ended as well. - _cm->register_concurrent_gc_end_and_stop_timer(); - } else { - _gc_timer_cm->register_gc_end(); - } - - _gc_tracer_cm->report_gc_end(_gc_timer_cm->gc_end(), _gc_timer_cm->time_partitions()); - - // Clear state variables to prepare for the next concurrent cycle. - collector_state()->set_concurrent_cycle_started(false); - _heap_summary_sent = false; - } -} - -void G1CollectedHeap::trace_heap_after_concurrent_cycle() { - if (collector_state()->concurrent_cycle_started()) { - // This function can be called when: - // the cleanup pause is run - // the concurrent cycle is aborted before the cleanup pause. - // the concurrent cycle is aborted after the cleanup pause, - // but before the concurrent cycle end has been registered. - // Make sure that we only send the heap information once. - if (!_heap_summary_sent) { - GCIdMarkAndRestore conc_gc_id_mark(_cmThread->gc_id()); - trace_heap_after_gc(_gc_tracer_cm); - _heap_summary_sent = true; - } - } -} - void G1CollectedHeap::collect(GCCause::Cause cause) { assert_heap_not_locked(); @@ -2545,8 +2505,8 @@ // p threads // Then thread t will start at region floor ((t * n) / p) - result = g1_policy()->collection_set(); - uint cs_size = g1_policy()->cset_region_length(); + result = collection_set()->head(); + uint cs_size = collection_set()->region_length(); uint active_workers = workers()->active_workers(); uint end_ind = (cs_size * worker_i) / active_workers; @@ -2577,7 +2537,7 @@ } void G1CollectedHeap::collection_set_iterate(HeapRegionClosure* cl) { - HeapRegion* r = g1_policy()->collection_set(); + HeapRegion* r = collection_set()->head(); while (r != NULL) { HeapRegion* next = r->next_in_collection_set(); if (cl->doHeapRegion(r)) { @@ -2606,7 +2566,7 @@ } cur = next; } - cur = g1_policy()->collection_set(); + cur = collection_set()->head(); while (cur != r) { HeapRegion* next = cur->next_in_collection_set(); if (cl->doHeapRegion(cur) && false) { @@ -2716,6 +2676,14 @@ return false; // keep some compilers happy } +void G1CollectedHeap::print_heap_regions() const { + Log(gc, heap, region) log; + if (log.is_trace()) { + ResourceMark rm; + print_regions_on(log.trace_stream()); + } +} + void G1CollectedHeap::print_on(outputStream* st) const { st->print(" %-20s", "garbage-first heap"); st->print(" total " SIZE_FORMAT "K, used " SIZE_FORMAT "K", @@ -2729,18 +2697,14 @@ uint young_regions = _young_list->length(); st->print("%u young (" SIZE_FORMAT "K), ", young_regions, (size_t) young_regions * HeapRegion::GrainBytes / K); - uint survivor_regions = g1_policy()->recorded_survivor_regions(); + uint survivor_regions = _young_list->survivor_length(); st->print("%u survivors (" SIZE_FORMAT "K)", survivor_regions, (size_t) survivor_regions * HeapRegion::GrainBytes / K); st->cr(); MetaspaceAux::print_on(st); } -void G1CollectedHeap::print_extended_on(outputStream* st) const { - print_on(st); - - // Print the per-region information. - st->cr(); +void G1CollectedHeap::print_regions_on(outputStream* st) const { st->print_cr("Heap Regions: E=young(eden), S=young(survivor), O=old, " "HS=humongous(starts), HC=humongous(continues), " "CS=collection set, F=free, A=archive, TS=gc time stamp, " @@ -2750,6 +2714,13 @@ heap_region_iterate(&blk); } +void G1CollectedHeap::print_extended_on(outputStream* st) const { + print_on(st); + + // Print the per-region information. + print_regions_on(st); +} + void G1CollectedHeap::print_on_error(outputStream* st) const { this->CollectedHeap::print_on_error(st); @@ -2839,12 +2810,14 @@ size_t eden_used_bytes = young_list->eden_used_bytes(); size_t survivor_used_bytes = young_list->survivor_used_bytes(); + size_t heap_used = Heap_lock->owned_by_self() ? used() : used_unlocked(); size_t eden_capacity_bytes = (g1_policy()->young_list_target_length() * HeapRegion::GrainBytes) - survivor_used_bytes; VirtualSpaceSummary heap_summary = create_heap_space_summary(); - return G1HeapSummary(heap_summary, used(), eden_used_bytes, eden_capacity_bytes, survivor_used_bytes, num_regions()); + return G1HeapSummary(heap_summary, heap_used, eden_used_bytes, + eden_capacity_bytes, survivor_used_bytes, num_regions()); } G1EvacSummary G1CollectedHeap::create_g1_evac_summary(G1EvacStats* stats) { @@ -2862,7 +2835,6 @@ gc_tracer->report_metaspace_summary(when, metaspace_summary); } - G1CollectedHeap* G1CollectedHeap::heap() { CollectedHeap* heap = Universe::heap(); assert(heap != NULL, "Uninitialized access to G1CollectedHeap::heap()"); @@ -3138,10 +3110,10 @@ } void G1CollectedHeap::print_taskqueue_stats() const { - if (!log_develop_is_enabled(Trace, gc, task, stats)) { + if (!log_is_enabled(Trace, gc, task, stats)) { return; } - LogHandle(gc, task, stats) log; + Log(gc, task, stats) log; ResourceMark rm; outputStream* st = log.trace_stream(); @@ -3201,15 +3173,19 @@ wait_for_root_region_scanning(); print_heap_before_gc(); + print_heap_regions(); trace_heap_before_gc(_gc_tracer_stw); _verifier->verify_region_sets_optional(); _verifier->verify_dirty_young_regions(); - // This call will decide whether this pause is an initial-mark - // pause. If it is, during_initial_mark_pause() will return true - // for the duration of this pause. - g1_policy()->decide_on_conc_mark_initiation(); + // We should not be doing initial mark unless the conc mark thread is running + if (!_cmThread->should_terminate()) { + // This call will decide whether this pause is an initial-mark + // pause. If it is, during_initial_mark_pause() will return true + // for the duration of this pause. + g1_policy()->decide_on_conc_mark_initiation(); + } // We do not allow initial-mark to be piggy-backed on a mixed GC. assert(!collector_state()->during_initial_mark_pause() || @@ -3231,7 +3207,7 @@ // We are about to start a marking cycle, so we increment the // full collection counter. increment_old_marking_cycles_started(); - register_concurrent_cycle_start(_gc_timer_stw->gc_start()); + _cm->gc_tracer_cm()->set_gc_cause(gc_cause()); } _gc_tracer_stw->report_yc_type(collector_state()->yc_type()); @@ -3253,7 +3229,7 @@ Threads::number_of_non_daemon_threads()); workers()->set_active_workers(active_workers); - g1_policy()->note_gc_start(active_workers); + g1_policy()->note_gc_start(); TraceCollectorStats tcs(g1mm()->incremental_collection_counters()); TraceMemoryManagerStats tms(false /* fullGC */, gc_cause()); @@ -3336,10 +3312,9 @@ concurrent_mark()->checkpointRootsInitialPre(); } - double time_remaining_ms = g1_policy()->finalize_young_cset_part(target_pause_time_ms); - g1_policy()->finalize_old_cset_part(time_remaining_ms); - - evacuation_info.set_collectionset_regions(g1_policy()->cset_region_length()); + g1_policy()->finalize_collection_set(target_pause_time_ms); + + evacuation_info.set_collectionset_regions(collection_set()->region_length()); // Make sure the remembered sets are up to date. This needs to be // done before register_humongous_regions_with_cset(), because the @@ -3358,7 +3333,7 @@ _cm->verify_no_cset_oops(); if (_hr_printer.is_active()) { - HeapRegion* hr = g1_policy()->collection_set(); + HeapRegion* hr = collection_set()->head(); while (hr != NULL) { _hr_printer.cset(hr); hr = hr->next_in_collection_set(); @@ -3373,7 +3348,7 @@ // Initialize the GC alloc regions. _allocator->init_gc_alloc_regions(evacuation_info); - G1ParScanThreadStateSet per_thread_states(this, workers()->active_workers(), g1_policy()->young_cset_region_length()); + G1ParScanThreadStateSet per_thread_states(this, workers()->active_workers(), collection_set()->young_region_length()); pre_evacuate_collection_set(); // Actually do the work... @@ -3382,18 +3357,18 @@ post_evacuate_collection_set(evacuation_info, &per_thread_states); const size_t* surviving_young_words = per_thread_states.surviving_young_words(); - free_collection_set(g1_policy()->collection_set(), evacuation_info, surviving_young_words); + free_collection_set(collection_set()->head(), evacuation_info, surviving_young_words); eagerly_reclaim_humongous_regions(); - g1_policy()->clear_collection_set(); + collection_set()->clear_head(); record_obj_copy_mem_stats(); _survivor_evac_stats.adjust_desired_plab_sz(); _old_evac_stats.adjust_desired_plab_sz(); // Start a new incremental collection set for the next pause. - g1_policy()->start_incremental_cset_building(); + collection_set()->start_incremental_building(); clear_cset_fast_test(); @@ -3404,10 +3379,6 @@ assert(check_young_list_empty(false /* check_heap */), "young list should be empty"); - g1_policy()->record_survivor_regions(_young_list->survivor_length(), - _young_list->first_survivor_region(), - _young_list->last_survivor_region()); - _young_list->reset_auxilary_lists(); if (evacuation_failed()) { @@ -3442,7 +3413,7 @@ _allocator->init_mutator_alloc_region(); { - size_t expand_bytes = g1_policy()->expansion_amount(); + size_t expand_bytes = _heap_sizing_policy->expansion_amount(); if (expand_bytes > 0) { size_t bytes_before = capacity(); // No need for an ergo logging here, @@ -3468,7 +3439,7 @@ size_t total_cards_scanned = per_thread_states.total_cards_scanned(); g1_policy()->record_collection_pause_end(pause_time_ms, total_cards_scanned, heap_used_bytes_before_gc); - evacuation_info.set_collectionset_used_before(g1_policy()->collection_set_bytes_used_before()); + evacuation_info.set_collectionset_used_before(collection_set()->bytes_used_before()); evacuation_info.set_bytes_copied(g1_policy()->bytes_copied_during_gc()); MemoryService::track_memory_usage(); @@ -3538,6 +3509,7 @@ TASKQUEUE_STATS_ONLY(reset_taskqueue_stats()); print_heap_after_gc(); + print_heap_regions(); trace_heap_after_gc(_gc_tracer_stw); // We must call G1MonitoringSupport::update_sizes() in the same scoping level @@ -3776,11 +3748,12 @@ "claim value %d after unlink less than initial symbol table size %d", SymbolTable::parallel_claimed_index(), _initial_symbol_table_size); - log_debug(gc, stringdedup)("Cleaned string and symbol table, " - "strings: " SIZE_FORMAT " processed, " SIZE_FORMAT " removed, " - "symbols: " SIZE_FORMAT " processed, " SIZE_FORMAT " removed", - strings_processed(), strings_removed(), - symbols_processed(), symbols_removed()); + log_info(gc, stringtable)( + "Cleaned string and symbol table, " + "strings: " SIZE_FORMAT " processed, " SIZE_FORMAT " removed, " + "symbols: " SIZE_FORMAT " processed, " SIZE_FORMAT " removed", + strings_processed(), strings_removed(), + symbols_processed(), symbols_removed()); } void work(uint worker_id) { @@ -4083,14 +4056,10 @@ void G1CollectedHeap::unlink_string_and_symbol_table(BoolObjectClosure* is_alive, bool process_strings, bool process_symbols) { - { + { // Timing scope G1StringSymbolTableUnlinkTask g1_unlink_task(is_alive, process_strings, process_symbols); workers()->run_task(&g1_unlink_task); } - - if (G1StringDedup::is_enabled()) { - G1StringDedup::unlink(is_alive); - } } class G1RedirtyLoggedCardsTask : public AbstractGangTask { @@ -4279,7 +4248,7 @@ _workers(workers), _active_workers(n_workers) { - assert(n_workers > 0, "shouldn't call this otherwise"); + g1h->ref_processor_stw()->set_active_mt_degree(n_workers); } // Executes the given task using concurrent marking worker threads. @@ -4400,7 +4369,9 @@ _queues(task_queues), _terminator(workers, _queues), _n_workers(workers) - { } + { + g1h->ref_processor_cm()->set_active_mt_degree(workers); + } void work(uint worker_id) { G1GCParPhaseTimesTracker x(_g1h->g1_policy()->phase_times(), G1GCPhaseTimes::PreserveCMReferents, worker_id); @@ -4543,8 +4514,9 @@ uint no_of_gc_workers = workers()->active_workers(); // Parallel reference processing - assert(rp->num_q() == no_of_gc_workers, "sanity"); - assert(no_of_gc_workers <= rp->max_num_q(), "sanity"); + assert(no_of_gc_workers <= rp->max_num_q(), + "Mismatch between the number of GC workers %u and the maximum number of Reference process queues %u", + no_of_gc_workers, rp->max_num_q()); G1STWRefProcTaskExecutor par_task_executor(this, per_thread_states, workers(), _task_queues, no_of_gc_workers); stats = rp->process_discovered_references(&is_alive, @@ -4580,8 +4552,9 @@ uint n_workers = workers()->active_workers(); - assert(rp->num_q() == n_workers, "sanity"); - assert(n_workers <= rp->max_num_q(), "sanity"); + assert(n_workers <= rp->max_num_q(), + "Mismatch between the number of GC workers %u and the maximum number of Reference process queues %u", + n_workers, rp->max_num_q()); G1STWRefProcTaskExecutor par_task_executor(this, per_thread_states, workers(), _task_queues, n_workers); rp->enqueue_discovered_references(&par_task_executor); @@ -4909,7 +4882,7 @@ if (cur->is_young()) { int index = cur->young_index_in_cset(); assert(index != -1, "invariant"); - assert((uint) index < policy->young_cset_region_length(), "invariant"); + assert((uint) index < collection_set()->young_region_length(), "invariant"); size_t words_survived = surviving_young_words[index]; cur->record_surv_words_in_group(words_survived); @@ -5382,7 +5355,7 @@ assert_heap_locked_or_at_safepoint(true /* should_be_vm_thread */); assert(alloc_region->is_eden(), "all mutator alloc regions should be eden"); - g1_policy()->add_region_to_incremental_cset_lhs(alloc_region); + collection_set()->add_eden_region(alloc_region); increase_used(allocated_bytes); _hr_printer.retire(alloc_region); // We update the eden sizes here, when the region is retired, @@ -5393,33 +5366,43 @@ // Methods for the GC alloc regions -HeapRegion* G1CollectedHeap::new_gc_alloc_region(size_t word_size, - uint count, - InCSetState dest) { +bool G1CollectedHeap::has_more_regions(InCSetState dest) { + if (dest.is_old()) { + return true; + } else { + return young_list()->survivor_length() < g1_policy()->max_survivor_regions(); + } +} + +HeapRegion* G1CollectedHeap::new_gc_alloc_region(size_t word_size, InCSetState dest) { assert(FreeList_lock->owned_by_self(), "pre-condition"); - if (count < g1_policy()->max_regions(dest)) { - const bool is_survivor = (dest.is_young()); - HeapRegion* new_alloc_region = new_region(word_size, - !is_survivor, - true /* do_expand */); - if (new_alloc_region != NULL) { - // We really only need to do this for old regions given that we - // should never scan survivors. But it doesn't hurt to do it - // for survivors too. - new_alloc_region->record_timestamp(); - if (is_survivor) { - new_alloc_region->set_survivor(); - _verifier->check_bitmaps("Survivor Region Allocation", new_alloc_region); - } else { - new_alloc_region->set_old(); - _verifier->check_bitmaps("Old Region Allocation", new_alloc_region); - } - _hr_printer.alloc(new_alloc_region); - bool during_im = collector_state()->during_initial_mark_pause(); - new_alloc_region->note_start_of_copying(during_im); - return new_alloc_region; + if (!has_more_regions(dest)) { + return NULL; + } + + const bool is_survivor = dest.is_young(); + + HeapRegion* new_alloc_region = new_region(word_size, + !is_survivor, + true /* do_expand */); + if (new_alloc_region != NULL) { + // We really only need to do this for old regions given that we + // should never scan survivors. But it doesn't hurt to do it + // for survivors too. + new_alloc_region->record_timestamp(); + if (is_survivor) { + new_alloc_region->set_survivor(); + young_list()->add_survivor_region(new_alloc_region); + _verifier->check_bitmaps("Survivor Region Allocation", new_alloc_region); + } else { + new_alloc_region->set_old(); + _verifier->check_bitmaps("Old Region Allocation", new_alloc_region); } + _hr_printer.alloc(new_alloc_region); + bool during_im = collector_state()->during_initial_mark_pause(); + new_alloc_region->note_start_of_copying(during_im); + return new_alloc_region; } return NULL; } @@ -5430,9 +5413,7 @@ bool during_im = collector_state()->during_initial_mark_pause(); alloc_region->note_end_of_copying(during_im); g1_policy()->record_bytes_copied_during_gc(allocated_bytes); - if (dest.is_young()) { - young_list()->add_survivor_region(alloc_region); - } else { + if (dest.is_old()) { _old_set.add(alloc_region); } _hr_printer.retire(alloc_region);
--- a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.hpp Mon Apr 04 13:40:18 2016 -0700 +++ b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.hpp Thu Apr 07 09:47:48 2016 -0700 @@ -28,6 +28,7 @@ #include "gc/g1/evacuationInfo.hpp" #include "gc/g1/g1AllocationContext.hpp" #include "gc/g1/g1BiasedArray.hpp" +#include "gc/g1/g1CollectionSet.hpp" #include "gc/g1/g1CollectorState.hpp" #include "gc/g1/g1ConcurrentMark.hpp" #include "gc/g1/g1HRPrinter.hpp" @@ -65,17 +66,16 @@ class SpaceClosure; class CompactibleSpaceClosure; class Space; +class G1CollectionSet; class G1CollectorPolicy; class G1RemSet; class HeapRegionRemSetIterator; class G1ConcurrentMark; class ConcurrentMarkThread; class ConcurrentG1Refine; -class ConcurrentGCTimer; class GenerationCounters; class STWGCTimer; class G1NewTracer; -class G1OldTracer; class EvacuationFailedInfo; class nmethod; class Ticks; @@ -83,6 +83,7 @@ class G1Allocator; class G1ArchiveAllocator; class G1HeapVerifier; +class G1HeapSizingPolicy; typedef OverflowTaskQueue<StarTask, mtGC> RefToScanQueue; typedef GenericTaskQueueSet<RefToScanQueue, mtGC> RefToScanQueueSet; @@ -268,8 +269,6 @@ // concurrent cycles) we have completed. volatile uint _old_marking_cycles_completed; - bool _heap_summary_sent; - // This is a non-product method that is helpful for testing. It is // called at the end of a GC and artificially expands the heap by // allocating a number of dead regions. This way we can induce very @@ -362,6 +361,9 @@ // The current policy object for the collector. G1CollectorPolicy* _g1_policy; + G1HeapSizingPolicy* _heap_sizing_policy; + + G1CollectionSet _collection_set; // This is the second level of trying to allocate a new region. If // new_region() didn't find a region on the free_list, this call will @@ -469,8 +471,8 @@ size_t allocated_bytes); // For GC alloc regions. - HeapRegion* new_gc_alloc_region(size_t word_size, uint count, - InCSetState dest); + bool has_more_regions(InCSetState dest); + HeapRegion* new_gc_alloc_region(size_t word_size, InCSetState dest); void retire_gc_alloc_region(HeapRegion* alloc_region, size_t allocated_bytes, InCSetState dest); @@ -618,10 +620,6 @@ return _old_marking_cycles_completed; } - void register_concurrent_cycle_start(const Ticks& start_time); - void register_concurrent_cycle_end(); - void trace_heap_after_concurrent_cycle(); - G1HRPrinter* hr_printer() { return &_hr_printer; } // Allocates a new heap region instance. @@ -896,9 +894,7 @@ ReferenceProcessor* _ref_processor_stw; STWGCTimer* _gc_timer_stw; - ConcurrentGCTimer* _gc_timer_cm; - G1OldTracer* _gc_tracer_cm; G1NewTracer* _gc_tracer_stw; // During reference object discovery, the _is_alive_non_header @@ -985,6 +981,9 @@ // The current policy object for the collector. G1CollectorPolicy* g1_policy() const { return _g1_policy; } + const G1CollectionSet* collection_set() const { return &_collection_set; } + G1CollectionSet* collection_set() { return &_collection_set; } + virtual CollectorPolicy* collector_policy() const; // Adaptive size policy. No such thing for g1. @@ -1029,9 +1028,6 @@ // The Concurrent Marking reference processor... ReferenceProcessor* ref_processor_cm() const { return _ref_processor_cm; } - ConcurrentGCTimer* gc_timer_cm() const { return _gc_timer_cm; } - G1OldTracer* gc_tracer_cm() const { return _gc_tracer_cm; } - virtual size_t capacity() const; virtual size_t used() const; // This should be called when we're not holding the heap lock. The @@ -1285,6 +1281,12 @@ return true; } + // The reference pending list lock is acquired from from the + // ConcurrentMarkThread. + virtual bool needs_reference_pending_list_locker_thread() const { + return true; + } + inline bool is_in_young(const oop obj); virtual bool is_scavengable(const void* addr); @@ -1463,7 +1465,11 @@ G1EvacSummary create_g1_evac_summary(G1EvacStats* stats); // Printing +private: + void print_heap_regions() const; + void print_regions_on(outputStream* st) const; +public: virtual void print_on(outputStream* st) const; virtual void print_extended_on(outputStream* st) const; virtual void print_on_error(outputStream* st) const;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/src/share/vm/gc/g1/g1CollectionSet.cpp Thu Apr 07 09:47:48 2016 -0700 @@ -0,0 +1,426 @@ +/* + * Copyright (c) 2016, 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/g1/g1CollectedHeap.hpp" +#include "gc/g1/g1CollectionSet.hpp" +#include "gc/g1/g1CollectorPolicy.hpp" +#include "gc/g1/g1CollectorState.hpp" +#include "gc/g1/heapRegion.inline.hpp" +#include "gc/g1/heapRegionRemSet.hpp" +#include "gc/g1/heapRegionSet.hpp" +#include "utilities/debug.hpp" + +G1CollectorState* G1CollectionSet::collector_state() { + return _g1->collector_state(); +} + +G1GCPhaseTimes* G1CollectionSet::phase_times() { + return _policy->phase_times(); +} + +CollectionSetChooser* G1CollectionSet::cset_chooser() { + return _cset_chooser; +} + +double G1CollectionSet::predict_region_elapsed_time_ms(HeapRegion* hr) { + return _policy->predict_region_elapsed_time_ms(hr, collector_state()->gcs_are_young()); +} + + +G1CollectionSet::G1CollectionSet(G1CollectedHeap* g1h) : + _g1(g1h), + _policy(NULL), + _cset_chooser(new CollectionSetChooser()), + _eden_region_length(0), + _survivor_region_length(0), + _old_region_length(0), + + _head(NULL), + _bytes_used_before(0), + _recorded_rs_lengths(0), + // Incremental CSet attributes + _inc_build_state(Inactive), + _inc_head(NULL), + _inc_tail(NULL), + _inc_bytes_used_before(0), + _inc_recorded_rs_lengths(0), + _inc_recorded_rs_lengths_diffs(0), + _inc_predicted_elapsed_time_ms(0.0), + _inc_predicted_elapsed_time_ms_diffs(0.0) {} + +G1CollectionSet::~G1CollectionSet() { + delete _cset_chooser; +} + +void G1CollectionSet::init_region_lengths(uint eden_cset_region_length, + uint survivor_cset_region_length) { + _eden_region_length = eden_cset_region_length; + _survivor_region_length = survivor_cset_region_length; + _old_region_length = 0; +} + +void G1CollectionSet::set_recorded_rs_lengths(size_t rs_lengths) { + _recorded_rs_lengths = rs_lengths; +} + +// Add the heap region at the head of the non-incremental collection set +void G1CollectionSet::add_old_region(HeapRegion* hr) { + assert(_inc_build_state == Active, "Precondition"); + assert(hr->is_old(), "the region should be old"); + + assert(!hr->in_collection_set(), "should not already be in the CSet"); + _g1->register_old_region_with_cset(hr); + hr->set_next_in_collection_set(_head); + _head = hr; + _bytes_used_before += hr->used(); + size_t rs_length = hr->rem_set()->occupied();