Merge
authorjwilhelm
Wed, 23 Mar 2016 23:36:29 +0100
changeset 37179 4dbcb3a642d2
parent 36617 390e8993b88e (current diff)
parent 37178 32d0f7759879 (diff)
child 37180 d73f2a3c0fdb
child 37182 18277fd690f4
Merge
hotspot/make/share/makefiles/mapfile-vers
hotspot/src/share/vm/classfile/classFileParser.cpp
hotspot/src/share/vm/classfile/javaClasses.cpp
hotspot/src/share/vm/classfile/javaClasses.hpp
hotspot/src/share/vm/classfile/systemDictionary.cpp
hotspot/src/share/vm/classfile/vmSymbols.hpp
hotspot/src/share/vm/compiler/compileBroker.cpp
hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp
hotspot/src/share/vm/interpreter/interpreterRuntime.cpp
hotspot/src/share/vm/logging/logTag.hpp
hotspot/src/share/vm/memory/filemap.cpp
hotspot/src/share/vm/memory/metaspaceShared.cpp
hotspot/src/share/vm/memory/universe.cpp
hotspot/src/share/vm/oops/method.cpp
hotspot/src/share/vm/prims/jni.cpp
hotspot/src/share/vm/prims/jvm.cpp
hotspot/src/share/vm/prims/jvm.h
hotspot/src/share/vm/prims/jvmtiEnv.cpp
hotspot/src/share/vm/prims/methodHandles.cpp
hotspot/src/share/vm/prims/whitebox.cpp
hotspot/src/share/vm/runtime/arguments.cpp
hotspot/src/share/vm/runtime/arguments.hpp
hotspot/src/share/vm/runtime/jniHandles.cpp
hotspot/src/share/vm/runtime/jniHandles.hpp
hotspot/src/share/vm/runtime/logTimer.hpp
hotspot/src/share/vm/runtime/mutexLocker.cpp
hotspot/src/share/vm/runtime/mutexLocker.hpp
hotspot/src/share/vm/runtime/os.cpp
hotspot/src/share/vm/runtime/os.hpp
hotspot/src/share/vm/runtime/reflection.cpp
hotspot/src/share/vm/runtime/sharedRuntime.cpp
hotspot/src/share/vm/runtime/sharedRuntime.hpp
hotspot/src/share/vm/runtime/thread.cpp
hotspot/src/share/vm/trace/traceMacros.hpp
hotspot/src/share/vm/utilities/ostream.cpp
--- a/hotspot/make/aix/adlc_updater	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/make/aix/adlc_updater	Wed Mar 23 23:36:29 2016 +0100
@@ -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	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/make/aix/makefiles/trace.make	Wed Mar 23 23:36:29 2016 +0100
@@ -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	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/make/bsd/adlc_updater	Wed Mar 23 23:36:29 2016 +0100
@@ -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	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/make/bsd/makefiles/trace.make	Wed Mar 23 23:36:29 2016 +0100
@@ -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	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/make/linux/adlc_updater	Wed Mar 23 23:36:29 2016 +0100
@@ -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	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/make/linux/makefiles/trace.make	Wed Mar 23 23:36:29 2016 +0100
@@ -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	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/make/share/makefiles/mapfile-vers	Wed Mar 23 23:36:29 2016 +0100
@@ -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	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/make/solaris/adlc_updater	Wed Mar 23 23:36:29 2016 +0100
@@ -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	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/make/solaris/makefiles/trace.make	Wed Mar 23 23:36:29 2016 +0100
@@ -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	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/make/windows/build.make	Wed Mar 23 23:36:29 2016 +0100
@@ -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	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/make/windows/create_obj_files.sh	Wed Mar 23 23:36:29 2016 +0100
@@ -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	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/make/windows/makefiles/defs.make	Wed Mar 23 23:36:29 2016 +0100
@@ -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	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/make/windows/makefiles/trace.make	Wed Mar 23 23:36:29 2016 +0100
@@ -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	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/make/windows/makefiles/vm.make	Wed Mar 23 23:36:29 2016 +0100
@@ -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/templateInterpreterGenerator_aarch64.cpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/cpu/aarch64/vm/templateInterpreterGenerator_aarch64.cpp	Wed Mar 23 23:36:29 2016 +0100
@@ -1967,7 +1967,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/templateInterpreterGenerator_ppc.cpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/cpu/ppc/vm/templateInterpreterGenerator_ppc.cpp	Wed Mar 23 23:36:29 2016 +0100
@@ -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/templateInterpreterGenerator_sparc.cpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/cpu/sparc/vm/templateInterpreterGenerator_sparc.cpp	Wed Mar 23 23:36:29 2016 +0100
@@ -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/frame_x86.hpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/cpu/x86/vm/frame_x86.hpp	Wed Mar 23 23:36:29 2016 +0100
@@ -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	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/cpu/x86/vm/interp_masm_x86.cpp	Wed Mar 23 23:36:29 2016 +0100
@@ -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);
   }
--- a/hotspot/src/cpu/x86/vm/templateInterpreterGenerator_x86.cpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/cpu/x86/vm/templateInterpreterGenerator_x86.cpp	Wed Mar 23 23:36:29 2016 +0100
@@ -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/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/SAGetopt.java	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/SAGetopt.java	Wed Mar 23 23:36:29 2016 +0100
@@ -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	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/SALauncher.java	Wed Mar 23 23:36:29 2016 +0100
@@ -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	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/shared/GCCause.java	Wed Mar 23 23:36:29 2016 +0100
@@ -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/runtime/Threads.java	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/Threads.java	Wed Mar 23 23:36:29 2016 +0100
@@ -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	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/JSnap.java	Wed Mar 23 23:36:29 2016 +0100
@@ -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	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/CompactHashTable.java	Wed Mar 23 23:36:29 2016 +0100
@@ -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/sa.js	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/soql/sa.js	Wed Mar 23 23:36:29 2016 +0100
@@ -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	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/os/aix/vm/os_aix.cpp	Wed Mar 23 23:36:29 2016 +0100
@@ -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	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/os/aix/vm/perfMemory_aix.cpp	Wed Mar 23 23:36:29 2016 +0100
@@ -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	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/os/bsd/vm/os_bsd.cpp	Wed Mar 23 23:36:29 2016 +0100
@@ -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	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/os/bsd/vm/perfMemory_bsd.cpp	Wed Mar 23 23:36:29 2016 +0100
@@ -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	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/os/linux/vm/os_linux.cpp	Wed Mar 23 23:36:29 2016 +0100
@@ -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(&current);
+    pthread_sigmask(SIG_SETMASK, NULL, &current);
+    assert(!sigismember(&current, 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	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/os/linux/vm/perfMemory_linux.cpp	Wed Mar 23 23:36:29 2016 +0100
@@ -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	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/os/posix/vm/os_posix.cpp	Wed Mar 23 23:36:29 2016 +0100
@@ -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	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/os/solaris/vm/attachListener_solaris.cpp	Wed Mar 23 23:36:29 2016 +0100
@@ -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	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/os/solaris/vm/os_solaris.cpp	Wed Mar 23 23:36:29 2016 +0100
@@ -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	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/os/solaris/vm/perfMemory_solaris.cpp	Wed Mar 23 23:36:29 2016 +0100
@@ -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	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/os/solaris/vm/threadCritical_solaris.cpp	Wed Mar 23 23:36:29 2016 +0100
@@ -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	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/os/windows/vm/os_windows.cpp	Wed Mar 23 23:36:29 2016 +0100
@@ -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	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/os/windows/vm/perfMemory_windows.cpp	Wed Mar 23 23:36:29 2016 +0100
@@ -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/share/vm/c1/c1_Compilation.cpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/c1/c1_Compilation.cpp	Wed Mar 23 23:36:29 2016 +0100
@@ -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
@@ -36,6 +36,7 @@
 #include "compiler/compileLog.hpp"
 #include "compiler/compilerDirectives.hpp"
 #include "runtime/sharedRuntime.hpp"
+#include "runtime/timerTrace.hpp"
 
 typedef enum {
   _t_compile,
--- a/hotspot/src/share/vm/c1/c1_LinearScan.cpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/c1/c1_LinearScan.cpp	Wed Mar 23 23:36:29 2016 +0100
@@ -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/ci/ciReplay.cpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/ci/ciReplay.cpp	Wed Mar 23 23:36:29 2016 +0100
@@ -1,4 +1,5 @@
-/* Copyright (c) 2013, 2015, 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/classfile/classFileParser.cpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/classfile/classFileParser.cpp	Wed Mar 23 23:36:29 2016 +0100
@@ -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 = LogHandle(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/javaClasses.cpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/classfile/javaClasses.cpp	Wed Mar 23 23:36:29 2016 +0100
@@ -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	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/classfile/javaClasses.hpp	Wed Mar 23 23:36:29 2016 +0100
@@ -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/stringTable.cpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/classfile/stringTable.cpp	Wed Mar 23 23:36:29 2016 +0100
@@ -94,15 +94,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 +410,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 +510,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	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/classfile/stringTable.hpp	Wed Mar 23 23:36:29 2016 +0100
@@ -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/systemDictionary.cpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/classfile/systemDictionary.cpp	Wed Mar 23 23:36:29 2016 +0100
@@ -67,6 +67,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
@@ -1650,6 +1651,8 @@
 
   }
 
+  TRACE_KLASS_DEFINITION(k, THREAD);
+
 }
 
 // Support parallel classloading
--- a/hotspot/src/share/vm/classfile/verificationType.cpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/classfile/verificationType.cpp	Wed Mar 23 23:36:29 2016 +0100
@@ -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	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/classfile/verifier.cpp	Wed Mar 23 23:36:29 2016 +0100
@@ -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(verboseverification)("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);
@@ -194,8 +193,8 @@
   if (log_is_enabled(Info, classinit)){
     log_end_verification(LogHandle(classinit)::info_stream(), klassName, exception_name, THREAD);
   }
-  if (VerboseVerification){
-    log_end_verification(tty, klassName, exception_name, THREAD);
+  if (log_is_enabled(Info, verboseverification)){
+    log_end_verification(LogHandle(verboseverification)::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(verboseverification)("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(verboseverification)("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(verboseverification)("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(verboseverification)("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, &current_frame, max_locals, max_stack,
                                code_data, code_length, CHECK_VERIFY(this));
 
-  if (VerboseVerification) {
-    stackmap_table.print_on(tty);
+  if (log_is_enabled(Info, verboseverification)) {
+    ResourceMark rm(THREAD);
+    stackmap_table.print_on(LogHandle(verboseverification)::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, verboseverification)) {
+        ResourceMark rm(THREAD);
+        current_frame.print_on(LogHandle(verboseverification)::info_stream());
+        log_info(verboseverification)("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, verboseverification)) {
+            ResourceMark rm(THREAD);
+            log_info(verboseverification)("Survived call to ends_in_athrow(): %s",
+                                          current_class()->name()->as_C_string());
           }
         }
       }
--- a/hotspot/src/share/vm/classfile/vmSymbols.hpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/classfile/vmSymbols.hpp	Wed Mar 23 23:36:29 2016 +0100
@@ -385,6 +385,7 @@
   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")                                  \
--- a/hotspot/src/share/vm/compiler/compileBroker.cpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/compiler/compileBroker.cpp	Wed Mar 23 23:36:29 2016 +0100
@@ -32,6 +32,7 @@
 #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 "oops/methodData.hpp"
@@ -48,6 +49,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"
@@ -900,7 +902,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/methodLiveness.cpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/compiler/methodLiveness.cpp	Wed Mar 23 23:36:29 2016 +0100
@@ -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,7 @@
 #include "interpreter/bytecode.hpp"
 #include "interpreter/bytecodes.hpp"
 #include "memory/allocation.inline.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/gc/cms/compactibleFreeListSpace.cpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/gc/cms/compactibleFreeListSpace.cpp	Wed Mar 23 23:36:29 2016 +0100
@@ -1931,11 +1931,6 @@
   if (blk->_ptr == NULL) {
     refillLinearAllocBlock(blk);
   }
-  if (PrintMiscellaneous && Verbose) {
-    if (blk->_word_size == 0) {
-      warning("CompactibleFreeListSpace(prologue):: Linear allocation failure");
-    }
-  }
 }
 
 void
--- a/hotspot/src/share/vm/gc/cms/concurrentMarkSweepGeneration.cpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/gc/cms/concurrentMarkSweepGeneration.cpp	Wed Mar 23 23:36:29 2016 +0100
@@ -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);
@@ -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.
@@ -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;
 }
 
@@ -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(),
@@ -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();
+    LogHandle(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	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/gc/cms/concurrentMarkSweepThread.cpp	Wed Mar 23 23:36:29 2016 +0100
@@ -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	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/gc/cms/concurrentMarkSweepThread.hpp	Wed Mar 23 23:36:29 2016 +0100
@@ -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	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/gc/cms/parCardTableModRefBS.cpp	Wed Mar 23 23:36:29 2016 +0100
@@ -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	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/gc/cms/parNewGeneration.cpp	Wed Mar 23 23:36:29 2016 +0100
@@ -901,7 +901,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	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/gc/cms/parOopClosures.inline.hpp	Wed Mar 23 23:36:29 2016 +0100
@@ -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));
+        LogHandle(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	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/gc/cms/vmCMSOperations.cpp	Wed Mar 23 23:36:29 2016 +0100
@@ -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	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/gc/cms/vmCMSOperations.hpp	Wed Mar 23 23:36:29 2016 +0100
@@ -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	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/gc/cms/vmStructs_cms.hpp	Wed Mar 23 23:36:29 2016 +0100
@@ -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	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/gc/g1/collectionSetChooser.cpp	Wed Mar 23 23:36:29 2016 +0100
@@ -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	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/gc/g1/collectionSetChooser.hpp	Wed Mar 23 23:36:29 2016 +0100
@@ -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	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/gc/g1/concurrentG1Refine.cpp	Wed Mar 23 23:36:29 2016 +0100
@@ -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	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/gc/g1/concurrentG1Refine.hpp	Wed Mar 23 23:36:29 2016 +0100
@@ -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	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/gc/g1/concurrentG1RefineThread.cpp	Wed Mar 23 23:36:29 2016 +0100
@@ -78,7 +78,7 @@
 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 +109,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;
     }
 
@@ -168,23 +159,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	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/gc/g1/concurrentG1RefineThread.hpp	Wed Mar 23 23:36:29 2016 +0100
@@ -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	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/gc/g1/concurrentMarkThread.cpp	Wed Mar 23 23:36:29 2016 +0100
@@ -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	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/gc/g1/concurrentMarkThread.hpp	Wed Mar 23 23:36:29 2016 +0100
@@ -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	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/gc/g1/dirtyCardQueue.cpp	Wed Mar 23 23:36:29 2016 +0100
@@ -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,14 +150,39 @@
   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;
+  void** buf = BufferNode::make_buffer_from_node(node);
+  size_t limit = DirtyCardQueue::byte_index_to_index(buffer_size());
+  size_t start = DirtyCardQueue::byte_index_to_index(node->index());
+  for (size_t i = start; 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)) {
+      if (consume) {
+        size_t new_index = DirtyCardQueue::index_to_byte_index(i + 1);
+        assert(new_index <= buffer_size(), "invariant");
+        node->set_index(new_index);
+      }
+      return false;
+    }
+  }
+  if (consume) {
+    node->set_index(buffer_size());
+  }
+  return true;
+}
+
+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();
 
-  bool b = DirtyCardQueue::apply_closure_to_buffer(_mut_process_closure, buf, 0,
-                                                   _sz, true, worker_i);
+  bool b = apply_closure_to_buffer(_mut_process_closure, node, true, worker_i);
   if (b) {
     Atomic::inc(&_processed_buffers_mut);
   }
@@ -239,49 +226,30 @@
   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)) {
       // 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);
+      enqueue_complete_buffer(nd);
       return false;
     }
   }
 }
 
-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();
-  }
-}
-
 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 +272,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 +288,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 +304,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	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/gc/g1/dirtyCardQueue.hpp	Wed Mar 23 23:36:29 2016 +0100
@@ -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,18 @@
 
   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
+  // follow the last processed element.
+  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 +100,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);
 
@@ -126,12 +122,13 @@
   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.
+  // specified closure to its active elements.  If all active 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 index updated to exclude the processed
+  // elements) is returned to the completed buffer set, and this call
+  // returns false.
   bool apply_closure_to_completed_buffer(CardTableEntryClosure* cl,
                                          uint worker_i,
                                          size_t stop_at,
@@ -139,13 +136,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	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/gc/g1/g1AllocRegion.cpp	Wed Mar 23 23:36:29 2016 +0100
@@ -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.
+
+  LogHandle(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	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/gc/g1/g1AllocRegion.hpp	Wed Mar 23 23:36:29 2016 +0100
@@ -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	Wed Mar 23 23:36:29 2016 +0100
@@ -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	Wed Mar 23 23:36:29 2016 +0100
@@ -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	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp	Wed Mar 23 23:36:29 2016 +0100
@@ -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"
@@ -566,7 +568,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 +677,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 +1093,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 +1230,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 +1305,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 +1424,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 +1449,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 +1745,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 +1770,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 +1784,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 +2319,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 +2504,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 +2536,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 +2565,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 +2675,14 @@
   return false; // keep some compilers happy
 }
 
+void G1CollectedHeap::print_heap_regions() const {
+  LogHandle(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 +2696,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 +2713,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 +2809,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 +2834,6 @@
   gc_tracer->report_metaspace_summary(when, metaspace_summary);
 }
 
-
 G1CollectedHeap* G1CollectedHeap::heap() {
   CollectedHeap* heap = Universe::heap();
   assert(heap != NULL, "Uninitialized access to G1CollectedHeap::heap()");
@@ -3201,15 +3172,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 +3206,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());
@@ -3336,10 +3311,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 +3332,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 +3347,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 +3356,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 +3378,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 +3412,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 +3438,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 +3508,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 +3747,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 +4055,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 +4247,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 +4368,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 +4513,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 +4551,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 +4881,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 +5354,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 +5365,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 +5412,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	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.hpp	Wed Mar 23 23:36:29 2016 +0100
@@ -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	Wed Mar 23 23:36:29 2016 +0100
@@ -0,0 +1,440 @@
+/*
+ * 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),
+  _bytes_live_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_bytes_live_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();
+  _bytes_live_before += hr->live_bytes();
+  size_t rs_length = hr->rem_set()->occupied();
+  _recorded_rs_lengths += rs_length;
+  _old_region_length += 1;
+}
+
+// Initialize the per-collection-set information
+void G1CollectionSet::start_incremental_building() {
+  assert(_inc_build_state == Inactive, "Precondition");
+
+  _inc_head = NULL;
+  _inc_tail = NULL;
+  _inc_bytes_used_before = 0;
+  _inc_bytes_live_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;
+  _inc_build_state = Active;
+}
+
+void G1CollectionSet::finalize_incremental_building() {
+  assert(_inc_build_state == Active, "Precondition");
+  assert(SafepointSynchronize::is_at_safepoint(), "should be at a safepoint");
+
+  // The two "main" fields, _inc_recorded_rs_lengths and
+  // _inc_predicted_elapsed_time_ms, are updated by the thread
+  // that adds a new region to the CSet. Further updates by the
+  // concurrent refinement thread that samples the young RSet lengths
+  // are accumulated in the *_diffs fields. Here we add the diffs to
+  // the "main" fields.
+
+  if (_inc_recorded_rs_lengths_diffs >= 0) {
+    _inc_recorded_rs_lengths += _inc_recorded_rs_lengths_diffs;
+  } else {
+    // This is defensive. The diff should in theory be always positive
+    // as RSets can only grow between GCs. However, given that we
+    // sample their size concurrently with other threads updating them
+    // it's possible that we might get the wrong size back, which
+    // could make the calculations somewhat inaccurate.
+    size_t diffs = (size_t) (-_inc_recorded_rs_lengths_diffs);
+    if (_inc_recorded_rs_lengths >= diffs) {
+      _inc_recorded_rs_lengths -= diffs;
+    } else {
+      _inc_recorded_rs_lengths = 0;
+    }
+  }
+  _inc_predicted_elapsed_time_ms += _inc_predicted_elapsed_time_ms_diffs;
+
+  _inc_recorded_rs_lengths_diffs = 0;
+  _inc_predicted_elapsed_time_ms_diffs = 0.0;
+}
+
+void G1CollectionSet::update_young_region_prediction(HeapRegion* hr,
+                                                     size_t new_rs_length) {
+  // Update the CSet information that is dependent on the new RS length
+  assert(hr->is_young(), "Precondition");
+  assert(!SafepointSynchronize::is_at_safepoint(), "should not be at a safepoint");
+
+  // We could have updated _inc_recorded_rs_lengths and
+  // _inc_predicted_elapsed_time_ms directly but we'd need to do
+  // that atomically, as this code is executed by a concurrent
+  // refinement thread, potentially concurrently with a mutator thread
+  // allocating a new region and also updating the same fields. To
+  // avoid the atomic operations we accumulate these updates on two
+  // separate fields (*_diffs) and we'll just add them to the "main"
+  // fields at the start of a GC.
+
+  ssize_t old_rs_length = (ssize_t) hr->recorded_rs_length();
+  ssize_t rs_lengths_diff = (ssize_t) new_rs_length - old_rs_length;
+  _inc_recorded_rs_lengths_diffs += rs_lengths_diff;
+
+  double old_elapsed_time_ms = hr->predicted_elapsed_time_ms();
+  double new_region_elapsed_time_ms = predict_region_elapsed_time_ms(hr);
+  double elapsed_ms_diff = new_region_elapsed_time_ms - old_elapsed_time_ms;
+  _inc_predicted_elapsed_time_ms_diffs += elapsed_ms_diff;
+
+  hr->set_recorded_rs_length(new_rs_length);
+  hr->set_predicted_elapsed_time_ms(new_region_elapsed_time_ms);
+}
+
+void G1CollectionSet::add_young_region_common(HeapRegion* hr) {
+  assert(hr->is_young(), "invariant");
+  assert(hr->young_index_in_cset() > -1, "should have already been set");
+  assert(_inc_build_state == Active, "Precondition");
+
+  // This routine is used when:
+  // * adding survivor regions to the incremental cset at the end of an
+  //   evacuation pause or
+  // * adding the current allocation region to the incremental cset
+  //   when it is retired.
+  // Therefore this routine may be called at a safepoint by the
+  // VM thread, or in-between safepoints by mutator threads (when
+  // retiring the current allocation region)
+  // We need to clear and set the cached recorded/cached collection set
+  // information in the heap region here (before the region gets added
+  // to the collection set). An individual heap region's cached values
+  // are calculated, aggregated with the policy collection set info,
+  // and cached in the heap region here (initially) and (subsequently)
+  // by the Young List sampling code.
+
+  size_t rs_length = hr->rem_set()->occupied();
+  double region_elapsed_time_ms = predict_region_elapsed_time_ms(hr);
+
+  // Cache the values we have added to the aggregated information
+  // in the heap region in case we have to remove this region from
+  // the incremental collection set, or it is updated by the
+  // rset sampling code
+  hr->set_recorded_rs_length(rs_length);
+  hr->set_predicted_elapsed_time_ms(region_elapsed_time_ms);
+
+  size_t used_bytes = hr->used();
+  _inc_recorded_rs_lengths += rs_length;
+  _inc_predicted_elapsed_time_ms += region_elapsed_time_ms;
+  _inc_bytes_used_before += used_bytes;
+  _inc_bytes_live_before += hr->live_bytes();
+
+  assert(!hr->in_collection_set(), "invariant");
+  _g1->register_young_region_with_cset(hr);
+  assert(hr->next_in_collection_set() == NULL, "invariant");
+}
+
+// Add the region at the RHS of the incremental cset
+void G1CollectionSet::add_survivor_regions(HeapRegion* hr) {
+  // We should only ever be appending survivors at the end of a pause
+  assert(hr->is_survivor(), "Logic");
+
+  // Do the 'common' stuff
+  add_young_region_common(hr);
+
+  // Now add the region at the right hand side
+  if (_inc_tail == NULL) {
+    assert(_inc_head == NULL, "invariant");
+    _inc_head = hr;
+  } else {
+    _inc_tail->set_next_in_collection_set(hr);
+  }
+  _inc_tail = hr;
+}
+
+// Add the region to the LHS of the incremental cset
+void G1CollectionSet::add_eden_region(HeapRegion* hr) {
+  // Survivors should be added to the RHS at the end of a pause
+  assert(hr->is_eden(), "Logic");
+
+  // Do the 'common' stuff
+  add_young_region_common(hr);
+
+  // Add the region at the left hand side
+  hr->set_next_in_collection_set(_inc_head);
+  if (_inc_head == NULL) {
+    assert(_inc_tail == NULL, "Invariant");
+    _inc_tail = hr;
+  }
+  _inc_head = hr;
+}
+
+#ifndef PRODUCT
+void G1CollectionSet::print(HeapRegion* list_head, outputStream* st) {
+  assert(list_head == inc_head() || list_head == head(), "must be");
+
+  st->print_cr("\nCollection_set:");
+  HeapRegion* csr = list_head;
+  while (csr != NULL) {
+    HeapRegion* next = csr->next_in_collection_set();
+    assert(csr->in_collection_set(), "bad CS");
+    st->print_cr("  " HR_FORMAT ", P: " PTR_FORMAT "N: " PTR_FORMAT ", age: %4d",
+                 HR_FORMAT_PARAMS(csr),
+                 p2i(csr->prev_top_at_mark_start()), p2i(csr->next_top_at_mark_start()),
+                 csr->age_in_surv_rate_group_cond());
+    csr = next;
+  }
+}
+#endif // !PRODUCT
+
+double G1CollectionSet::finalize_young_part(double target_pause_time_ms) {
+  double young_start_time_sec = os::elapsedTime();
+
+  YoungList* young_list = _g1->young_list();
+  finalize_incremental_building();
+
+  guarantee(target_pause_time_ms > 0.0,
+            "target_pause_time_ms = %1.6lf should be positive", target_pause_time_ms);
+  guarantee(_head == NULL, "Precondition");
+
+  size_t pending_cards = _policy->pending_cards();
+  double base_time_ms = _policy->predict_base_elapsed_time_ms(pending_cards);
+  double time_remaining_ms = MAX2(target_pause_time_ms - base_time_ms, 0.0);
+
+  log_trace(gc, ergo, cset)("Start choosing CSet. pending cards: " SIZE_FORMAT " predicted base time: %1.2fms remaining time: %1.2fms target pause time: %1.2fms",
+                            pending_cards, base_time_ms, time_remaining_ms, target_pause_time_ms);
+
+  collector_state()->set_last_gc_was_young(collector_state()->gcs_are_young());
+
+  // The young list is laid with the survivor regions from the previous
+  // pause are appended to the RHS of the young list, i.e.
+  //   [Newly Young Regions ++ Survivors from last pause].
+
+  uint survivor_region_length = young_list->survivor_length();
+  uint eden_region_length = young_list->eden_length();
+  init_region_lengths(eden_region_length, survivor_region_length);
+
+  HeapRegion* hr = young_list->first_survivor_region();
+  while (hr != NULL) {
+    assert(hr->is_survivor(), "badly formed young list");
+    // There is a convention that all the young regions in the CSet
+    // are tagged as "eden", so we do this for the survivors here. We
+    // use the special set_eden_pre_gc() as it doesn't check that the
+    // region is free (which is not the case here).
+    hr->set_eden_pre_gc();
+    hr = hr->get_next_young_region();
+  }
+
+  // Clear the fields that point to the survivor list - they are all young now.
+  young_list->clear_survivors();
+
+  _head = _inc_head;
+  _bytes_used_before = _inc_bytes_used_before;
+  _bytes_live_before = _inc_bytes_live_before;
+  time_remaining_ms = MAX2(time_remaining_ms - _inc_predicted_elapsed_time_ms, 0.0);
+
+  log_trace(gc, ergo, cset)("Add young regions to CSet. eden: %u regions, survivors: %u regions, predicted young region time: %1.2fms, target pause time: %1.2fms",
+                            eden_region_length, survivor_region_length, _inc_predicted_elapsed_time_ms, target_pause_time_ms);
+
+  // The number of recorded young regions is the incremental
+  // collection set's current size
+  set_recorded_rs_lengths(_inc_recorded_rs_lengths);
+
+  double young_end_time_sec = os::elapsedTime();
+  phase_times()->record_young_cset_choice_time_ms((young_end_time_sec - young_start_time_sec) * 1000.0);
+
+  return time_remaining_ms;
+}
+
+void G1CollectionSet::finalize_old_part(double time_remaining_ms) {
+  double non_young_start_time_sec = os::elapsedTime();
+  double predicted_old_time_ms = 0.0;
+
+  if (!collector_state()->gcs_are_young()) {
+    cset_chooser()->verify();
+    const uint min_old_cset_length = _policy->calc_min_old_cset_length();
+    const uint max_old_cset_length = _policy->calc_max_old_cset_length();
+    const size_t estimated_available_bytes = _policy->available_bytes_estimate();
+
+    uint expensive_region_num = 0;
+    bool check_time_remaining = _policy->adaptive_young_list_length();
+
+    HeapRegion* hr = cset_chooser()->peek();
+    while (hr != NULL) {
+      if (old_region_length() >= max_old_cset_length) {
+        // Added maximum number of old regions to the CSet.
+        log_debug(gc, ergo, cset)("Finish adding old regions to CSet (old CSet region num reached max). old %u regions, max %u regions",
+                                  old_region_length(), max_old_cset_length);
+        break;
+      }
+
+      // Stop adding regions if the remaining reclaimable space is
+      // not above G1HeapWastePercent.
+      size_t reclaimable_bytes = cset_chooser()->remaining_reclaimable_bytes();
+      double reclaimable_perc = _policy->reclaimable_bytes_perc(reclaimable_bytes);
+      double threshold = (double) G1HeapWastePercent;
+      if (reclaimable_perc <= threshold) {
+        // We've added enough old regions that the amount of uncollected
+        // reclaimable space is at or below the waste threshold. Stop
+        // adding old regions to the CSet.
+        log_debug(gc, ergo, cset)("Finish adding old regions to CSet (reclaimable percentage not over threshold). "
+                                  "old %u regions, max %u regions, reclaimable: " SIZE_FORMAT "B (%1.2f%%) threshold: " UINTX_FORMAT "%%",
+                                  old_region_length(), max_old_cset_length, reclaimable_bytes, reclaimable_perc, G1HeapWastePercent);
+        break;
+      }
+
+      // Stop adding regions if the live bytes (according to the last marking)
+      // added so far would exceed the estimated free bytes.
+      if ((_bytes_live_before + hr->live_bytes()) > estimated_available_bytes) {
+        log_debug(gc, ergo, cset)("Finish adding old regions to CSet (reached estimated free space limit)");
+        break;
+      }
+
+      double predicted_time_ms = predict_region_elapsed_time_ms(hr);
+      if (check_time_remaining) {
+        if (predicted_time_ms > time_remaining_ms) {
+          // Too expensive for the current CSet.
+
+          if (old_region_length() >= min_old_cset_length) {
+            // We have added the minimum number of old regions to the CSet,
+            // we are done with this CSet.
+            log_debug(gc, ergo, cset)("Finish adding old regions to CSet (predicted time is too high). "
+                                      "predicted time: %1.2fms, remaining time: %1.2fms old %u regions, min %u regions",
+                                      predicted_time_ms, time_remaining_ms, old_region_length(), min_old_cset_length);
+            break;
+          }
+
+          // We'll add it anyway given that we haven't reached the
+          // minimum number of old regions.
+          expensive_region_num += 1;
+        }
+      } else {
+        if (old_region_length() >= min_old_cset_length) {
+          // In the non-auto-tuning case, we'll finish adding regions
+          // to the CSet if we reach the minimum.
+
+          log_debug(gc, ergo, cset)("Finish adding old regions to CSet (old CSet region num reached min). old %u regions, min %u regions",
+                                    old_region_length(), min_old_cset_length);
+          break;
+        }
+      }
+
+      // We will add this region to the CSet.
+      time_remaining_ms = MAX2(time_remaining_ms - predicted_time_ms, 0.0);
+      predicted_old_time_ms += predicted_time_ms;
+      cset_chooser()->pop(); // already have region via peek()
+      _g1->old_set_remove(hr);
+      add_old_region(hr);
+
+      hr = cset_chooser()->peek();
+    }
+    if (hr == NULL) {
+      log_debug(gc, ergo, cset)("Finish adding old regions to CSet (candidate old regions not available)");
+    }
+
+    if (expensive_region_num > 0) {
+      // We print the information once here at the end, predicated on
+      // whether we added any apparently expensive regions or not, to
+      // avoid generating output per region.
+      log_debug(gc, ergo, cset)("Added expensive regions to CSet (old CSet region num not reached min)."
+                                "old: %u regions, expensive: %u regions, min: %u regions, remaining time: %1.2fms",
+                                old_region_length(), expensive_region_num, min_old_cset_length, time_remaining_ms);
+    }
+
+    cset_chooser()->verify();
+  }
+
+  stop_incremental_building();
+
+  log_debug(gc, ergo, cset)("Finish choosing CSet. old: %u regions, predicted old region time: %1.2fms, time remaining: %1.2f",
+                            old_region_length(), predicted_old_time_ms, time_remaining_ms);
+
+  double non_young_end_time_sec = os::elapsedTime();
+  phase_times()->record_non_young_cset_choice_time_ms((non_young_end_time_sec - non_young_start_time_sec) * 1000.0);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/gc/g1/g1CollectionSet.hpp	Wed Mar 23 23:36:29 2016 +0100
@@ -0,0 +1,217 @@
+/*
+ * 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_G1COLLECTIONSET_HPP
+#define SHARE_VM_GC_G1_G1COLLECTIONSET_HPP
+
+#include "gc/g1/collectionSetChooser.hpp"
+#include "memory/allocation.hpp"
+#include "utilities/debug.hpp"
+#include "utilities/globalDefinitions.hpp"
+
+class G1CollectedHeap;
+class G1CollectorPolicy;
+class G1CollectorState;
+class G1GCPhaseTimes;
+class HeapRegion;
+
+class G1CollectionSet VALUE_OBJ_CLASS_SPEC {
+  G1CollectedHeap* _g1;
+  G1CollectorPolicy* _policy;
+
+  CollectionSetChooser* _cset_chooser;
+
+  uint _eden_region_length;
+  uint _survivor_region_length;
+  uint _old_region_length;
+
+  // The head of the list (via "next_in_collection_set()") representing the
+  // current collection set. Set from the incrementally built collection
+  // set at the start of the pause.
+  HeapRegion* _head;
+
+  // The number of bytes in the collection set before the pause. Set from
+  // the incrementally built collection set at the start of an evacuation
+  // pause, and incremented in finalize_old_part() when adding old regions
+  // (if any) to the collection set.
+  size_t _bytes_used_before;
+
+  // The sum of live bytes in the collection set, set as described above.
+  size_t _bytes_live_before;
+
+  size_t _recorded_rs_lengths;
+
+  // The associated information that is maintained while the incremental
+  // collection set is being built with young regions. Used to populate
+  // the recorded info for the evacuation pause.
+
+  enum CSetBuildType {
+    Active,             // We are actively building the collection set
+    Inactive            // We are not actively building the collection set
+  };
+
+  CSetBuildType _inc_build_state;
+
+  // The head of the incrementally built collection set.
+  HeapRegion* _inc_head;
+
+  // The tail of the incrementally built collection set.
+  HeapRegion* _inc_tail;
+
+  // The number of bytes in the incrementally built collection set.
+  // Used to set _collection_set_bytes_used_before at the start of
+  // an evacuation pause.
+  size_t _inc_bytes_used_before;
+
+  // The number of live bytes in the incrementally built collection set.
+  size_t _inc_bytes_live_before;
+
+  // The RSet lengths recorded for regions in the CSet. It is updated
+  // by the thread that adds a new region to the CSet. We assume that
+  // only one thread can be allocating a new CSet region (currently,
+  // it does so after taking the Heap_lock) hence no need to
+  // synchronize updates to this field.
+  size_t _inc_recorded_rs_lengths;
+
+  // A concurrent refinement thread periodically samples the young
+  // region RSets and needs to update _inc_recorded_rs_lengths as
+  // the RSets grow. Instead of having to synchronize updates to that
+  // field we accumulate them in this field and add it to
+  // _inc_recorded_rs_lengths_diffs at the start of a GC.
+  ssize_t _inc_recorded_rs_lengths_diffs;
+
+  // The predicted elapsed time it will take to collect the regions in
+  // the CSet. This is updated by the thread that adds a new region to
+  // the CSet. See the comment for _inc_recorded_rs_lengths about
+  // MT-safety assumptions.
+  double _inc_predicted_elapsed_time_ms;
+
+  // See the comment for _inc_recorded_rs_lengths_diffs.
+  double _inc_predicted_elapsed_time_ms_diffs;
+
+  G1CollectorState* collector_state();
+  G1GCPhaseTimes* phase_times();
+
+  double predict_region_elapsed_time_ms(HeapRegion* hr);
+
+public:
+  G1CollectionSet(G1CollectedHeap* g1h);
+  ~G1CollectionSet();
+
+  void set_policy(G1CollectorPolicy* g1p) {
+    assert(_policy == NULL, "should only initialize once");
+    _policy = g1p;
+  }
+
+  CollectionSetChooser* cset_chooser();
+
+  void init_region_lengths(uint eden_cset_region_length,
+                           uint survivor_cset_region_length);
+
+  void set_recorded_rs_lengths(size_t rs_lengths);
+
+  uint region_length() const       { return young_region_length() +
+                                            old_region_length(); }
+  uint young_region_length() const { return eden_region_length() +
+                                            survivor_region_length(); }
+
+  uint eden_region_length() const     { return _eden_region_length;     }
+  uint survivor_region_length() const { return _survivor_region_length; }
+  uint old_region_length() const      { return _old_region_length;      }
+
+  // Incremental CSet Support
+
+  // The head of the incrementally built collection set.
+  HeapRegion* inc_head() { return _inc_head; }
+
+  // The tail of the incrementally built collection set.
+  HeapRegion* inc_tail() { return _inc_tail; }
+
+  // Initialize incremental collection set info.
+  void start_incremental_building();
+
+  // Perform any final calculations on the incremental CSet fields
+  // before we can use them.
+  void finalize_incremental_building();
+
+  void clear_incremental() {
+    _inc_head = NULL;
+    _inc_tail = NULL;
+  }
+
+  // Stop adding regions to the incremental collection set
+  void stop_incremental_building() { _inc_build_state = Inactive; }
+
+  // The head of the list (via "next_in_collection_set()") representing the
+  // current collection set.
+  HeapRegion* head() { return _head; }
+
+  void clear_head() { _head = NULL; }
+
+  size_t recorded_rs_lengths() { return _recorded_rs_lengths; }
+
+  size_t bytes_used_before() const {
+    return _bytes_used_before;
+  }
+
+  void reset_bytes_used_before() {
+    _bytes_used_before = 0;
+  }
+
+  void reset_bytes_live_before() {
+    _bytes_live_before = 0;
+  }
+
+  // Choose a new collection set.  Marks the chosen regions as being
+  // "in_collection_set", and links them together.  The head and number of
+  // the collection set are available via access methods.
+  double finalize_young_part(double target_pause_time_ms);
+  void finalize_old_part(double time_remaining_ms);
+
+  // Add old region "hr" to the CSet.
+  void add_old_region(HeapRegion* hr);
+
+  // Update information about hr in the aggregated information for
+  // the incrementally built collection set.
+  void update_young_region_prediction(HeapRegion* hr, size_t new_rs_length);
+
+  // Add hr to the LHS of the incremental collection set.
+  void add_eden_region(HeapRegion* hr);
+
+  // Add hr to the RHS of the incremental collection set.
+  void add_survivor_regions(HeapRegion* hr);
+
+#ifndef PRODUCT
+  void print(HeapRegion* list_head, outputStream* st);
+#endif // !PRODUCT
+
+private:
+  // Update the incremental cset information when adding a region
+  // (should not be called directly).
+  void add_young_region_common(HeapRegion* hr);
+
+};
+
+#endif // SHARE_VM_GC_G1_G1COLLECTIONSET_HPP
+
--- a/hotspot/src/share/vm/gc/g1/g1CollectorPolicy.cpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/gc/g1/g1CollectorPolicy.cpp	Wed Mar 23 23:36:29 2016 +0100
@@ -25,11 +25,14 @@
 #include "precompiled.hpp"
 #include "gc/g1/concurrentG1Refine.hpp"
 #include "gc/g1/concurrentMarkThread.inline.hpp"
+#include "gc/g1/g1Analytics.hpp"
 #include "gc/g1/g1CollectedHeap.inline.hpp"
+#include "gc/g1/g1CollectionSet.hpp"
 #include "gc/g1/g1CollectorPolicy.hpp"
 #include "gc/g1/g1ConcurrentMark.hpp"
 #include "gc/g1/g1IHOPControl.hpp"
 #include "gc/g1/g1GCPhaseTimes.hpp"
+#include "gc/g1/g1YoungGenSizer.hpp"
 #include "gc/g1/heapRegion.inline.hpp"
 #include "gc/g1/heapRegionRemSet.hpp"
 #include "gc/shared/gcPolicyCounters.hpp"
@@ -39,107 +42,14 @@
 #include "utilities/debug.hpp"
 #include "utilities/pair.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
-};
-
 G1CollectorPolicy::G1CollectorPolicy() :
   _predictor(G1ConfidencePercent / 100.0),
-
-  _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)),
-
+  _analytics(new G1Analytics(&_predictor)),
   _pause_time_target_ms((double) MaxGCPauseMillis),
-
-  _recent_prev_end_times_for_all_gcs_sec(
-                                new TruncatedSeq(NumPrevPausesForHeuristics)),
-
-  _recent_avg_pause_time_ratio(0.0),
   _rs_lengths_prediction(0),
   _max_survivor_regions(0),
-
-  _eden_cset_region_length(0),
-  _survivor_cset_region_length(0),
-  _old_cset_region_length(0),
-
-  _collection_set(NULL),
-  _collection_set_bytes_used_before(0),
-
-  // Incremental CSet attributes
-  _inc_cset_build_state(Inactive),
-  _inc_cset_head(NULL),
-  _inc_cset_tail(NULL),
-  _inc_cset_bytes_used_before(0),
-  _inc_cset_recorded_rs_lengths(0),
-  _inc_cset_recorded_rs_lengths_diffs(0),
-  _inc_cset_predicted_elapsed_time_ms(0.0),
-  _inc_cset_predicted_elapsed_time_ms_diffs(0.0),
-
-  // add here any more surv rate groups
-  _recorded_survivor_regions(0),
-  _recorded_survivor_head(NULL),
-  _recorded_survivor_tail(NULL),
   _survivors_age_table(true),
 
-  _gc_overhead_perc(0.0),
-
   _bytes_allocated_in_old_since_last_gc(0),
   _ihop_control(NULL),
   _initial_mark_to_mixed() {
@@ -165,27 +75,8 @@
   HeapRegion::setup_heap_region_size(InitialHeapSize, MaxHeapSize);
   HeapRegionRemSet::setup_remset_size();
 
-  _recent_prev_end_times_for_all_gcs_sec->add(os::elapsedTime());
-  _prev_collection_pause_end_ms = os::elapsedTime() * 1000.0;
-  clear_ratio_check_data();
-
   _phase_times = new G1GCPhaseTimes(ParallelGCThreads);
 
-  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]);
-
   // Below, we might need to calculate the pause time target based on
   // the pause interval. When we do so we are going to give G1 maximum
   // flexibility and allow it to do pauses when it needs to. So, we'll
@@ -198,18 +89,7 @@
 
   // First make sure that, if either parameter is set, its value is
   // reasonable.
-  if (!FLAG_IS_DEFAULT(MaxGCPauseMillis)) {
-    if (MaxGCPauseMillis < 1) {
-      vm_exit_during_initialization("MaxGCPauseMillis should be "
-                                    "greater than 0");
-    }
-  }
-  if (!FLAG_IS_DEFAULT(GCPauseIntervalMillis)) {
-    if (GCPauseIntervalMillis < 1) {
-      vm_exit_during_initialization("GCPauseIntervalMillis should be "
-                                    "greater than 0");
-    }
-  }
+  guarantee(MaxGCPauseMillis >= 1, "Range checking for MaxGCPauseMillis should guarantee that value is >= 1");
 
   // Then, if the pause time target parameter was not set, set it to
   // the default value.
@@ -231,45 +111,22 @@
   if (FLAG_IS_DEFAULT(GCPauseIntervalMillis)) {
     FLAG_SET_DEFAULT(GCPauseIntervalMillis, MaxGCPauseMillis + 1);
   }
-
-  // Finally, make sure that the two parameters are consistent.
-  if (MaxGCPauseMillis >= GCPauseIntervalMillis) {
-    char buffer[256];
-    jio_snprintf(buffer, 256,
-                 "MaxGCPauseMillis (%u) should be less than "
-                 "GCPauseIntervalMillis (%u)",
-                 MaxGCPauseMillis, GCPauseIntervalMillis);
-    vm_exit_during_initialization(buffer);
-  }
+  guarantee(GCPauseIntervalMillis >= 1, "Constraint for GCPauseIntervalMillis should guarantee that value is >= 1");
+  guarantee(GCPauseIntervalMillis > MaxGCPauseMillis, "Constraint for GCPauseIntervalMillis should guarantee that GCPauseIntervalMillis > MaxGCPauseMillis");
 
   double max_gc_time = (double) MaxGCPauseMillis / 1000.0;
   double time_slice  = (double) GCPauseIntervalMillis / 1000.0;
   _mmu_tracker = new G1MMUTrackerQueue(time_slice, max_gc_time);
 
-  // start conservatively (around 50ms is about right)
-  _concurrent_mark_remark_times_ms->add(0.05);
-  _concurrent_mark_cleanup_times_ms->add(0.20);
   _tenuring_threshold = MaxTenuringThreshold;
 
-  assert(GCTimeRatio > 0,
-         "we should have set it to a default value set_g1_gc_flags() "
-         "if a user set it to 0");
-  _gc_overhead_perc = 100.0 * (1.0 / (1.0 + GCTimeRatio));
 
-  uintx reserve_perc = G1ReservePercent;
-  // Put an artificial ceiling on this so that it's not set to a silly value.
-  if (reserve_perc > 50) {
-    reserve_perc = 50;
-    warning("G1ReservePercent is set to a value that is too large, "
-            "it's been updated to " UINTX_FORMAT, reserve_perc);
-  }
-  _reserve_factor = (double) reserve_perc / 100.0;
+  guarantee(G1ReservePercent <= 50, "Range checking should not allow values over 50.");
+  _reserve_factor = (double) G1ReservePercent / 100.0;
   // This will be set when the heap is expanded
   // for the first time during initialization.
   _reserve_regions = 0;
 
-  _cset_chooser = new CollectionSetChooser();
-
   _ihop_control = create_ihop_control();
 }
 
@@ -277,14 +134,6 @@
   delete _ihop_control;
 }
 
-double G1CollectorPolicy::get_new_prediction(TruncatedSeq const* seq) const {
-  return _predictor.get_new_prediction(seq);
-}
-
-size_t G1CollectorPolicy::get_new_size_prediction(TruncatedSeq const* seq) const {
-  return (size_t)get_new_prediction(seq);
-}
-
 void G1CollectorPolicy::initialize_alignments() {
   _space_alignment = HeapRegion::GrainBytes;
   size_t card_table_alignment = CardTableRS::ct_max_alignment_constraint();
@@ -294,177 +143,6 @@
 
 G1CollectorState* G1CollectorPolicy::collector_state() const { return _g1->collector_state(); }
 
-// There are three command line options related to the young gen size:
-// NewSize, MaxNewSize and NewRatio (There is also -Xmn, but that is
-// just a short form for NewSize==MaxNewSize). G1 will use its internal
-// heuristics to calculate the actual young gen size, so these options
-// basically only limit the range within which G1 can pick a young gen
-// size. Also, these are general options taking byte sizes. G1 will
-// internally work with a number of regions instead. So, some rounding
-// will occur.
-//
-// If nothing related to the the young gen size is set on the command
-// line we should allow the young gen to be between G1NewSizePercent
-// and G1MaxNewSizePercent of the heap size. This means that every time
-// the heap size changes, the limits for the young gen size will be
-// recalculated.
-//
-// If only -XX:NewSize is set we should use the specified value as the
-// minimum size for young gen. Still using G1MaxNewSizePercent of the
-// heap as maximum.
-//
-// If only -XX:MaxNewSize is set we should use the specified value as the
-// maximum size for young gen. Still using G1NewSizePercent of the heap
-// as minimum.
-//
-// If -XX:NewSize and -XX:MaxNewSize are both specified we use these values.
-// No updates when the heap size changes. There is a special case when
-// NewSize==MaxNewSize. This is interpreted as "fixed" and will use a
-// different heuristic for calculating the collection set when we do mixed
-// collection.
-//
-// If only -XX:NewRatio is set we should use the specified ratio of the heap
-// as both min and max. This will be interpreted as "fixed" just like the
-// NewSize==MaxNewSize case above. But we will update the min and max
-// every time the heap size changes.
-//
-// NewSize and MaxNewSize override NewRatio. So, NewRatio is ignored if it is
-// combined with either NewSize or MaxNewSize. (A warning message is printed.)
-class G1YoungGenSizer : public CHeapObj<mtGC> {
-private:
-  enum SizerKind {
-    SizerDefaults,
-    SizerNewSizeOnly,
-    SizerMaxNewSizeOnly,
-    SizerMaxAndNewSize,
-    SizerNewRatio
-  };
-  SizerKind _sizer_kind;
-  uint _min_desired_young_length;
-  uint _max_desired_young_length;
-  bool _adaptive_size;
-  uint calculate_default_min_length(uint new_number_of_heap_regions);
-  uint calculate_default_max_length(uint new_number_of_heap_regions);
-
-  // Update the given values for minimum and maximum young gen length in regions
-  // given the number of heap regions depending on the kind of sizing algorithm.
-  void recalculate_min_max_young_length(uint number_of_heap_regions, uint* min_young_length, uint* max_young_length);
-
-public:
-  G1YoungGenSizer();
-  // Calculate the maximum length of the young gen given the number of regions
-  // depending on the sizing algorithm.
-  uint max_young_length(uint number_of_heap_regions);
-
-  void heap_size_changed(uint new_number_of_heap_regions);
-  uint min_desired_young_length() {
-    return _min_desired_young_length;
-  }
-  uint max_desired_young_length() {
-    return _max_desired_young_length;
-  }
-
-  bool adaptive_young_list_length() const {
-    return _adaptive_size;
-  }
-};
-
-
-G1YoungGenSizer::G1YoungGenSizer() : _sizer_kind(SizerDefaults), _adaptive_size(true),
-        _min_desired_young_length(0), _max_desired_young_length(0) {
-  if (FLAG_IS_CMDLINE(NewRatio)) {
-    if (FLAG_IS_CMDLINE(NewSize) || FLAG_IS_CMDLINE(MaxNewSize)) {
-      warning("-XX:NewSize and -XX:MaxNewSize override -XX:NewRatio");
-    } else {
-      _sizer_kind = SizerNewRatio;
-      _adaptive_size = false;
-      return;
-    }
-  }
-
-  if (NewSize > MaxNewSize) {
-    if (FLAG_IS_CMDLINE(MaxNewSize)) {
-      warning("NewSize (" SIZE_FORMAT "k) is greater than the MaxNewSize (" SIZE_FORMAT "k). "
-              "A new max generation size of " SIZE_FORMAT "k will be used.",
-              NewSize/K, MaxNewSize/K, NewSize/K);
-    }
-    MaxNewSize = NewSize;
-  }
-
-  if (FLAG_IS_CMDLINE(NewSize)) {
-    _min_desired_young_length = MAX2((uint) (NewSize / HeapRegion::GrainBytes),
-                                     1U);
-    if (FLAG_IS_CMDLINE(MaxNewSize)) {
-      _max_desired_young_length =
-                             MAX2((uint) (MaxNewSize / HeapRegion::GrainBytes),
-                                  1U);
-      _sizer_kind = SizerMaxAndNewSize;
-      _adaptive_size = _min_desired_young_length == _max_desired_young_length;
-    } else {
-      _sizer_kind = SizerNewSizeOnly;
-    }
-  } else if (FLAG_IS_CMDLINE(MaxNewSize)) {
-    _max_desired_young_length =
-                             MAX2((uint) (MaxNewSize / HeapRegion::GrainBytes),
-                                  1U);
-    _sizer_kind = SizerMaxNewSizeOnly;
-  }
-}
-
-uint G1YoungGenSizer::calculate_default_min_length(uint new_number_of_heap_regions) {
-  uint default_value = (new_number_of_heap_regions * G1NewSizePercent) / 100;
-  return MAX2(1U, default_value);
-}
-
-uint G1YoungGenSizer::calculate_default_max_length(uint new_number_of_heap_regions) {
-  uint default_value = (new_number_of_heap_regions * G1MaxNewSizePercent) / 100;
-  return MAX2(1U, default_value);
-}
-
-void G1YoungGenSizer::recalculate_min_max_young_length(uint number_of_heap_regions, uint* min_young_length, uint* max_young_length) {
-  assert(number_of_heap_regions > 0, "Heap must be initialized");
-
-  switch (_sizer_kind) {
-    case SizerDefaults:
-      *min_young_length = calculate_default_min_length(number_of_heap_regions);
-      *max_young_length = calculate_default_max_length(number_of_heap_regions);
-      break;
-    case SizerNewSizeOnly:
-      *max_young_length = calculate_default_max_length(number_of_heap_regions);
-      *max_young_length = MAX2(*min_young_length, *max_young_length);
-      break;
-    case SizerMaxNewSizeOnly:
-      *min_young_length = calculate_default_min_length(number_of_heap_regions);
-      *min_young_length = MIN2(*min_young_length, *max_young_length);
-      break;
-    case SizerMaxAndNewSize:
-      // Do nothing. Values set on the command line, don't update them at runtime.
-      break;
-    case SizerNewRatio:
-      *min_young_length = number_of_heap_regions / (NewRatio + 1);
-      *max_young_length = *min_young_length;
-      break;
-    default:
-      ShouldNotReachHere();
-  }
-
-  assert(*min_young_length <= *max_young_length, "Invalid min/max young gen size values");
-}
-
-uint G1YoungGenSizer::max_young_length(uint number_of_heap_regions) {
-  // We need to pass the desired values because recalculation may not update these
-  // values in some cases.
-  uint temp = _min_desired_young_length;
-  uint result = _max_desired_young_length;
-  recalculate_min_max_young_length(number_of_heap_regions, &temp, &result);
-  return result;
-}
-
-void G1YoungGenSizer::heap_size_changed(uint new_number_of_heap_regions) {
-  recalculate_min_max_young_length(new_number_of_heap_regions, &_min_desired_young_length,
-          &_max_desired_young_length);
-}
-
 void G1CollectorPolicy::post_heap_initialize() {
   uintx max_regions = G1CollectedHeap::heap()->max_regions();
   size_t max_young_size = (size_t)_young_gen_sizer->max_young_length(max_regions) * HeapRegion::GrainBytes;
@@ -478,9 +156,8 @@
     FLAG_SET_ERGO(size_t, G1HeapRegionSize, HeapRegion::GrainBytes);
   }
 
-  if (SurvivorRatio < 1) {
-    vm_exit_during_initialization("Invalid survivor ratio specified");
-  }
+  guarantee(SurvivorRatio >= 1, "Range checking for SurvivorRatio should guarantee that value is >= 1");
+
   CollectorPolicy::initialize_flags();
   _young_gen_sizer = new G1YoungGenSizer(); // Must be after call to initialize_flags
 }
@@ -489,6 +166,8 @@
 void G1CollectorPolicy::init() {
   // Set aside an initial future to_space.
   _g1 = G1CollectedHeap::heap();
+  _collection_set = _g1->collection_set();
+  _collection_set->set_policy(this);
 
   assert(Heap_lock->owned_by_self(), "Locking discipline.");
 
@@ -504,7 +183,7 @@
   update_young_list_max_and_target_length();
   // We may immediately start allocating regions and placing them on the
   // collection set list. Initialize the per-collection set info
-  start_incremental_cset_building();
+  _collection_set->start_incremental_building();
 }
 
 void G1CollectorPolicy::note_gc_start(uint num_active_workers) {
@@ -528,8 +207,9 @@
   double accum_surv_rate = accum_yg_surv_rate_pred((int) young_length - 1);
   size_t bytes_to_copy =
                (size_t) (accum_surv_rate * (double) HeapRegion::GrainBytes);
-  double copy_time_ms = predict_object_copy_time_ms(bytes_to_copy);
-  double young_other_time_ms = predict_young_other_time_ms(young_length);
+  double copy_time_ms = _analytics->predict_object_copy_time_ms(bytes_to_copy,
+                                                                collector_state()->during_concurrent_mark());
+  double young_other_time_ms = _analytics->predict_young_other_time_ms(young_length);
   double pause_time_ms = base_time_ms + copy_time_ms + young_other_time_ms;
   if (pause_time_ms > target_pause_time_ms) {
     // end condition 2: prediction is over the target pause time
@@ -541,12 +221,7 @@
   // When copying, we will likely need more bytes free than is live in the region.
   // Add some safety margin to factor in the confidence of our guess, and the
   // natural expected waste.
-  // (100.0 / G1ConfidencePercent) is a scale factor that expresses the uncertainty
-  // of the calculation: the lower the confidence, the more headroom.
-  // (100 + TargetPLABWastePct) represents the increase in expected bytes during
-  // copying due to anticipated waste in the PLABs.
-  double safety_factor = (100.0 / G1ConfidencePercent) * (100 + TargetPLABWastePct) / 100.0;
-  size_t expected_bytes_to_copy = (size_t)(safety_factor * bytes_to_copy);
+  size_t expected_bytes_to_copy = (size_t)(bytes_to_copy * safety_factor());
 
   if (expected_bytes_to_copy > free_bytes) {
     // end condition 3: out-of-space
@@ -573,10 +248,10 @@
                                                        uint base_min_length) const {
   uint desired_min_length = 0;
   if (adaptive_young_list_length()) {
-    if (_alloc_rate_ms_seq->num() > 3) {
+    if (_analytics->num_alloc_rate_ms() > 3) {
       double now_sec = os::elapsedTime();
       double when_ms = _mmu_tracker->when_max_gc_sec(now_sec) * 1000.0;
-      double alloc_rate_ms = predict_alloc_rate_ms();
+      double alloc_rate_ms = _analytics->predict_alloc_rate_ms();
       desired_min_length = (uint) ceil(alloc_rate_ms * when_ms);
     } else {
       // otherwise we don't have enough info to make the prediction
@@ -595,7 +270,7 @@
 }
 
 uint G1CollectorPolicy::update_young_list_max_and_target_length() {
-  return update_young_list_max_and_target_length(get_new_size_prediction(_rs_lengths_seq));
+  return update_young_list_max_and_target_length(_analytics->predict_rs_lengths());
 }
 
 uint G1CollectorPolicy::update_young_list_max_and_target_length(size_t rs_lengths) {
@@ -616,7 +291,7 @@
   // Calculate the absolute and desired min bounds first.
 
   // This is how many young regions we already have (currently: the survivors).
-  uint base_min_length = recorded_survivor_regions();
+  const uint base_min_length = _g1->young_list()->survivor_length();
   uint desired_min_length = calculate_young_list_desired_min_length(base_min_length);
   // This is the absolute minimum young length. Ensure that we
   // will at least have one eden region available for allocation.
@@ -667,7 +342,7 @@
     young_list_target_length = desired_min_length;
   }
 
-  assert(young_list_target_length > recorded_survivor_regions(),
+  assert(young_list_target_length > base_min_length,
          "we should be able to allocate at least one eden region");
   assert(young_list_target_length >= absolute_min_length, "post-condition");
 
@@ -700,9 +375,9 @@
 
   double target_pause_time_ms = _mmu_tracker->max_gc_time() * 1000.0;
   double survivor_regions_evac_time = predict_survivor_regions_evac_time();
-  size_t pending_cards = get_new_size_prediction(_pending_cards_seq);
-  size_t adj_rs_lengths = rs_lengths + predict_rs_length_diff();
-  size_t scanned_cards = predict_young_card_num(adj_rs_lengths);
+  size_t pending_cards = _analytics->predict_pending_cards();
+  size_t adj_rs_lengths = rs_lengths + _analytics->predict_rs_length_diff();
+  size_t scanned_cards = _analytics->predict_card_num(adj_rs_lengths, /* gcs_are_young */ true);
   double base_time_ms =
     predict_base_elapsed_time_ms(pending_cards, scanned_cards) +
     survivor_regions_evac_time;
@@ -781,8 +456,8 @@
 
 double G1CollectorPolicy::predict_survivor_regions_evac_time() const {
   double survivor_regions_evac_time = 0.0;
-  for (HeapRegion * r = _recorded_survivor_head;
-       r != NULL && r != _recorded_survivor_tail->get_next_young_region();
+  for (HeapRegion * r = _g1->young_list()->first_survivor_region();
+       r != NULL && r != _g1->young_list()->last_survivor_region()->get_next_young_region();
        r = r->get_next_young_region()) {
     survivor_regions_evac_time += predict_region_elapsed_time_ms(r, collector_state()->gcs_are_young());
   }
@@ -802,7 +477,7 @@
 }
 
 void G1CollectorPolicy::update_rs_lengths_prediction() {
-  update_rs_lengths_prediction(get_new_size_prediction(_rs_lengths_seq));
+  update_rs_lengths_prediction(_analytics->predict_rs_lengths());
 }
 
 void G1CollectorPolicy::update_rs_lengths_prediction(size_t prediction) {
@@ -870,7 +545,7 @@
   double full_gc_time_sec = end_sec - _full_collection_start_sec;
   double full_gc_time_ms = full_gc_time_sec * 1000.0;
 
-  update_recent_gc_times(end_sec, full_gc_time_ms);
+  _analytics->update_recent_gc_times(end_sec, full_gc_time_ms);
 
   collector_state()->set_full_collection(false);
 
@@ -886,8 +561,6 @@
   _short_lived_surv_rate_group->start_adding_regions();
   // also call this on any additional surv rate groups
 
-  record_survivor_regions(0, NULL, NULL);
-
   _free_regions_at_end_of_collection = _g1->num_free_regions();
   // Reset survivors SurvRateGroup.
   _survivor_surv_rate_group->reset();
@@ -913,7 +586,8 @@
   phase_times()->record_cur_collection_start_sec(start_time_sec);
   _pending_cards = _g1->pending_card_num();
 
-  _collection_set_bytes_used_before = 0;
+  _collection_set->reset_bytes_used_before();
+  _collection_set->reset_bytes_live_before();
   _bytes_copied_during_gc = 0;
 
   collector_state()->set_last_gc_was_young(false);
@@ -940,8 +614,8 @@
 void G1CollectorPolicy::record_concurrent_mark_remark_end() {
   double end_time_sec = os::elapsedTime();
   double elapsed_time_ms = (end_time_sec - _mark_remark_start_sec)*1000.0;
-  _concurrent_mark_remark_times_ms->add(elapsed_time_ms);
-  _prev_collection_pause_end_ms += elapsed_time_ms;
+  _analytics->report_concurrent_mark_remark_times_ms(elapsed_time_ms);
+  _analytics->append_prev_collection_pause_end_ms(elapsed_time_ms);
 
   record_pause(Remark, _mark_remark_start_sec, end_time_sec);
 }
@@ -988,6 +662,10 @@
   return other_time_ms(pause_time_ms) - young_other_time_ms() - non_young_other_time_ms();
 }
 
+CollectionSetChooser* G1CollectorPolicy::cset_chooser() const {
+  return _collection_set->cset_chooser();
+}
+
 bool G1CollectorPolicy::about_to_start_mixed_phase() const {
   return _g1->concurrent_mark()->cmThread()->during_cycle() || collector_state()->last_young_gc();
 }
@@ -1036,7 +714,7 @@
     maybe_start_marking();
   }
 
-  double app_time_ms = (phase_times()->cur_collection_start_sec() * 1000.0 - _prev_collection_pause_end_ms);
+  double app_time_ms = (phase_times()->cur_collection_start_sec() * 1000.0 - _analytics->prev_collection_pause_end_ms());
   if (app_time_ms < MIN_TIMER_GRANULARITY) {
     // This usually happens due to the timer not having the required
     // granularity. Some Linuxes are the usual culprits.
@@ -1053,33 +731,14 @@
     // given that humongous object allocations do not really affect
     // either the pause's duration nor when the next pause will take
     // place we can safely ignore them here.
-    uint regions_allocated = eden_cset_region_length();
+    uint regions_allocated = _collection_set->eden_region_length();
     double alloc_rate_ms = (double) regions_allocated / app_time_ms;
-    _alloc_rate_ms_seq->add(alloc_rate_ms);
+    _analytics->report_alloc_rate_ms(alloc_rate_ms);
 
     double interval_ms =
-      (end_time_sec - _recent_prev_end_times_for_all_gcs_sec->oldest()) * 1000.0;
-    update_recent_gc_times(end_time_sec, 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;
+      (end_time_sec - _analytics->last_known_gc_end_time_sec()) * 1000.0;
+    _analytics->update_recent_gc_times(end_time_sec, pause_time_ms);
+    _analytics->compute_pause_time_ratio(interval_ms, pause_time_ms);
   }
 
   bool new_in_marking_window = collector_state()->in_marking_window();
@@ -1125,28 +784,20 @@
     double cost_per_card_ms = 0.0;
     if (_pending_cards > 0) {
       cost_per_card_ms = (average_time_ms(G1GCPhaseTimes::UpdateRS) - scan_hcc_time_ms) / (double) _pending_cards;
-      _cost_per_card_ms_seq->add(cost_per_card_ms);
+      _analytics->report_cost_per_card_ms(cost_per_card_ms);
     }
-    _cost_scan_hcc_seq->add(scan_hcc_time_ms);
+    _analytics->report_cost_scan_hcc(scan_hcc_time_ms);
 
     double cost_per_entry_ms = 0.0;
     if (cards_scanned > 10) {
       cost_per_entry_ms = average_time_ms(G1GCPhaseTimes::ScanRS) / (double) cards_scanned;
-      if (collector_state()->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);
-      }
+      _analytics->report_cost_per_entry_ms(cost_per_entry_ms, collector_state()->last_gc_was_young());
     }
 
     if (_max_rs_lengths > 0) {
       double cards_per_entry_ratio =
         (double) cards_scanned / (double) _max_rs_lengths;
-      if (collector_state()->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);
-      }
+      _analytics->report_cards_per_entry_ratio(cards_per_entry_ratio, collector_state()->last_gc_was_young());
     }
 
     // This is defensive. For a while _max_rs_lengths could get
@@ -1163,38 +814,35 @@
     // say, it's in mid-coarsening). So I'll leave in the defensive
     // conditional below just in case.
     size_t rs_length_diff = 0;
-    if (_max_rs_lengths > _recorded_rs_lengths) {
-      rs_length_diff = _max_rs_lengths - _recorded_rs_lengths;
+    size_t recorded_rs_lengths = _collection_set->recorded_rs_lengths();
+    if (_max_rs_lengths > recorded_rs_lengths) {
+      rs_length_diff = _max_rs_lengths - recorded_rs_lengths;
     }
-    _rs_length_diff_seq->add((double) rs_length_diff);
+    _analytics->report_rs_length_diff((double) rs_length_diff);
 
     size_t freed_bytes = heap_used_bytes_before_gc - cur_used_bytes;
-    size_t copied_bytes = _collection_set_bytes_used_before - freed_bytes;
+    size_t copied_bytes = _collection_set->bytes_used_before() - freed_bytes;
     double cost_per_byte_ms = 0.0;
 
     if (copied_bytes > 0) {
       cost_per_byte_ms = average_time_ms(G1GCPhaseTimes::ObjCopy) / (double) copied_bytes;
-      if (collector_state()->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);
-      }
+      _analytics->report_cost_per_byte_ms(cost_per_byte_ms, collector_state()->in_marking_window());
+    }
+
+    if (_collection_set->young_region_length() > 0) {
+      _analytics->report_young_other_cost_per_region_ms(young_other_time_ms() /
+                                                        _collection_set->young_region_length());
     }
 
-    if (young_cset_region_length() > 0) {
-      _young_other_cost_per_region_ms_seq->add(young_other_time_ms() /
-                                               young_cset_region_length());
+    if (_collection_set->old_region_length() > 0) {
+      _analytics->report_non_young_other_cost_per_region_ms(non_young_other_time_ms() /
+                                                            _collection_set->old_region_length());
     }
 
-    if (old_cset_region_length() > 0) {
-      _non_young_other_cost_per_region_ms_seq->add(non_young_other_time_ms() /
-                                                   old_cset_region_length());
-    }
+    _analytics->report_constant_other_time_ms(constant_other_time_ms(pause_time_ms));
 
-    _constant_other_time_ms_seq->add(constant_other_time_ms(pause_time_ms));
-
-    _pending_cards_seq->add((double) _pending_cards);
-    _rs_lengths_seq->add((double) _max_rs_lengths);
+    _analytics->report_pending_cards((double) _pending_cards);
+    _analytics->report_rs_lengths((double) _max_rs_lengths);
   }
 
   collector_state()->set_in_marking_window(new_in_marking_window);
@@ -1226,9 +874,9 @@
   } else {
     update_rs_time_goal_ms -= scan_hcc_time_ms;
   }
-  adjust_concurrent_refinement(average_time_ms(G1GCPhaseTimes::UpdateRS) - scan_hcc_time_ms,
-                               phase_times()->sum_thread_work_items(G1GCPhaseTimes::UpdateRS),
-                               update_rs_time_goal_ms);
+  _g1->concurrent_g1_refine()->adjust(average_time_ms(G1GCPhaseTimes::UpdateRS) - scan_hcc_time_ms,
+                                      phase_times()->sum_thread_work_items(G1GCPhaseTimes::UpdateRS),
+                                      update_rs_time_goal_ms);
 
   cset_chooser()->verify();
 }
@@ -1290,143 +938,10 @@
   phase_times()->print();
 }
 
-void G1CollectorPolicy::adjust_concurrent_refinement(double update_rs_time,
-                                                     double update_rs_processed_buffers,
-                                                     double goal_ms) {
-  DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set();
-  ConcurrentG1Refine *cg1r = G1CollectedHeap::heap()->concurrent_g1_refine();
-
-  if (G1UseAdaptiveConcRefinement) {
-    const int k_gy = 3, k_gr = 6;
-    const double inc_k = 1.1, dec_k = 0.9;
-
-    size_t g = cg1r->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
-    cg1r->set_green_zone(g);
-    cg1r->set_yellow_zone(g * k_gy);
-    cg1r->set_red_zone(g * k_gr);
-    cg1r->reinitialize_threads();
-
-    size_t processing_threshold_delta = MAX2<size_t>(cg1r->green_zone() * _predictor.sigma(), 1);
-    size_t processing_threshold = MIN2(cg1r->green_zone() + processing_threshold_delta,
-                                    cg1r->yellow_zone());
-    // Change the barrier params
-    dcqs.set_process_completed_threshold((int)processing_threshold);
-    dcqs.set_max_completed_queue((int)cg1r->red_zone());
-  }
-
-  size_t curr_queue_size = dcqs.completed_buffers_num();
-  if (curr_queue_size >= cg1r->yellow_zone()) {
-    dcqs.set_completed_queue_padding(curr_queue_size);
-  } else {
-    dcqs.set_completed_queue_padding(0);
-  }
-  dcqs.notify_if_necessary();
-}
-
-size_t G1CollectorPolicy::predict_rs_length_diff() const {
-  return get_new_size_prediction(_rs_length_diff_seq);
-}
-
-double G1CollectorPolicy::predict_alloc_rate_ms() const {
-  return get_new_prediction(_alloc_rate_ms_seq);
-}
-
-double G1CollectorPolicy::predict_cost_per_card_ms() const {
-  return get_new_prediction(_cost_per_card_ms_seq);
-}
-
-double G1CollectorPolicy::predict_scan_hcc_ms() const {
-  return get_new_prediction(_cost_scan_hcc_seq);
-}
-
-double G1CollectorPolicy::predict_rs_update_time_ms(size_t pending_cards) const {
-  return pending_cards * predict_cost_per_card_ms() + predict_scan_hcc_ms();
-}
-
-double G1CollectorPolicy::predict_young_cards_per_entry_ratio() const {
-  return get_new_prediction(_young_cards_per_entry_ratio_seq);
-}
-
-double G1CollectorPolicy::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 G1CollectorPolicy::predict_young_card_num(size_t rs_length) const {
-  return (size_t) (rs_length * predict_young_cards_per_entry_ratio());
-}
-
-size_t G1CollectorPolicy::predict_non_young_card_num(size_t rs_length) const {
-  return (size_t)(rs_length * predict_mixed_cards_per_entry_ratio());
-}
-
-double G1CollectorPolicy::predict_rs_scan_time_ms(size_t card_num) const {
-  if (collector_state()->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 G1CollectorPolicy::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 G1CollectorPolicy::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 G1CollectorPolicy::predict_object_copy_time_ms(size_t bytes_to_copy) const {
-  if (collector_state()->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 G1CollectorPolicy::predict_constant_other_time_ms() const {
-  return get_new_prediction(_constant_other_time_ms_seq);
-}
-
-double G1CollectorPolicy::predict_young_other_time_ms(size_t young_num) const {
-  return young_num * get_new_prediction(_young_other_cost_per_region_ms_seq);
-}
-
-double G1CollectorPolicy::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 G1CollectorPolicy::predict_remark_time_ms() const {
-  return get_new_prediction(_concurrent_mark_remark_times_ms);
-}
-
-double G1CollectorPolicy::predict_cleanup_time_ms() const {
-  return get_new_prediction(_concurrent_mark_cleanup_times_ms);
-}
-
 double G1CollectorPolicy::predict_yg_surv_rate(int age, SurvRateGroup* surv_rate_group) const {
   TruncatedSeq* seq = surv_rate_group->get_seq(age);
   guarantee(seq->num() > 0, "There should be some young gen survivor samples available. Tried to access with age %d", age);
-  double pred = get_new_prediction(seq);
+  double pred = _predictor.get_new_prediction(seq);
   if (pred > 1.0) {
     pred = 1.0;
   }
@@ -1444,19 +959,14 @@
 double G1CollectorPolicy::predict_base_elapsed_time_ms(size_t pending_cards,
                                                        size_t scanned_cards) const {
   return
-    predict_rs_update_time_ms(pending_cards) +
-    predict_rs_scan_time_ms(scanned_cards) +
-    predict_constant_other_time_ms();
+    _analytics->predict_rs_update_time_ms(pending_cards) +
+    _analytics->predict_rs_scan_time_ms(scanned_cards, collector_state()->gcs_are_young()) +
+    _analytics->predict_constant_other_time_ms();
 }
 
 double G1CollectorPolicy::predict_base_elapsed_time_ms(size_t pending_cards) const {
-  size_t rs_length = predict_rs_length_diff();
-  size_t card_num;
-  if (collector_state()->gcs_are_young()) {
-    card_num = predict_young_card_num(rs_length);
-  } else {
-    card_num = predict_non_young_card_num(rs_length);
-  }
+  size_t rs_length = _analytics->predict_rs_lengths() + _analytics->predict_rs_length_diff();
+  size_t card_num = _analytics->predict_card_num(rs_length, collector_state()->gcs_are_young());
   return predict_base_elapsed_time_ms(pending_cards, card_num);
 }
 
@@ -1476,160 +986,25 @@
 double G1CollectorPolicy::predict_region_elapsed_time_ms(HeapRegion* hr,
                                                          bool for_young_gc) const {
   size_t rs_length = hr->rem_set()->occupied();
-  size_t card_num;
-
   // Predicting the number of cards is based on which type of GC
   // we're predicting for.
-  if (for_young_gc) {
-    card_num = predict_young_card_num(rs_length);
-  } else {
-    card_num = predict_non_young_card_num(rs_length);
-  }
+  size_t card_num = _analytics->predict_card_num(rs_length, for_young_gc);
   size_t bytes_to_copy = predict_bytes_to_copy(hr);
 
   double region_elapsed_time_ms =
-    predict_rs_scan_time_ms(card_num) +
-    predict_object_copy_time_ms(bytes_to_copy);
+    _analytics->predict_rs_scan_time_ms(card_num, collector_state()->gcs_are_young()) +
+    _analytics->predict_object_copy_time_ms(bytes_to_copy, collector_state()->during_concurrent_mark());
 
   // The prediction of the "other" time for this region is based
   // upon the region type and NOT the GC type.
   if (hr->is_young()) {
-    region_elapsed_time_ms += predict_young_other_time_ms(1);
+    region_elapsed_time_ms += _analytics->predict_young_other_time_ms(1);
   } else {
-    region_elapsed_time_ms += predict_non_young_other_time_ms(1);
+    region_elapsed_time_ms += _analytics->predict_non_young_other_time_ms(1);
   }
   return region_elapsed_time_ms;
 }
 
-void G1CollectorPolicy::init_cset_region_lengths(uint eden_cset_region_length,
-                                                 uint survivor_cset_region_length) {
-  _eden_cset_region_length     = eden_cset_region_length;
-  _survivor_cset_region_length = survivor_cset_region_length;
-  _old_cset_region_length      = 0;
-}
-
-void G1CollectorPolicy::set_recorded_rs_lengths(size_t rs_lengths) {
-  _recorded_rs_lengths = rs_lengths;
-}
-
-void G1CollectorPolicy::update_recent_gc_times(double end_time_sec,
-                                               double elapsed_ms) {
-  _recent_gc_times_ms->add(elapsed_ms);
-  _recent_prev_end_times_for_all_gcs_sec->add(end_time_sec);
-  _prev_collection_pause_end_ms = end_time_sec * 1000.0;
-}
-
-void G1CollectorPolicy::clear_ratio_check_data() {
-  _ratio_over_threshold_count = 0;
-  _ratio_over_threshold_sum = 0.0;
-  _pauses_since_start = 0;
-}
-
-size_t G1CollectorPolicy::expansion_amount() {
-  double recent_gc_overhead = recent_avg_pause_time_ratio() * 100.0;
-  double last_gc_overhead = _last_pause_time_ratio * 100.0;
-  double threshold = _gc_overhead_perc;
-  size_t expand_bytes = 0;
-
-  // If the heap is at less than half its maximum size, scale the threshold down,
-  // to a limit of 1. Thus the smaller the heap is, the more likely it is to expand,
-  // though the scaling code will likely keep the increase small.
-  if (_g1->capacity() <= _g1->max_capacity() / 2) {
-    threshold *= (double)_g1->capacity() / (double)(_g1->max_capacity() / 2);
-    threshold = MAX2(threshold, 1.0);
-  }
-
-  // If the last GC time ratio is over the threshold, increment the count of
-  // times it has been exceeded, and add this ratio to the sum of exceeded
-  // ratios.
-  if (last_gc_overhead > threshold) {
-    _ratio_over_threshold_count++;
-    _ratio_over_threshold_sum += last_gc_overhead;
-  }
-
-  // Check if we've had enough GC time ratio checks that were over the
-  // threshold to trigger an expansion. We'll also expand if we've
-  // reached the end of the history buffer and the average of all entries
-  // is still over the threshold. This indicates a smaller number of GCs were
-  // long enough to make the average exceed the threshold.
-  bool filled_history_buffer = _pauses_since_start == NumPrevPausesForHeuristics;
-  if ((_ratio_over_threshold_count == MinOverThresholdForGrowth) ||
-      (filled_history_buffer && (recent_gc_overhead > threshold))) {
-    size_t min_expand_bytes = HeapRegion::GrainBytes;
-    size_t reserved_bytes = _g1->max_capacity();
-    size_t committed_bytes = _g1->capacity();
-    size_t uncommitted_bytes = reserved_bytes - committed_bytes;
-    size_t expand_bytes_via_pct =
-      uncommitted_bytes * G1ExpandByPercentOfAvailable / 100;
-    double scale_factor = 1.0;
-
-    // If the current size is less than 1/4 of the Initial heap size, expand
-    // by half of the delta between the current and Initial sizes. IE, grow
-    // back quickly.
-    //
-    // Otherwise, take the current size, or G1ExpandByPercentOfAvailable % of
-    // the available expansion space, whichever is smaller, as the base
-    // expansion size. Then possibly scale this size according to how much the
-    // threshold has (on average) been exceeded by. If the delta is small
-    // (less than the StartScaleDownAt value), scale the size down linearly, but
-    // not by less than MinScaleDownFactor. If the delta is large (greater than
-    // the StartScaleUpAt value), scale up, but adding no more than MaxScaleUpFactor
-    // times the base size. The scaling will be linear in the range from
-    // StartScaleUpAt to (StartScaleUpAt + ScaleUpRange). In other words,
-    // ScaleUpRange sets the rate of scaling up.
-    if (committed_bytes < InitialHeapSize / 4) {
-      expand_bytes = (InitialHeapSize - committed_bytes) / 2;
-    } else {
-      double const MinScaleDownFactor = 0.2;
-      double const MaxScaleUpFactor = 2;
-      double const StartScaleDownAt = _gc_overhead_perc;
-      double const StartScaleUpAt = _gc_overhead_perc * 1.5;
-      double const ScaleUpRange = _gc_overhead_perc * 2.0;
-
-      double ratio_delta;
-      if (filled_history_buffer) {
-        ratio_delta = recent_gc_overhead - threshold;
-      } else {
-        ratio_delta = (_ratio_over_threshold_sum/_ratio_over_threshold_count) - threshold;
-      }
-
-      expand_bytes = MIN2(expand_bytes_via_pct, committed_bytes);
-      if (ratio_delta < StartScaleDownAt) {
-        scale_factor = ratio_delta / StartScaleDownAt;
-        scale_factor = MAX2(scale_factor, MinScaleDownFactor);
-      } else if (ratio_delta > StartScaleUpAt) {
-        scale_factor = 1 + ((ratio_delta - StartScaleUpAt) / ScaleUpRange);
-        scale_factor = MIN2(scale_factor, MaxScaleUpFactor);
-      }
-    }
-
-    log_debug(gc, ergo, heap)("Attempt heap expansion (recent GC overhead higher than threshold after GC) "
-                              "recent GC overhead: %1.2f %% threshold: %1.2f %% uncommitted: " SIZE_FORMAT "B base expansion amount and scale: " SIZE_FORMAT "B (%1.2f%%)",
-                              recent_gc_overhead, threshold, uncommitted_bytes, expand_bytes, scale_factor * 100);
-
-    expand_bytes = static_cast<size_t>(expand_bytes * scale_factor);
-
-    // Ensure the expansion size is at least the minimum growth amount
-    // and at most the remaining uncommitted byte size.
-    expand_bytes = MAX2(expand_bytes, min_expand_bytes);
-    expand_bytes = MIN2(expand_bytes, uncommitted_bytes);
-
-    clear_ratio_check_data();
-  } else {
-    // An expansion was not triggered. If we've started counting, increment
-    // the number of checks we've made in the current window.  If we've
-    // reached the end of the window without resizing, clear the counters to
-    // start again the next time we see a ratio above the threshold.
-    if (_ratio_over_threshold_count > 0) {
-      _pauses_since_start++;
-      if (_pauses_since_start > NumPrevPausesForHeuristics) {
-        clear_ratio_check_data();
-      }
-    }
-  }
-
-  return expand_bytes;
-}
 
 void G1CollectorPolicy::print_yg_surv_rate_info() const {
 #ifndef PRODUCT
@@ -1747,269 +1122,17 @@
   }
 }
 
-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 G1CollectorPolicy::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 G1CollectorPolicy::record_concurrent_mark_cleanup_end() {
-  cset_chooser()->clear();
-
-  WorkGang* workers = _g1->workers();
-  uint n_workers = workers->active_workers();
-
-  uint n_regions = _g1->num_regions();
-  uint chunk_size = calculate_parallel_work_chunk_size(n_workers, n_regions);
-  cset_chooser()->prepare_for_par_region_addition(n_workers, n_regions, chunk_size);
-  ParKnownGarbageTask par_known_garbage_task(cset_chooser(), chunk_size, n_workers);
-  workers->run_task(&par_known_garbage_task);
-
-  cset_chooser()->sort_regions();
+  cset_chooser()->rebuild(_g1->workers(), _g1->num_regions());
 
   double end_sec = os::elapsedTime();
   double elapsed_time_ms = (end_sec - _mark_cleanup_start_sec) * 1000.0;
-  _concurrent_mark_cleanup_times_ms->add(elapsed_time_ms);
-  _prev_collection_pause_end_ms += elapsed_time_ms;
+  _analytics->report_concurrent_mark_cleanup_times_ms(elapsed_time_ms);
+  _analytics->append_prev_collection_pause_end_ms(elapsed_time_ms);
 
   record_pause(Cleanup, _mark_cleanup_start_sec, end_sec);
 }
 
-// Add the heap region at the head of the non-incremental collection set
-void G1CollectorPolicy::add_old_region_to_cset(HeapRegion* hr) {
-  assert(_inc_cset_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(_collection_set);
-  _collection_set = hr;
-  _collection_set_bytes_used_before += hr->used();
-  size_t rs_length = hr->rem_set()->occupied();
-  _recorded_rs_lengths += rs_length;
-  _old_cset_region_length += 1;
-}
-
-// Initialize the per-collection-set information
-void G1CollectorPolicy::start_incremental_cset_building() {
-  assert(_inc_cset_build_state == Inactive, "Precondition");
-
-  _inc_cset_head = NULL;
-  _inc_cset_tail = NULL;
-  _inc_cset_bytes_used_before = 0;
-
-  _inc_cset_recorded_rs_lengths = 0;
-  _inc_cset_recorded_rs_lengths_diffs = 0;
-  _inc_cset_predicted_elapsed_time_ms = 0.0;
-  _inc_cset_predicted_elapsed_time_ms_diffs = 0.0;
-  _inc_cset_build_state = Active;
-}
-
-void G1CollectorPolicy::finalize_incremental_cset_building() {
-  assert(_inc_cset_build_state == Active, "Precondition");
-  assert(SafepointSynchronize::is_at_safepoint(), "should be at a safepoint");
-
-  // The two "main" fields, _inc_cset_recorded_rs_lengths and
-  // _inc_cset_predicted_elapsed_time_ms, are updated by the thread
-  // that adds a new region to the CSet. Further updates by the
-  // concurrent refinement thread that samples the young RSet lengths
-  // are accumulated in the *_diffs fields. Here we add the diffs to
-  // the "main" fields.
-
-  if (_inc_cset_recorded_rs_lengths_diffs >= 0) {
-    _inc_cset_recorded_rs_lengths += _inc_cset_recorded_rs_lengths_diffs;
-  } else {
-    // This is defensive. The diff should in theory be always positive
-    // as RSets can only grow between GCs. However, given that we
-    // sample their size concurrently with other threads updating them
-    // it's possible that we might get the wrong size back, which
-    // could make the calculations somewhat inaccurate.
-    size_t diffs = (size_t) (-_inc_cset_recorded_rs_lengths_diffs);
-    if (_inc_cset_recorded_rs_lengths >= diffs) {
-      _inc_cset_recorded_rs_lengths -= diffs;
-    } else {
-      _inc_cset_recorded_rs_lengths = 0;
-    }
-  }
-  _inc_cset_predicted_elapsed_time_ms +=
-                                     _inc_cset_predicted_elapsed_time_ms_diffs;
-
-  _inc_cset_recorded_rs_lengths_diffs = 0;
-  _inc_cset_predicted_elapsed_time_ms_diffs = 0.0;
-}
-
-void G1CollectorPolicy::add_to_incremental_cset_info(HeapRegion* hr, size_t rs_length) {
-  // This routine is used when:
-  // * adding survivor regions to the incremental cset at the end of an
-  //   evacuation pause,
-  // * adding the current allocation region to the incremental cset
-  //   when it is retired, and
-  // * updating existing policy information for a region in the
-  //   incremental cset via young list RSet sampling.
-  // Therefore this routine may be called at a safepoint by the
-  // VM thread, or in-between safepoints by mutator threads (when
-  // retiring the current allocation region) or a concurrent
-  // refine thread (RSet sampling).
-
-  double region_elapsed_time_ms = predict_region_elapsed_time_ms(hr, collector_state()->gcs_are_young());
-  size_t used_bytes = hr->used();
-  _inc_cset_recorded_rs_lengths += rs_length;
-  _inc_cset_predicted_elapsed_time_ms += region_elapsed_time_ms;
-  _inc_cset_bytes_used_before += used_bytes;
-
-  // Cache the values we have added to the aggregated information
-  // in the heap region in case we have to remove this region from
-  // the incremental collection set, or it is updated by the
-  // rset sampling code
-  hr->set_recorded_rs_length(rs_length);
-  hr->set_predicted_elapsed_time_ms(region_elapsed_time_ms);
-}
-
-void G1CollectorPolicy::update_incremental_cset_info(HeapRegion* hr,
-                                                     size_t new_rs_length) {
-  // Update the CSet information that is dependent on the new RS length
-  assert(hr->is_young(), "Precondition");
-  assert(!SafepointSynchronize::is_at_safepoint(),
-                                               "should not be at a safepoint");
-
-  // We could have updated _inc_cset_recorded_rs_lengths and
-  // _inc_cset_predicted_elapsed_time_ms directly but we'd need to do
-  // that atomically, as this code is executed by a concurrent
-  // refinement thread, potentially concurrently with a mutator thread
-  // allocating a new region and also updating the same fields. To
-  // avoid the atomic operations we accumulate these updates on two
-  // separate fields (*_diffs) and we'll just add them to the "main"
-  // fields at the start of a GC.
-
-  ssize_t old_rs_length = (ssize_t) hr->recorded_rs_length();
-  ssize_t rs_lengths_diff = (ssize_t) new_rs_length - old_rs_length;
-  _inc_cset_recorded_rs_lengths_diffs += rs_lengths_diff;
-
-  double old_elapsed_time_ms = hr->predicted_elapsed_time_ms();
-  double new_region_elapsed_time_ms = predict_region_elapsed_time_ms(hr, collector_state()->gcs_are_young());
-  double elapsed_ms_diff = new_region_elapsed_time_ms - old_elapsed_time_ms;
-  _inc_cset_predicted_elapsed_time_ms_diffs += elapsed_ms_diff;
-
-  hr->set_recorded_rs_length(new_rs_length);
-  hr->set_predicted_elapsed_time_ms(new_region_elapsed_time_ms);
-}
-
-void G1CollectorPolicy::add_region_to_incremental_cset_common(HeapRegion* hr) {
-  assert(hr->is_young(), "invariant");
-  assert(hr->young_index_in_cset() > -1, "should have already been set");
-  assert(_inc_cset_build_state == Active, "Precondition");
-
-  // We need to clear and set the cached recorded/cached collection set
-  // information in the heap region here (before the region gets added
-  // to the collection set). An individual heap region's cached values
-  // are calculated, aggregated with the policy collection set info,
-  // and cached in the heap region here (initially) and (subsequently)
-  // by the Young List sampling code.
-
-  size_t rs_length = hr->rem_set()->occupied();
-  add_to_incremental_cset_info(hr, rs_length);
-
-  assert(!hr->in_collection_set(), "invariant");
-  _g1->register_young_region_with_cset(hr);
-  assert(hr->next_in_collection_set() == NULL, "invariant");
-}
-
-// Add the region at the RHS of the incremental cset
-void G1CollectorPolicy::add_region_to_incremental_cset_rhs(HeapRegion* hr) {
-  // We should only ever be appending survivors at the end of a pause
-  assert(hr->is_survivor(), "Logic");
-
-  // Do the 'common' stuff
-  add_region_to_incremental_cset_common(hr);
-
-  // Now add the region at the right hand side
-  if (_inc_cset_tail == NULL) {
-    assert(_inc_cset_head == NULL, "invariant");
-    _inc_cset_head = hr;
-  } else {
-    _inc_cset_tail->set_next_in_collection_set(hr);
-  }
-  _inc_cset_tail = hr;
-}
-
-// Add the region to the LHS of the incremental cset
-void G1CollectorPolicy::add_region_to_incremental_cset_lhs(HeapRegion* hr) {
-  // Survivors should be added to the RHS at the end of a pause
-  assert(hr->is_eden(), "Logic");
-
-  // Do the 'common' stuff
-  add_region_to_incremental_cset_common(hr);
-
-  // Add the region at the left hand side
-  hr->set_next_in_collection_set(_inc_cset_head);
-  if (_inc_cset_head == NULL) {
-    assert(_inc_cset_tail == NULL, "Invariant");
-    _inc_cset_tail = hr;
-  }
-  _inc_cset_head = hr;
-}
-
-#ifndef PRODUCT
-void G1CollectorPolicy::print_collection_set(HeapRegion* list_head, outputStream* st) {
-  assert(list_head == inc_cset_head() || list_head == collection_set(), "must be");
-
-  st->print_cr("\nCollection_set:");
-  HeapRegion* csr = list_head;
-  while (csr != NULL) {
-    HeapRegion* next = csr->next_in_collection_set();
-    assert(csr->in_collection_set(), "bad CS");
-    st->print_cr("  " HR_FORMAT ", P: " PTR_FORMAT "N: " PTR_FORMAT ", age: %4d",
-                 HR_FORMAT_PARAMS(csr),
-                 p2i(csr->prev_top_at_mark_start()), p2i(csr->next_top_at_mark_start()),
-                 csr->age_in_surv_rate_group_cond());
-    csr = next;
-  }
-}
-#endif // !PRODUCT
-
 double G1CollectorPolicy::reclaimable_bytes_perc(size_t reclaimable_bytes) const {
   // Returns the given amount of reclaimable bytes (that represents
   // the amount of reclaimable space still to be collected) as a
@@ -2139,161 +1262,16 @@
   return (uint) result;
 }
 
-
-double G1CollectorPolicy::finalize_young_cset_part(double target_pause_time_ms) {
-  double young_start_time_sec = os::elapsedTime();
-
-  YoungList* young_list = _g1->young_list();
-  finalize_incremental_cset_building();
-
-  guarantee(target_pause_time_ms > 0.0,
-            "target_pause_time_ms = %1.6lf should be positive", target_pause_time_ms);
-  guarantee(_collection_set == NULL, "Precondition");
-
-  double base_time_ms = predict_base_elapsed_time_ms(_pending_cards);
-  double time_remaining_ms = MAX2(target_pause_time_ms - base_time_ms, 0.0);
-
-  log_trace(gc, ergo, cset)("Start choosing CSet. pending cards: " SIZE_FORMAT " predicted base time: %1.2fms remaining time: %1.2fms target pause time: %1.2fms",
-                            _pending_cards, base_time_ms, time_remaining_ms, target_pause_time_ms);
-
-  collector_state()->set_last_gc_was_young(collector_state()->gcs_are_young());
-
-  // The young list is laid with the survivor regions from the previous
-  // pause are appended to the RHS of the young list, i.e.
-  //   [Newly Young Regions ++ Survivors from last pause].
-
-  uint survivor_region_length = young_list->survivor_length();
-  uint eden_region_length = young_list->eden_length();
-  init_cset_region_lengths(eden_region_length, survivor_region_length);
-
-  HeapRegion* hr = young_list->first_survivor_region();
-  while (hr != NULL) {
-    assert(hr->is_survivor(), "badly formed young list");
-    // There is a convention that all the young regions in the CSet
-    // are tagged as "eden", so we do this for the survivors here. We
-    // use the special set_eden_pre_gc() as it doesn't check that the
-    // region is free (which is not the case here).
-    hr->set_eden_pre_gc();
-    hr = hr->get_next_young_region();
+size_t G1CollectorPolicy::available_bytes_estimate() {
+  size_t estimated_available_bytes = 0;
+  if (_free_regions_at_end_of_collection > _reserve_regions) {
+    uint available_regions = _free_regions_at_end_of_collection - _reserve_regions;
+    estimated_available_bytes = (size_t)((available_regions * HeapRegion::GrainBytes) / safety_factor());
   }
-
-  // Clear the fields that point to the survivor list - they are all young now.
-  young_list->clear_survivors();
-
-  _collection_set = _inc_cset_head;
-  _collection_set_bytes_used_before = _inc_cset_bytes_used_before;
-  time_remaining_ms = MAX2(time_remaining_ms - _inc_cset_predicted_elapsed_time_ms, 0.0);
-
-  log_trace(gc, ergo, cset)("Add young regions to CSet. eden: %u regions, survivors: %u regions, predicted young region time: %1.2fms, target pause time: %1.2fms",
-                            eden_region_length, survivor_region_length, _inc_cset_predicted_elapsed_time_ms, target_pause_time_ms);
-
-  // The number of recorded young regions is the incremental
-  // collection set's current size
-  set_recorded_rs_lengths(_inc_cset_recorded_rs_lengths);
-
-  double young_end_time_sec = os::elapsedTime();
-  phase_times()->record_young_cset_choice_time_ms((young_end_time_sec - young_start_time_sec) * 1000.0);
-
-  return time_remaining_ms;
+  return estimated_available_bytes;
 }
 
-void G1CollectorPolicy::finalize_old_cset_part(double time_remaining_ms) {
-  double non_young_start_time_sec = os::elapsedTime();
-  double predicted_old_time_ms = 0.0;
-
-
-  if (!collector_state()->gcs_are_young()) {
-    cset_chooser()->verify();
-    const uint min_old_cset_length = calc_min_old_cset_length();
-    const uint max_old_cset_length = calc_max_old_cset_length();
-
-    uint expensive_region_num = 0;
-    bool check_time_remaining = adaptive_young_list_length();
-
-    HeapRegion* hr = cset_chooser()->peek();
-    while (hr != NULL) {
-      if (old_cset_region_length() >= max_old_cset_length) {
-        // Added maximum number of old regions to the CSet.
-        log_debug(gc, ergo, cset)("Finish adding old regions to CSet (old CSet region num reached max). old %u regions, max %u regions",
-                                  old_cset_region_length(), max_old_cset_length);
-        break;
-      }
-
-
-      // Stop adding regions if the remaining reclaimable space is
-      // not above G1HeapWastePercent.
-      size_t reclaimable_bytes = cset_chooser()->remaining_reclaimable_bytes();
-      double reclaimable_perc = reclaimable_bytes_perc(reclaimable_bytes);
-      double threshold = (double) G1HeapWastePercent;
-      if (reclaimable_perc <= threshold) {
-        // We've added enough old regions that the amount of uncollected
-        // reclaimable space is at or below the waste threshold. Stop
-        // adding old regions to the CSet.
-        log_debug(gc, ergo, cset)("Finish adding old regions to CSet (reclaimable percentage not over threshold). "
-                                  "old %u regions, max %u regions, reclaimable: " SIZE_FORMAT "B (%1.2f%%) threshold: " UINTX_FORMAT "%%",
-                                  old_cset_region_length(), max_old_cset_length, reclaimable_bytes, reclaimable_perc, G1HeapWastePercent);
-        break;
-      }
-
-      double predicted_time_ms = predict_region_elapsed_time_ms(hr, collector_state()->gcs_are_young());
-      if (check_time_remaining) {
-        if (predicted_time_ms > time_remaining_ms) {
-          // Too expensive for the current CSet.
-
-          if (old_cset_region_length() >= min_old_cset_length) {
-            // We have added the minimum number of old regions to the CSet,
-            // we are done with this CSet.
-            log_debug(gc, ergo, cset)("Finish adding old regions to CSet (predicted time is too high). "
-                                      "predicted time: %1.2fms, remaining time: %1.2fms old %u regions, min %u regions",
-                                      predicted_time_ms, time_remaining_ms, old_cset_region_length(), min_old_cset_length);
-            break;
-          }
-
-          // We'll add it anyway given that we haven't reached the
-          // minimum number of old regions.
-          expensive_region_num += 1;
-        }
-      } else {
-        if (old_cset_region_length() >= min_old_cset_length) {
-          // In the non-auto-tuning case, we'll finish adding regions
-          // to the CSet if we reach the minimum.
-
-          log_debug(gc, ergo, cset)("Finish adding old regions to CSet (old CSet region num reached min). old %u regions, min %u regions",
-                                    old_cset_region_length(), min_old_cset_length);
-          break;
-        }
-      }
-
-      // We will add this region to the CSet.
-      time_remaining_ms = MAX2(time_remaining_ms - predicted_time_ms, 0.0);
-      predicted_old_time_ms += predicted_time_ms;
-      cset_chooser()->pop(); // already have region via peek()
-      _g1->old_set_remove(hr);
-      add_old_region_to_cset(hr);
-
-      hr = cset_chooser()->peek();
-    }
-    if (hr == NULL) {
-      log_debug(gc, ergo, cset)("Finish adding old regions to CSet (candidate old regions not available)");
-    }
-
-    if (expensive_region_num > 0) {
-      // We print the information once here at the end, predicated on
-      // whether we added any apparently expensive regions or not, to
-      // avoid generating output per region.
-      log_debug(gc, ergo, cset)("Added expensive regions to CSet (old CSet region num not reached min)."
-                                "old: %u regions, expensive: %u regions, min: %u regions, remaining time: %1.2fms",
-                                old_cset_region_length(), expensive_region_num, min_old_cset_length, time_remaining_ms);
-    }
-
-    cset_chooser()->verify();
-  }
-
-  stop_incremental_cset_building();
-
-  log_debug(gc, ergo, cset)("Finish choosing CSet. old: %u regions, predicted old region time: %1.2fms, time remaining: %1.2f",
-                            old_cset_region_length(), predicted_old_time_ms, time_remaining_ms);
-
-  double non_young_end_time_sec = os::elapsedTime();
-  phase_times()->record_non_young_cset_choice_time_ms((non_young_end_time_sec - non_young_start_time_sec) * 1000.0);
+void G1CollectorPolicy::finalize_collection_set(double target_pause_time_ms) {
+  double time_remaining_ms = _collection_set->finalize_young_part(target_pause_time_ms);
+  _collection_set->finalize_old_part(time_remaining_ms);
 }
--- a/hotspot/src/share/vm/gc/g1/g1CollectorPolicy.hpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/gc/g1/g1CollectorPolicy.hpp	Wed Mar 23 23:36:29 2016 +0100
@@ -25,7 +25,6 @@
 #ifndef SHARE_VM_GC_G1_G1COLLECTORPOLICY_HPP
 #define SHARE_VM_GC_G1_G1COLLECTORPOLICY_HPP
 
-#include "gc/g1/collectionSetChooser.hpp"
 #include "gc/g1/g1CollectorState.hpp"
 #include "gc/g1/g1GCPhaseTimes.hpp"
 #include "gc/g1/g1InCSetState.hpp"
@@ -41,8 +40,10 @@
 //   * when to collect.
 
 class HeapRegion;
+class G1CollectionSet;
 class CollectionSetChooser;
 class G1IHOPControl;
+class G1Analytics;
 class G1YoungGenSizer;
 
 class G1CollectorPolicy: public CollectorPolicy {
@@ -57,30 +58,14 @@
   void report_ihop_statistics();
 
   G1Predictions _predictor;
-
-  double get_new_prediction(TruncatedSeq const* seq) const;
-  size_t get_new_size_prediction(TruncatedSeq const* seq) const;
-
+  G1Analytics* _analytics;
   G1MMUTracker* _mmu_tracker;
 
   void initialize_alignments();
   void initialize_flags();
 
-  CollectionSetChooser* _cset_chooser;
-
   double _full_collection_start_sec;
 
-  // These exclude marking times.
-  TruncatedSeq* _recent_gc_times_ms;
-
-  TruncatedSeq* _concurrent_mark_remark_times_ms;
-  TruncatedSeq* _concurrent_mark_cleanup_times_ms;
-
-  // Ratio check data for determining if heap growth is necessary.
-  uint _ratio_over_threshold_count;
-  double _ratio_over_threshold_sum;
-  uint _pauses_since_start;
-
   uint _young_list_target_length;
   uint _young_list_fixed_length;
 
@@ -90,58 +75,14 @@
 
   SurvRateGroup* _short_lived_surv_rate_group;
   SurvRateGroup* _survivor_surv_rate_group;
-  // add here any more surv rate groups
-
-  double _gc_overhead_perc;
 
   double _reserve_factor;
   uint   _reserve_regions;
 
-  enum PredictionConstants {
-    TruncatedSeqLength = 10,
-    NumPrevPausesForHeuristics = 10,
-    // MinOverThresholdForGrowth must be less than NumPrevPausesForHeuristics,
-    // representing the minimum number of pause time ratios that exceed
-    // GCTimeRatio before a heap expansion will be triggered.
-    MinOverThresholdForGrowth = 4
-  };
-
-  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;
-
   G1YoungGenSizer* _young_gen_sizer;
 
-  uint _eden_cset_region_length;
-  uint _survivor_cset_region_length;
-  uint _old_cset_region_length;
-
-  void init_cset_region_lengths(uint eden_cset_region_length,
-                                uint survivor_cset_region_length);
-
-  uint eden_cset_region_length() const     { return _eden_cset_region_length;     }
-  uint survivor_cset_region_length() const { return _survivor_cset_region_length; }
-  uint old_cset_region_length() const      { return _old_cset_region_length;      }
-
   uint _free_regions_at_end_of_collection;
 
-  size_t _recorded_rs_lengths;
   size_t _max_rs_lengths;
 
   size_t _rs_lengths_prediction;
@@ -150,10 +91,6 @@
   bool verify_young_ages(HeapRegion* head, SurvRateGroup *surv_rate_group);
 #endif // PRODUCT
 
-  void adjust_concurrent_refinement(double update_rs_time,
-                                    double update_rs_processed_buffers,
-                                    double goal_ms);
-
   double _pause_time_target_ms;
 
   size_t _pending_cards;
@@ -165,6 +102,7 @@
   G1InitialMarkToMixedTimeTracker _initial_mark_to_mixed;
 public:
   const G1Predictions& predictor() const { return _predictor; }
+  const G1Analytics* analytics()   const { return const_cast<const G1Analytics*>(_analytics); }
 
   // Add the given number of bytes to the total number of allocated bytes in the old gen.
   void add_bytes_allocated_in_old_since_last_gc(size_t bytes) { _bytes_allocated_in_old_since_last_gc += bytes; }
@@ -191,37 +129,6 @@
     _max_rs_lengths = rs_lengths;
   }
 
-  size_t predict_rs_length_diff() const;
-
-  double predict_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_young_card_num(size_t rs_length) const;
-
-  size_t predict_non_young_card_num(size_t rs_length) const;
-
-  double predict_rs_scan_time_ms(size_t card_num) 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) 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_base_elapsed_time_ms(size_t pending_cards) const;
   double predict_base_elapsed_time_ms(size_t pending_cards,
@@ -229,13 +136,6 @@
   size_t predict_bytes_to_copy(HeapRegion* hr) const;
   double predict_region_elapsed_time_ms(HeapRegion* hr, bool for_young_gc) const;
 
-  void set_recorded_rs_lengths(size_t rs_lengths);
-
-  uint cset_region_length() const       { return young_cset_region_length() +
-                                           old_cset_region_length(); }
-  uint young_cset_region_length() const { return eden_cset_region_length() +
-                                           survivor_cset_region_length(); }
-
   double predict_survivor_regions_evac_time() const;
 
   bool should_update_surv_rate_group_predictors() {
@@ -261,10 +161,6 @@
     return _mmu_tracker->max_gc_time() * 1000.0;
   }
 
-  double predict_remark_time_ms() const;
-
-  double predict_cleanup_time_ms() const;
-
   // Returns an estimate of the survival rate of the region at yg-age
   // "yg_age".
   double predict_yg_surv_rate(int age, SurvRateGroup* surv_rate_group) const;
@@ -273,7 +169,23 @@
 
   double accum_yg_surv_rate_pred(int age) const;
 
+  // When copying, we will likely need more bytes free than is live in the region.
+  // Add some safety margin to factor in the confidence of our guess, and the
+  // natural expected waste.
+  // (100.0 / G1ConfidencePercent) is a scale factor that expresses the uncertainty
+  // of the calculation: the lower the confidence, the more headroom.
+  // (100 + TargetPLABWastePct) represents the increase in expected bytes during
+  // copying due to anticipated waste in the PLABs.
+  double safety_factor() const {
+    return (100.0 / G1ConfidencePercent) * (100 + TargetPLABWastePct) / 100.0;
+  }
+
+  // Returns an estimate of the available bytes at end of collection, adjusted by
+  // the safety factor.
+  size_t available_bytes_estimate();
+
 protected:
+  G1CollectionSet* _collection_set;
   virtual double average_time_ms(G1GCPhaseTimes::GCParPhases phase) const;
   virtual double other_time_ms(double pause_time_ms) const;
 
@@ -281,90 +193,17 @@
   double non_young_other_time_ms() const;
   double constant_other_time_ms(double pause_time_ms) const;
 
-  CollectionSetChooser* cset_chooser() const {
-    return _cset_chooser;
-  }
-
+  CollectionSetChooser* cset_chooser() const;
 private:
-  // Statistics kept per GC stoppage, pause or full.
-  TruncatedSeq* _recent_prev_end_times_for_all_gcs_sec;
-
-  // 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);
-
-  // The head of the list (via "next_in_collection_set()") representing the
-  // current collection set. Set from the incrementally built collection
-  // set at the start of the pause.
-  HeapRegion* _collection_set;
-
-  // The number of bytes in the collection set before the pause. Set from
-  // the incrementally built collection set at the start of an evacuation
-  // pause, and incremented in finalize_old_cset_part() when adding old regions
-  // (if any) to the collection set.
-  size_t _collection_set_bytes_used_before;
 
   // The number of bytes copied during the GC.
   size_t _bytes_copied_during_gc;
 
-  // The associated information that is maintained while the incremental
-  // collection set is being built with young regions. Used to populate
-  // the recorded info for the evacuation pause.
-
-  enum CSetBuildType {
-    Active,             // We are actively building the collection set
-    Inactive            // We are not actively building the collection set
-  };
-
-  CSetBuildType _inc_cset_build_state;
-
-  // The head of the incrementally built collection set.
-  HeapRegion* _inc_cset_head;
-
-  // The tail of the incrementally built collection set.
-  HeapRegion* _inc_cset_tail;
-
-  // The number of bytes in the incrementally built collection set.
-  // Used to set _collection_set_bytes_used_before at the start of
-  // an evacuation pause.
-  size_t _inc_cset_bytes_used_before;
-
-  // The RSet lengths recorded for regions in the CSet. It is updated
-  // by the thread that adds a new region to the CSet. We assume that
-  // only one thread can be allocating a new CSet region (currently,
-  // it does so after taking the Heap_lock) hence no need to
-  // synchronize updates to this field.
-  size_t _inc_cset_recorded_rs_lengths;
-
-  // A concurrent refinement thread periodically samples the young
-  // region RSets and needs to update _inc_cset_recorded_rs_lengths as
-  // the RSets grow. Instead of having to synchronize updates to that
-  // field we accumulate them in this field and add it to
-  // _inc_cset_recorded_rs_lengths_diffs at the start of a GC.
-  ssize_t _inc_cset_recorded_rs_lengths_diffs;
-
-  // The predicted elapsed time it will take to collect the regions in
-  // the CSet. This is updated by the thread that adds a new region to
-  // the CSet. See the comment for _inc_cset_recorded_rs_lengths about
-  // MT-safety assumptions.
-  double _inc_cset_predicted_elapsed_time_ms;
-
-  // See the comment for _inc_cset_recorded_rs_lengths_diffs.
-  double _inc_cset_predicted_elapsed_time_ms_diffs;
-
   // Stash a pointer to the g1 heap.
   G1CollectedHeap* _g1;
 
   G1GCPhaseTimes* _phase_times;
 
-  // 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 recent_avg_pause_time_ratio() const {
-    return _recent_avg_pause_time_ratio;
-  }
-
   // This set of variables tracks the collector efficiency, in order to
   // determine whether we should initiate a new marking.
   double _mark_remark_start_sec;
@@ -412,10 +251,6 @@
   void update_rs_lengths_prediction();
   void update_rs_lengths_prediction(size_t prediction);
 
-  // Calculate and return chunk size (in number of regions) for parallel
-  // concurrent mark cleanup.
-  uint calculate_parallel_work_chunk_size(uint n_workers, uint n_regions) const;
-
   // Check whether a given young length (young_length) fits into the
   // given target pause time and whether the prediction for the amount
   // of objects to be copied for the given length will fit into the
@@ -424,6 +259,9 @@
   bool predict_will_fit(uint young_length, double base_time_ms,
                         uint base_free_regions, double target_pause_time_ms) const;
 
+public:
+  size_t pending_cards() const { return _pending_cards; }
+
   // Calculate the minimum number of old regions we'll add to the CSet
   // during a mixed GC.
   uint calc_min_old_cset_length() const;
@@ -436,6 +274,7 @@
   // as a percentage of the current heap capacity.
   double reclaimable_bytes_perc(size_t reclaimable_bytes) const;
 
+private:
   // Sets up marking if proper conditions are met.
   void maybe_start_marking();
 
@@ -520,83 +359,20 @@
     return _bytes_copied_during_gc;
   }
 
-  size_t collection_set_bytes_used_before() const {
-    return _collection_set_bytes_used_before;
-  }
-
   // Determine whether there are candidate regions so that the
   // next GC should be mixed. The two action strings are used
   // in the ergo output when the method returns true or false.
   bool next_gc_should_be_mixed(const char* true_action_str,
                                const char* false_action_str) const;
 
-  // Choose a new collection set.  Marks the chosen regions as being
-  // "in_collection_set", and links them together.  The head and number of
-  // the collection set are available via access methods.
-  double finalize_young_cset_part(double target_pause_time_ms);
-  virtual void finalize_old_cset_part(double time_remaining_ms);
-
-  // The head of the list (via "next_in_collection_set()") representing the
-  // current collection set.
-  HeapRegion* collection_set() { return _collection_set; }
-
-  void clear_collection_set() { _collection_set = NULL; }
-
-  // Add old region "hr" to the CSet.
-  void add_old_region_to_cset(HeapRegion* hr);
-
-  // Incremental CSet Support
-
-  // The head of the incrementally built collection set.
-  HeapRegion* inc_cset_head() { return _inc_cset_head; }
-
-  // The tail of the incrementally built collection set.
-  HeapRegion* inc_set_tail() { return _inc_cset_tail; }
-
-  // Initialize incremental collection set info.
-  void start_incremental_cset_building();
-
-  // Perform any final calculations on the incremental CSet fields
-  // before we can use them.
-  void finalize_incremental_cset_building();
-
-  void clear_incremental_cset() {
-    _inc_cset_head = NULL;
-    _inc_cset_tail = NULL;
-  }
-
-  // Stop adding regions to the incremental collection set
-  void stop_incremental_cset_building() { _inc_cset_build_state = Inactive; }
-
-  // Add information about hr to the aggregated information for the
-  // incrementally built collection set.
-  void add_to_incremental_cset_info(HeapRegion* hr, size_t rs_length);
-
-  // Update information about hr in the aggregated information for
-  // the incrementally built collection set.
-  void update_incremental_cset_info(HeapRegion* hr, size_t new_rs_length);
-
+  virtual void finalize_collection_set(double target_pause_time_ms);
 private:
-  // Update the incremental cset information when adding a region
-  // (should not be called directly).
-  void add_region_to_incremental_cset_common(HeapRegion* hr);
-
   // Set the state to start a concurrent marking cycle and clear
   // _initiate_conc_mark_if_possible because it has now been
   // acted on.
   void initiate_conc_mark();
 
 public:
-  // Add hr to the LHS of the incremental collection set.
-  void add_region_to_incremental_cset_lhs(HeapRegion* hr);
-
-  // Add hr to the RHS of the incremental collection set.
-  void add_region_to_incremental_cset_rhs(HeapRegion* hr);
-
-#ifndef PRODUCT
-  void print_collection_set(HeapRegion* list_head, outputStream* st);
-#endif // !PRODUCT
-
   // This sets the initiate_conc_mark_if_possible() flag to start a
   // new cycle, as long as we are not already in one. It's best if it
   // is called during a safepoint when the test whether a cycle is in
@@ -611,13 +387,6 @@
   // the initial-mark work and start a marking cycle.
   void decide_on_conc_mark_initiation();
 
-  // If an expansion would be appropriate, because recent GC overhead had
-  // exceeded the desired limit, return an amount to expand by.
-  virtual size_t expansion_amount();
-
-  // Clear ratio tracking data used by expansion_amount().
-  void clear_ratio_check_data();
-
   // Print stats on young survival ratio
   void print_yg_surv_rate_info() const;
 
@@ -627,7 +396,6 @@
     } else {
       _short_lived_surv_rate_group->finished_recalculating_age_indexes();
     }
-    // do that for any other surv rate groups
   }
 
   size_t young_list_target_length() const { return _young_list_target_length; }
@@ -658,16 +426,6 @@
   // The limit on the number of regions allocated for survivors.
   uint _max_survivor_regions;
 
-  // For reporting purposes.
-  // The value of _heap_bytes_before_gc is also used to calculate
-  // the cost of copying.
-
-  // The amount of survivor regions after a collection.
-  uint _recorded_survivor_regions;
-  // List of survivor regions.
-  HeapRegion* _recorded_survivor_head;
-  HeapRegion* _recorded_survivor_tail;
-
   AgeTable _survivors_age_table;
 
 public:
@@ -677,22 +435,6 @@
     return _max_survivor_regions;
   }
 
-  static const uint REGIONS_UNLIMITED = (uint) -1;
-
-  uint max_regions(InCSetState dest) const {
-    switch (dest.value()) {
-      case InCSetState::Young:
-        return _max_survivor_regions;
-      case InCSetState::Old:
-        return REGIONS_UNLIMITED;
-      default:
-        assert(false, "Unknown dest state: " CSETSTATE_FORMAT, dest.value());
-        break;
-    }
-    // keep some compilers happy
-    return 0;
-  }
-
   void note_start_adding_survivor_regions() {
     _survivor_surv_rate_group->start_adding_regions();
   }
@@ -701,18 +443,6 @@
     _survivor_surv_rate_group->stop_adding_regions();
   }
 
-  void record_survivor_regions(uint regions,
-                               HeapRegion* head,
-                               HeapRegion* tail) {
-    _recorded_survivor_regions = regions;
-    _recorded_survivor_head    = head;
-    _recorded_survivor_tail    = tail;
-  }
-
-  uint recorded_survivor_regions() const {
-    return _recorded_survivor_regions;
-  }
-
   void record_age_table(AgeTable* age_table) {
     _survivors_age_table.merge(age_table);
   }
--- a/hotspot/src/share/vm/gc/g1/g1CollectorState.hpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/gc/g1/g1CollectorState.hpp	Wed Mar 23 23:36:29 2016 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 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,8 +25,9 @@
 #ifndef SHARE_VM_GC_G1_G1COLLECTORSTATE_HPP
 #define SHARE_VM_GC_G1_G1COLLECTORSTATE_HPP
 
+#include "gc/g1/g1YCTypes.hpp"
+#include "memory/allocation.hpp"
 #include "utilities/globalDefinitions.hpp"
-#include "gc/g1/g1YCTypes.hpp"
 
 // Various state variables that indicate
 // the phase of the G1 collection.
@@ -71,7 +72,6 @@
   bool _in_marking_window;
   bool _in_marking_window_im;
 
-  bool _concurrent_cycle_started;
   bool _full_collection;
 
   public:
@@ -87,7 +87,6 @@
       _mark_in_progress(false),
       _in_marking_window(false),
       _in_marking_window_im(false),
-      _concurrent_cycle_started(false),
       _full_collection(false) {}
 
   // Setters
@@ -100,7 +99,6 @@
   void set_mark_in_progress(bool v) { _mark_in_progress = v; }
   void set_in_marking_window(bool v) { _in_marking_window = v; }
   void set_in_marking_window_im(bool v) { _in_marking_window_im = v; }
-  void set_concurrent_cycle_started(bool v) { _concurrent_cycle_started = v; }
   void set_full_collection(bool v) { _full_collection = v; }
 
   // Getters
@@ -113,7 +111,6 @@
   bool mark_in_progress() const { return _mark_in_progress; }
   bool in_marking_window() const { return _in_marking_window; }
   bool in_marking_window_im() const { return _in_marking_window_im; }
-  bool concurrent_cycle_started() const { return _concurrent_cycle_started; }
   bool full_collection() const { return _full_collection; }
 
   // Composite booleans (clients worry about flickering)
--- a/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.cpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.cpp	Wed Mar 23 23:36:29 2016 +0100
@@ -120,74 +120,10 @@
   }
   // We need to clear the bitmap on commit, removing any existing information.
   MemRegion mr(G1CollectedHeap::heap()->bottom_addr_for_region(start_region), num_regions * HeapRegion::GrainWords);
-  _bm->clearRange(mr);
+  _bm->clear_range(mr);
 }
 
-// Closure used for clearing the given mark bitmap.
-class ClearBitmapHRClosure : public HeapRegionClosure {
- private:
-  G1ConcurrentMark* _cm;
-  G1CMBitMap* _bitmap;
-  bool _may_yield;      // The closure may yield during iteration. If yielded, abort the iteration.
- public:
-  ClearBitmapHRClosure(G1ConcurrentMark* cm, G1CMBitMap* bitmap, bool may_yield) : HeapRegionClosure(), _cm(cm), _bitmap(bitmap), _may_yield(may_yield) {
-    assert(!may_yield || cm != NULL, "CM must be non-NULL if this closure is expected to yield.");
-  }
-
-  virtual bool doHeapRegion(HeapRegion* r) {
-    size_t const chunk_size_in_words = M / HeapWordSize;
-
-    HeapWord* cur = r->bottom();
-    HeapWord* const end = r->end();
-
-    while (cur < end) {
-      MemRegion mr(cur, MIN2(cur + chunk_size_in_words, end));
-      _bitmap->clearRange(mr);
-
-      cur += chunk_size_in_words;
-
-      // Abort iteration if after yielding the marking has been aborted.
-      if (_may_yield && _cm->do_yield_check() && _cm->has_aborted()) {
-        return true;
-      }
-      // Repeat the asserts from before the start of the closure. We will do them
-      // as asserts here to minimize their overhead on the product. However, we
-      // will have them as guarantees at the beginning / end of the bitmap
-      // clearing to get some checking in the product.
-      assert(!_may_yield || _cm->cmThread()->during_cycle(), "invariant");
-      assert(!_may_yield || !G1CollectedHeap::heap()->collector_state()->mark_in_progress(), "invariant");
-    }
-
-    return false;
-  }
-};
-
-class ParClearNextMarkBitmapTask : public AbstractGangTask {
-  ClearBitmapHRClosure* _cl;
-  HeapRegionClaimer     _hrclaimer;
-  bool                  _suspendible; // If the task is suspendible, workers must join the STS.
-
-public:
-  ParClearNextMarkBitmapTask(ClearBitmapHRClosure *cl, uint n_workers, bool suspendible) :
-      _cl(cl), _suspendible(suspendible), AbstractGangTask("Parallel Clear Bitmap Task"), _hrclaimer(n_workers) {}
-
-  void work(uint worker_id) {
-    SuspendibleThreadSetJoiner sts_join(_suspendible);
-    G1CollectedHeap::heap()->heap_region_par_iterate(_cl, worker_id, &_hrclaimer, true);
-  }
-};
-
-void G1CMBitMap::clearAll() {
-  G1CollectedHeap* g1h = G1CollectedHeap::heap();
-  ClearBitmapHRClosure cl(NULL, this, false /* may_yield */);
-  uint n_workers = g1h->workers()->active_workers();
-  ParClearNextMarkBitmapTask task(&cl, n_workers, false);
-  g1h->workers()->run_task(&task);
-  guarantee(cl.complete(), "Must have completed iteration.");
-  return;
-}
-
-void G1CMBitMap::clearRange(MemRegion mr) {
+void G1CMBitMap::clear_range(MemRegion mr) {
   mr.intersection(MemRegion(_bmStartWord, _bmWordSize));
   assert(!mr.is_empty(), "unexpected empty region");
   // convert address range into offset range
@@ -203,12 +139,12 @@
   // allocate a stack of the requisite depth
   ReservedSpace rs(ReservedSpace::allocation_align_size_up(capacity * sizeof(oop)));
   if (!rs.is_reserved()) {
-    warning("ConcurrentMark MarkStack allocation failure");
+    log_warning(gc)("ConcurrentMark MarkStack allocation failure");
     return false;
   }
   MemTracker::record_virtual_memory_type((address)rs.base(), mtGC);
   if (!_virtual_space.initialize(rs, rs.size())) {
-    warning("ConcurrentMark MarkStack backing store failure");
+    log_warning(gc)("ConcurrentMark MarkStack backing store failure");
     // Release the virtual memory reserved for the marking stack
     rs.release();
     return false;
@@ -441,7 +377,8 @@
   _has_aborted(false),
   _restart_for_overflow(false),
   _concurrent_marking_in_progress(false),
-  _concurrent_phase_status(ConcPhaseNotStarted),
+  _gc_timer_cm(new (ResourceObj::C_HEAP, mtGC) ConcurrentGCTimer()),
+  _gc_tracer_cm(new (ResourceObj::C_HEAP, mtGC) G1OldTracer()),
 
   // _verbose_level set below
 
@@ -478,9 +415,8 @@
   _root_regions.init(_g1h, this);
 
   if (ConcGCThreads > ParallelGCThreads) {
-    warning("Can't have more ConcGCThreads (%u) "
-            "than ParallelGCThreads (%u).",
-            ConcGCThreads, ParallelGCThreads);
+    log_warning(gc)("Can't have more ConcGCThreads (%u) than ParallelGCThreads (%u).",
+                    ConcGCThreads, ParallelGCThreads);
     return;
   }
   if (!FLAG_IS_DEFAULT(ConcGCThreads) && ConcGCThreads > 0) {
@@ -534,9 +470,9 @@
     // Verify that the calculated value for MarkStackSize is in range.
     // It would be nice to use the private utility routine from Arguments.
     if (!(mark_stack_size >= 1 && mark_stack_size <= MarkStackSizeMax)) {
-      warning("Invalid value calculated for MarkStackSize (" SIZE_FORMAT "): "
-              "must be between 1 and " SIZE_FORMAT,
-              mark_stack_size, MarkStackSizeMax);
+      log_warning(gc)("Invalid value calculated for MarkStackSize (" SIZE_FORMAT "): "
+                      "must be between 1 and " SIZE_FORMAT,
+                      mark_stack_size, MarkStackSizeMax);
       return;
     }
     FLAG_SET_ERGO(size_t, MarkStackSize, mark_stack_size);
@@ -545,16 +481,16 @@
     if (FLAG_IS_CMDLINE(MarkStackSize)) {
       if (FLAG_IS_DEFAULT(MarkStackSizeMax)) {
         if (!(MarkStackSize >= 1 && MarkStackSize <= MarkStackSizeMax)) {
-          warning("Invalid value specified for MarkStackSize (" SIZE_FORMAT "): "
-                  "must be between 1 and " SIZE_FORMAT,
-                  MarkStackSize, MarkStackSizeMax);
+          log_warning(gc)("Invalid value specified for MarkStackSize (" SIZE_FORMAT "): "
+                          "must be between 1 and " SIZE_FORMAT,
+                          MarkStackSize, MarkStackSizeMax);
           return;
         }
       } else if (FLAG_IS_CMDLINE(MarkStackSizeMax)) {
         if (!(MarkStackSize >= 1 && MarkStackSize <= MarkStackSizeMax)) {
-          warning("Invalid value specified for MarkStackSize (" SIZE_FORMAT ")"
-                  " or for MarkStackSizeMax (" SIZE_FORMAT ")",
-                  MarkStackSize, MarkStackSizeMax);
+          log_warning(gc)("Invalid value specified for MarkStackSize (" SIZE_FORMAT ")"
+                          " or for MarkStackSizeMax (" SIZE_FORMAT ")",
+                          MarkStackSize, MarkStackSizeMax);
           return;
         }
       }
@@ -562,7 +498,7 @@
   }
 
   if (!_markStack.allocate(MarkStackSize)) {
-    warning("Failed to allocate CM marking stack");
+    log_warning(gc)("Failed to allocate CM marking stack");
     return;
   }
 
@@ -698,9 +634,76 @@
   ShouldNotReachHere();
 }
 
-void G1ConcurrentMark::clearNextBitmap() {
-  G1CollectedHeap* g1h = G1CollectedHeap::heap();
-
+class G1ClearBitMapTask : public AbstractGangTask {
+  // Heap region closure used for clearing the given mark bitmap.
+  class G1ClearBitmapHRClosure : public HeapRegionClosure {
+  private:
+    G1CMBitMap* _bitmap;
+    G1ConcurrentMark* _cm;
+  public:
+    G1ClearBitmapHRClosure(G1CMBitMap* bitmap, G1ConcurrentMark* cm) : HeapRegionClosure(), _cm(cm), _bitmap(bitmap) {
+    }
+
+    virtual bool doHeapRegion(HeapRegion* r) {
+      size_t const chunk_size_in_words = M / HeapWordSize;
+
+      HeapWord* cur = r->bottom();
+      HeapWord* const end = r->end();
+
+      while (cur < end) {
+        MemRegion mr(cur, MIN2(cur + chunk_size_in_words, end));
+        _bitmap->clear_range(mr);
+
+        cur += chunk_size_in_words;
+
+        // Abort iteration if after yielding the marking has been aborted.
+        if (_cm != NULL && _cm->do_yield_check() && _cm->has_aborted()) {
+          return true;
+        }
+        // Repeat the asserts from before the start of the closure. We will do them
+        // as asserts here to minimize their overhead on the product. However, we
+        // will have them as guarantees at the beginning / end of the bitmap
+        // clearing to get some checking in the product.
+        assert(_cm == NULL || _cm->cmThread()->during_cycle(), "invariant");
+        assert(_cm == NULL || !G1CollectedHeap::heap()->collector_state()->mark_in_progress(), "invariant");
+      }
+      assert(cur == end, "Must have completed iteration over the bitmap for region %u.", r->hrm_index());
+
+      return false;
+    }
+  };
+
+  G1ClearBitmapHRClosure _cl;
+  HeapRegionClaimer _hr_claimer;
+  bool _suspendible; // If the task is suspendible, workers must join the STS.
+
+public:
+  G1ClearBitMapTask(G1CMBitMap* bitmap, G1ConcurrentMark* cm, uint n_workers, bool suspendible) :
+    AbstractGangTask("Parallel Clear Bitmap Task"),
+    _cl(bitmap, suspendible ? cm : NULL),
+    _hr_claimer(n_workers),
+    _suspendible(suspendible)
+  { }
+
+  void work(uint worker_id) {
+    SuspendibleThreadSetJoiner sts_join(_suspendible);
+    G1CollectedHeap::heap()->heap_region_par_iterate(&_cl, worker_id, &_hr_claimer, true);
+  }
+
+  bool is_complete() {
+    return _cl.complete();
+  }
+};
+
+void G1ConcurrentMark::clear_bitmap(G1CMBitMap* bitmap, WorkGang* workers, bool may_yield) {
+  assert(may_yield || SafepointSynchronize::is_at_safepoint(), "Non-yielding bitmap clear only allowed at safepoint.");
+
+  G1ClearBitMapTask task(bitmap, this, workers->active_workers(), may_yield);
+  workers->run_task(&task);
+  guarantee(!may_yield || task.is_complete(), "Must have completed iteration when not yielding.");
+}
+
+void G1ConcurrentMark::cleanup_for_next_mark() {
   // Make sure that the concurrent mark thread looks to still be in
   // the current cycle.
   guarantee(cmThread()->during_cycle(), "invariant");
@@ -709,21 +712,24 @@
   // marking bitmap and getting it ready for the next cycle. During
   // this time no other cycle can start. So, let's make sure that this
   // is the case.
-  guarantee(!g1h->collector_state()->mark_in_progress(), "invariant");
-
-  ClearBitmapHRClosure cl(this, _nextMarkBitMap, true /* may_yield */);
-  ParClearNextMarkBitmapTask task(&cl, parallel_marking_threads(), true);
-  _parallel_workers->run_task(&task);
+  guarantee(!_g1h->collector_state()->mark_in_progress(), "invariant");
+
+  clear_bitmap(_nextMarkBitMap, _parallel_workers, true);
 
   // Clear the liveness counting data. If the marking has been aborted, the abort()
   // call already did that.
-  if (cl.complete()) {
+  if (!has_aborted()) {
     clear_all_count_data();
   }
 
   // Repeat the asserts from above.
   guarantee(cmThread()->during_cycle(), "invariant");
-  guarantee(!g1h->collector_state()->mark_in_progress(), "invariant");
+  guarantee(!_g1h->collector_state()->mark_in_progress(), "invariant");
+}
+
+void G1ConcurrentMark::clear_prev_bitmap(WorkGang* workers) {
+  assert(SafepointSynchronize::is_at_safepoint(), "Should only clear the entire prev bitmap at a safepoint.");
+  clear_bitmap((G1CMBitMap*)_prevMarkBitMap, workers, false);
 }
 
 class CheckBitmapClearHRClosure : public HeapRegionClosure {
@@ -848,7 +854,7 @@
       // marking.
       reset_marking_state(true /* clear_overflow */);
 
-      log_info(gc)("Concurrent Mark reset for overflow");
+      log_info(gc, marking)("Concurrent Mark reset for overflow");
     }
   }
 
@@ -983,13 +989,12 @@
   }
 };
 
-void G1ConcurrentMark::scanRootRegions() {
+void G1ConcurrentMark::scan_root_regions() {
   // scan_in_progress() will have been set to true only if there was
   // at least one root region to scan. So, if it's false, we
   // should not attempt to do any further work.
   if (root_regions()->scan_in_progress()) {
     assert(!has_aborted(), "Aborting before root region scanning is finished not supported.");
-    GCTraceConcTime(Info, gc) tt("Concurrent Root Region Scan");
 
     _parallel_marking_threads = calc_parallel_marking_threads();
     assert(parallel_marking_threads() <= max_parallel_marking_threads(),
@@ -1007,47 +1012,27 @@
   }
 }
 
-void G1ConcurrentMark::register_concurrent_phase_start(const char* title) {
-  uint old_val = 0;
-  do {
-    old_val = Atomic::cmpxchg(ConcPhaseStarted, &_concurrent_phase_status, ConcPhaseNotStarted);
-  } while (old_val != ConcPhaseNotStarted);
-  _g1h->gc_timer_cm()->register_gc_concurrent_start(title);
+void G1ConcurrentMark::concurrent_cycle_start() {
+  _gc_timer_cm->register_gc_start();
+
+  _gc_tracer_cm->report_gc_start(GCCause::_no_gc /* first parameter is not used */, _gc_timer_cm->gc_start());
+
+  _g1h->trace_heap_before_gc(_gc_tracer_cm);
 }
 
-void G1ConcurrentMark::register_concurrent_phase_end_common(bool end_timer) {
-  if (_concurrent_phase_status == ConcPhaseNotStarted) {
-    return;
+void G1ConcurrentMark::concurrent_cycle_end() {
+  _g1h->trace_heap_after_gc(_gc_tracer_cm);
+
+  if (has_aborted()) {
+    _gc_tracer_cm->report_concurrent_mode_failure();
   }
 
-  uint old_val = Atomic::cmpxchg(ConcPhaseStopping, &_concurrent_phase_status, ConcPhaseStarted);
-  if (old_val == ConcPhaseStarted) {
-    _g1h->gc_timer_cm()->register_gc_concurrent_end();
-    // If 'end_timer' is true, we came here to end timer which needs concurrent phase ended.
-    // We need to end it before changing the status to 'ConcPhaseNotStarted' to prevent
-    // starting a new concurrent phase by 'ConcurrentMarkThread'.
-    if (end_timer) {
-      _g1h->gc_timer_cm()->register_gc_end();
-    }
-    old_val = Atomic::cmpxchg(ConcPhaseNotStarted, &_concurrent_phase_status, ConcPhaseStopping);
-    assert(old_val == ConcPhaseStopping, "Should not have changed since we entered this scope.");
-  } else {
-    do {
-      // Let other thread finish changing '_concurrent_phase_status' to 'ConcPhaseNotStarted'.
-      os::naked_short_sleep(1);
-    } while (_concurrent_phase_status != ConcPhaseNotStarted);
-  }
+  _gc_timer_cm->register_gc_end();
+
+  _gc_tracer_cm->report_gc_end(_gc_timer_cm->gc_end(), _gc_timer_cm->time_partitions());
 }
 
-void G1ConcurrentMark::register_concurrent_phase_end() {
-  register_concurrent_phase_end_common(false);
-}
-
-void G1ConcurrentMark::register_concurrent_gc_end_and_stop_timer() {
-  register_concurrent_phase_end_common(true);
-}
-
-void G1ConcurrentMark::markFromRoots() {
+void G1ConcurrentMark::mark_from_roots() {
   // we might be tempted to assert that:
   // assert(asynch == !SafepointSynchronize::is_at_safepoint(),
   //        "inconsistent argument?");
@@ -1110,7 +1095,6 @@
   if (has_overflown()) {
     // Oops.  We overflowed.  Restart concurrent marking.
     _restart_for_overflow = true;
-    log_develop_trace(gc)("Remark led to restart for overflow.");
 
     // Verify the heap w.r.t. the previous marking bitmap.
     if (VerifyDuringGC) {
@@ -1124,7 +1108,7 @@
     reset_marking_state();
   } else {
     {
-      GCTraceTime(Debug, gc) trace("Aggregate Data", g1h->gc_timer_cm());
+      GCTraceTime(Debug, gc, phases) trace("Aggregate Data", _gc_timer_cm);
 
       // Aggregate the per-task counting data that we have accumulated
       // while marking.
@@ -1163,7 +1147,7 @@
   g1p->record_concurrent_mark_remark_end();
 
   G1CMIsAliveClosure is_alive(g1h);
-  g1h->gc_tracer_cm()->report_object_count_after_gc(&is_alive);
+  _gc_tracer_cm->report_object_count_after_gc(&is_alive);
 }
 
 // Base class of the closures that finalize and verify the
@@ -1752,11 +1736,9 @@
   // sure we update the old gen/space data.
   g1h->g1mm()->update_sizes();
   g1h->allocation_context_stats().update_after_mark();
-
-  g1h->trace_heap_after_concurrent_cycle();
 }
 
-void G1ConcurrentMark::completeCleanup() {
+void G1ConcurrentMark::complete_cleanup() {
   if (has_aborted()) return;
 
   G1CollectedHeap* g1h = G1CollectedHeap::heap();
@@ -2045,7 +2027,7 @@
   // Inner scope to exclude the cleaning of the string and symbol
   // tables from the displayed time.
   {
-    GCTraceTime(Debug, gc) trace("Reference Processing", g1h->gc_timer_cm());
+    GCTraceTime(Debug, gc, phases) trace("Reference Processing", _gc_timer_cm);
 
     ReferenceProcessor* rp = g1h->ref_processor_cm();
 
@@ -2102,8 +2084,8 @@
                                           &g1_keep_alive,
                                           &g1_drain_mark_stack,
                                           executor,
-                                          g1h->gc_timer_cm());
-    g1h->gc_tracer_cm()->report_gc_reference_stats(stats);
+                                          _gc_timer_cm);
+    _gc_tracer_cm->report_gc_reference_stats(stats);
 
     // The do_oop work routines of the keep_alive and drain_marking_stack
     // oop closures will set the has_overflown flag if we overflow the
@@ -2134,28 +2116,24 @@
   assert(_markStack.isEmpty(), "Marking should have completed");
 
   // Unload Klasses, String, Symbols, Code Cache, etc.
-  {
-    GCTraceTime(Debug, gc) trace("Unloading", g1h->gc_timer_cm());
-
-    if (ClassUnloadingWithConcurrentMark) {
-      bool purged_classes;
-
-      {
-        GCTraceTime(Trace, gc) trace("System Dictionary Unloading", g1h->gc_timer_cm());
-        purged_classes = SystemDictionary::do_unloading(&g1_is_alive, false /* Defer klass cleaning */);
-      }
-
-      {
-        GCTraceTime(Trace, gc) trace("Parallel Unloading", g1h->gc_timer_cm());
-        weakRefsWorkParallelPart(&g1_is_alive, purged_classes);
-      }
+  if (ClassUnloadingWithConcurrentMark) {
+    bool purged_classes;
+
+    {
+      GCTraceTime(Debug, gc, phases) trace("System Dictionary Unloading", _gc_timer_cm);
+      purged_classes = SystemDictionary::do_unloading(&g1_is_alive, false /* Defer klass cleaning */);
     }
 
-    if (G1StringDedup::is_enabled()) {
-      GCTraceTime(Trace, gc) trace("String Deduplication Unlink", g1h->gc_timer_cm());
-      G1StringDedup::unlink(&g1_is_alive);
+    {
+      GCTraceTime(Debug, gc, phases) trace("Parallel Unloading", _gc_timer_cm);
+      weakRefsWorkParallelPart(&g1_is_alive, purged_classes);
     }
   }
+
+  if (G1StringDedup::is_enabled()) {
+    GCTraceTime(Debug, gc, phases) trace("String Deduplication Unlink", _gc_timer_cm);
+    G1StringDedup::unlink(&g1_is_alive);
+  }
 }
 
 void G1ConcurrentMark::swapMarkBitMaps() {
@@ -2273,7 +2251,7 @@
   HandleMark   hm;
   G1CollectedHeap* g1h = G1CollectedHeap::heap();
 
-  GCTraceTime(Debug, gc) trace("Finalize Marking", g1h->gc_timer_cm());
+  GCTraceTime(Debug, gc, phases) trace("Finalize Marking", _gc_timer_cm);
 
   g1h->ensure_parsability(false);
 
@@ -2308,7 +2286,7 @@
 void G1ConcurrentMark::clearRangePrevBitmap(MemRegion mr) {
   // Note we are overriding the read-only view of the prev map here, via
   // the cast.
-  ((G1CMBitMap*)_prevMarkBitMap)->clearRange(mr);
+  ((G1CMBitMap*)_prevMarkBitMap)->clear_range(mr);
 }
 
 HeapRegion*
@@ -2605,7 +2583,7 @@
 
   // Clear all marks in the next bitmap for the next marking cycle. This will allow us to skip the next
   // concurrent bitmap clearing.
-  _nextMarkBitMap->clearAll();
+  clear_bitmap(_nextMarkBitMap, _g1h->workers(), false);
 
   // Note we cannot clear the previous marking bitmap here
   // since VerifyDuringGC verifies the objects marked during
@@ -2629,10 +2607,6 @@
   satb_mq_set.set_active_all_threads(
                                  false, /* new active value */
                                  satb_mq_set.is_active() /* expected_active */);
-
-  _g1h->trace_heap_after_concurrent_cycle();
-
-  _g1h->register_concurrent_cycle_end();
 }
 
 static void print_ms_time_info(const char* prefix, const char* name,
@@ -3554,8 +3528,6 @@
 G1PrintRegionLivenessInfoClosure(const char* phase_name)
   : _total_used_bytes(0), _total_capacity_bytes(0),
     _total_prev_live_bytes(0), _total_next_live_bytes(0),
-    _hum_used_bytes(0), _hum_capacity_bytes(0),
-    _hum_prev_live_bytes(0), _hum_next_live_bytes(0),
     _total_remset_bytes(0), _total_strong_code_roots_bytes(0) {
   G1CollectedHeap* g1h = G1CollectedHeap::heap();
   MemRegion g1_reserved = g1h->g1_reserved();
@@ -3595,36 +3567,6 @@
                           "(bytes)", "(bytes)");
 }
 
-// It takes as a parameter a reference to one of the _hum_* fields, it
-// deduces the corresponding value for a region in a humongous region
-// series (either the region size, or what's left if the _hum_* field
-// is < the region size), and updates the _hum_* field accordingly.
-size_t G1PrintRegionLivenessInfoClosure::get_hum_bytes(size_t* hum_bytes) {
-  size_t bytes = 0;
-  // The > 0 check is to deal with the prev and next live bytes which
-  // could be 0.
-  if (*hum_bytes > 0) {
-    bytes = MIN2(HeapRegion::GrainBytes, *hum_bytes);
-    *hum_bytes -= bytes;
-  }
-  return bytes;
-}
-
-// It deduces the values for a region in a humongous region series
-// from the _hum_* fields and updates those accordingly. It assumes
-// that that _hum_* fields have already been set up from the "starts
-// humongous" region and we visit the regions in address order.
-void G1PrintRegionLivenessInfoClosure::get_hum_bytes(size_t* used_bytes,
-                                                     size_t* capacity_bytes,
-                                                     size_t* prev_live_bytes,
-                                                     size_t* next_live_bytes) {
-  assert(_hum_used_bytes > 0 && _hum_capacity_bytes > 0, "pre-condition");
-  *used_bytes      = get_hum_bytes(&_hum_used_bytes);
-  *capacity_bytes  = get_hum_bytes(&_hum_capacity_bytes);
-  *prev_live_bytes = get_hum_bytes(&_hum_prev_live_bytes);
-  *next_live_bytes = get_hum_bytes(&_hum_next_live_bytes);
-}
-
 bool G1PrintRegionLivenessInfoClosure::doHeapRegion(HeapRegion* r) {
   const char* type       = r->get_type_str();
   HeapWord* bottom       = r->bottom();
@@ -3637,24 +3579,6 @@
   size_t remset_bytes    = r->rem_set()->mem_size();
   size_t strong_code_roots_bytes = r->rem_set()->strong_code_roots_mem_size();
 
-  if (r->is_starts_humongous()) {
-    assert(_hum_used_bytes == 0 && _hum_capacity_bytes == 0 &&
-           _hum_prev_live_bytes == 0 && _hum_next_live_bytes == 0,
-           "they should have been zeroed after the last time we used them");
-    // Set up the _hum_* fields.
-    _hum_capacity_bytes  = capacity_bytes;
-    _hum_used_bytes      = used_bytes;
-    _hum_prev_live_bytes = prev_live_bytes;
-    _hum_next_live_bytes = next_live_bytes;
-    get_hum_bytes(&used_bytes, &capacity_bytes,
-                  &prev_live_bytes, &next_live_bytes);
-    end = bottom + HeapRegion::GrainWords;
-  } else if (r->is_continues_humongous()) {
-    get_hum_bytes(&used_bytes, &capacity_bytes,
-                  &prev_live_bytes, &next_live_bytes);
-    assert(end == bottom + HeapRegion::GrainWords, "invariant");
-  }
-
   _total_used_bytes      += used_bytes;
   _total_capacity_bytes  += capacity_bytes;
   _total_prev_live_bytes += prev_live_bytes;
--- a/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.hpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.hpp	Wed Mar 23 23:36:29 2016 +0100
@@ -34,6 +34,8 @@
 class G1CMBitMap;
 class G1CMTask;
 class G1ConcurrentMark;
+class ConcurrentGCTimer;
+class G1OldTracer;
 typedef GenericTaskQueue<oop, mtGC>              G1CMTaskQueue;
 typedef GenericTaskQueueSet<G1CMTaskQueue, mtGC> G1CMTaskQueueSet;
 
@@ -139,10 +141,7 @@
   inline void clear(HeapWord* addr);
   inline bool parMark(HeapWord* addr);
 
-  void clearRange(MemRegion mr);
-
-  // Clear the whole mark bitmap.
-  void clearAll();
+  void clear_range(MemRegion mr);
 };
 
 // Represents a marking stack used by ConcurrentMarking in the G1 collector.
@@ -352,17 +351,9 @@
   // time of remark.
   volatile bool           _concurrent_marking_in_progress;
 
-  // There would be a race between ConcurrentMarkThread and VMThread(ConcurrentMark::abort())
-  // to call ConcurrentGCTimer::register_gc_concurrent_end().
-  // And this variable is used to keep track of concurrent phase.
-  volatile uint           _concurrent_phase_status;
-  // Concurrent phase is not yet started.
-  static const uint       ConcPhaseNotStarted = 0;
-  // Concurrent phase is started.
-  static const uint       ConcPhaseStarted = 1;
-  // Caller thread of ConcurrentGCTimer::register_gc_concurrent_end() is ending concurrent phase.
-  // So other thread should wait until the status to be changed to ConcPhaseNotStarted.
-  static const uint       ConcPhaseStopping = 2;
+  ConcurrentGCTimer*      _gc_timer_cm;
+
+  G1OldTracer*            _gc_tracer_cm;
 
   // All of these times are in ms
   NumberSeq _init_times;
@@ -497,6 +488,9 @@
   // end_timer, true to end gc timer after ending concurrent phase.
   void register_concurrent_phase_end_common(bool end_timer);
 
+  // Clear the given bitmap in parallel using the given WorkGang. If may_yield is
+  // true, periodically insert checks to see if this method should exit prematurely.
+  void clear_bitmap(G1CMBitMap* bitmap, WorkGang* workers, bool may_yield);
 public:
   // Manipulation of the global mark stack.
   // The push and pop operations are used by tasks for transfers
@@ -530,10 +524,8 @@
     _concurrent_marking_in_progress = false;
   }
 
-  void register_concurrent_phase_start(const char* title);
-  void register_concurrent_phase_end();
-  // Ends both concurrent phase and timer.
-  void register_concurrent_gc_end_and_stop_timer();
+  void concurrent_cycle_start();
+  void concurrent_cycle_end();
 
   void update_accum_task_vtime(int i, double vtime) {
     _accum_task_vtime[i] += vtime;
@@ -585,8 +577,13 @@
                        uint worker_id,
                        HeapRegion* hr = NULL);
 
-  // Clear the next marking bitmap (will be called concurrently).
-  void clearNextBitmap();
+  // Prepare internal data structures for the next mark cycle. This includes clearing
+  // the next mark bitmap and some internal data structures. This method is intended
+  // to be called concurrently to the mutator. It will yield to safepoint requests.
+  void cleanup_for_next_mark();
+
+  // Clear the previous marking bitmap during safepoint.
+  void clear_prev_bitmap(WorkGang* workers);
 
   // Return whether the next mark bitmap has no marks set. To be used for assertions
   // only. Will not yield to pause requests.
@@ -603,18 +600,18 @@
 
   // Scan all the root regions and mark everything reachable from
   // them.
-  void scanRootRegions();
+  void scan_root_regions();
 
   // Scan a single root region and mark everything reachable from it.
   void scanRootRegion(HeapRegion* hr, uint worker_id);
 
   // Do concurrent phase of marking, to a tentative transitive closure.
-  void markFromRoots();
+  void mark_from_roots();
 
   void checkpointRootsFinal(bool clear_all_soft_refs);
   void checkpointRootsFinalWork();
   void cleanup();
-  void completeCleanup();
+  void complete_cleanup();
 
   // Mark in the previous bitmap.  NB: this is usually read-only, so use
   // this carefully!
@@ -730,6 +727,9 @@
     return _completed_initialization;
   }
 
+  ConcurrentGCTimer* gc_timer_cm() const { return _gc_timer_cm; }
+  G1OldTracer* gc_tracer_cm() const { return _gc_tracer_cm; }
+
 protected:
   // Clear all the per-task bitmaps and arrays used to store the
   // counting data.
@@ -996,18 +996,6 @@
   size_t _total_prev_live_bytes;
   size_t _total_next_live_bytes;
 
-  // These are set up when we come across a "stars humongous" region
-  // (as this is where most of this information is stored, not in the
-  // subsequent "continues humongous" regions). After that, for every
-  // region in a given humongous region series we deduce the right
-  // values for it by simply subtracting the appropriate amount from
-  // these fields. All these values should reach 0 after we've visited
-  // the last region in the series.
-  size_t _hum_used_bytes;
-  size_t _hum_capacity_bytes;
-  size_t _hum_prev_live_bytes;
-  size_t _hum_next_live_bytes;
-
   // Accumulator for the remembered set size
   size_t _total_remset_bytes;
 
@@ -1026,11 +1014,6 @@
     return (double) val / (double) M;
   }
 
-  // See the .cpp file.
-  size_t get_hum_bytes(size_t* hum_bytes);
-  void get_hum_bytes(size_t* used_bytes, size_t* capacity_bytes,
-                     size_t* prev_live_bytes, size_t* next_live_bytes);
-
 public:
   // The header and footer are printed in the constructor and
   // destructor respectively.
--- a/hotspot/src/share/vm/gc/g1/g1EvacStats.cpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/gc/g1/g1EvacStats.cpp	Wed Mar 23 23:36:29 2016 +0100
@@ -110,15 +110,9 @@
   size_t const cur_plab_sz = (size_t)((double)total_waste_allowed / G1LastPLABAverageOccupancy);
   // Take historical weighted average
   _filter.sample(cur_plab_sz);
-  // Clip from above and below, and align to object boundary
-  size_t plab_sz;
-  plab_sz = MAX2(min_size(), (size_t)_filter.average());
-  plab_sz = MIN2(max_size(), plab_sz);
-  plab_sz = align_object_size(plab_sz);
-  // Latch the result
-  _desired_net_plab_sz = plab_sz;
+  _desired_net_plab_sz = MAX2(min_size(), (size_t)_filter.average());
 
-  log_sizing(cur_plab_sz, plab_sz);
+  log_sizing(cur_plab_sz, _desired_net_plab_sz);
   // Clear accumulators for next round.
   reset();
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/gc/g1/g1HeapSizingPolicy.cpp	Wed Mar 23 23:36:29 2016 +0100
@@ -0,0 +1,157 @@
+/*
+ * 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/g1HeapSizingPolicy.hpp"
+#include "gc/g1/g1Analytics.hpp"
+#include "logging/log.hpp"
+#include "runtime/globals.hpp"
+#include "utilities/debug.hpp"
+#include "utilities/globalDefinitions.hpp"
+
+G1HeapSizingPolicy::G1HeapSizingPolicy(const G1CollectedHeap* g1, const G1Analytics* analytics) :
+      _g1(g1),
+      _analytics(analytics),
+      _num_prev_pauses_for_heuristics(analytics->number_of_recorded_pause_times()) {
+    assert(MinOverThresholdForGrowth < _num_prev_pauses_for_heuristics, "Threshold must be less than %u", _num_prev_pauses_for_heuristics);
+    clear_ratio_check_data();
+  }
+
+void G1HeapSizingPolicy::clear_ratio_check_data() {
+  _ratio_over_threshold_count = 0;
+  _ratio_over_threshold_sum = 0.0;
+  _pauses_since_start = 0;
+}
+
+size_t G1HeapSizingPolicy::expansion_amount() {
+  double recent_gc_overhead = _analytics->recent_avg_pause_time_ratio() * 100.0;
+  double last_gc_overhead = _analytics->last_pause_time_ratio() * 100.0;
+  assert(GCTimeRatio > 0,
+         "we should have set it to a default value set_g1_gc_flags() "
+         "if a user set it to 0");
+  const double gc_overhead_perc = 100.0 * (1.0 / (1.0 + GCTimeRatio));
+
+  double threshold = gc_overhead_perc;
+  size_t expand_bytes = 0;
+
+  // If the heap is at less than half its maximum size, scale the threshold down,
+  // to a limit of 1. Thus the smaller the heap is, the more likely it is to expand,
+  // though the scaling code will likely keep the increase small.
+  if (_g1->capacity() <= _g1->max_capacity() / 2) {
+    threshold *= (double)_g1->capacity() / (double)(_g1->max_capacity() / 2);
+    threshold = MAX2(threshold, 1.0);
+  }
+
+  // If the last GC time ratio is over the threshold, increment the count of
+  // times it has been exceeded, and add this ratio to the sum of exceeded
+  // ratios.
+  if (last_gc_overhead > threshold) {
+    _ratio_over_threshold_count++;
+    _ratio_over_threshold_sum += last_gc_overhead;
+  }
+
+  // Check if we've had enough GC time ratio checks that were over the
+  // threshold to trigger an expansion. We'll also expand if we've
+  // reached the end of the history buffer and the average of all entries
+  // is still over the threshold. This indicates a smaller number of GCs were
+  // long enough to make the average exceed the threshold.
+  bool filled_history_buffer = _pauses_since_start == _num_prev_pauses_for_heuristics;
+  if ((_ratio_over_threshold_count == MinOverThresholdForGrowth) ||
+      (filled_history_buffer && (recent_gc_overhead > threshold))) {
+    size_t min_expand_bytes = HeapRegion::GrainBytes;
+    size_t reserved_bytes = _g1->max_capacity();
+    size_t committed_bytes = _g1->capacity();
+    size_t uncommitted_bytes = reserved_bytes - committed_bytes;
+    size_t expand_bytes_via_pct =
+      uncommitted_bytes * G1ExpandByPercentOfAvailable / 100;
+    double scale_factor = 1.0;
+
+    // If the current size is less than 1/4 of the Initial heap size, expand
+    // by half of the delta between the current and Initial sizes. IE, grow
+    // back quickly.
+    //
+    // Otherwise, take the current size, or G1ExpandByPercentOfAvailable % of
+    // the available expansion space, whichever is smaller, as the base
+    // expansion size. Then possibly scale this size according to how much the
+    // threshold has (on average) been exceeded by. If the delta is small
+    // (less than the StartScaleDownAt value), scale the size down linearly, but
+    // not by less than MinScaleDownFactor. If the delta is large (greater than
+    // the StartScaleUpAt value), scale up, but adding no more than MaxScaleUpFactor
+    // times the base size. The scaling will be linear in the range from
+    // StartScaleUpAt to (StartScaleUpAt + ScaleUpRange). In other words,
+    // ScaleUpRange sets the rate of scaling up.
+    if (committed_bytes < InitialHeapSize / 4) {
+      expand_bytes = (InitialHeapSize - committed_bytes) / 2;
+    } else {
+      double const MinScaleDownFactor = 0.2;
+      double const MaxScaleUpFactor = 2;
+      double const StartScaleDownAt = gc_overhead_perc;
+      double const StartScaleUpAt = gc_overhead_perc * 1.5;
+      double const ScaleUpRange = gc_overhead_perc * 2.0;
+
+      double ratio_delta;
+      if (filled_history_buffer) {
+        ratio_delta = recent_gc_overhead - threshold;
+      } else {
+        ratio_delta = (_ratio_over_threshold_sum/_ratio_over_threshold_count) - threshold;
+      }
+
+      expand_bytes = MIN2(expand_bytes_via_pct, committed_bytes);
+      if (ratio_delta < StartScaleDownAt) {
+        scale_factor = ratio_delta / StartScaleDownAt;
+        scale_factor = MAX2(scale_factor, MinScaleDownFactor);
+      } else if (ratio_delta > StartScaleUpAt) {
+        scale_factor = 1 + ((ratio_delta - StartScaleUpAt) / ScaleUpRange);
+        scale_factor = MIN2(scale_factor, MaxScaleUpFactor);
+      }
+    }
+
+    log_debug(gc, ergo, heap)("Attempt heap expansion (recent GC overhead higher than threshold after GC) "
+                              "recent GC overhead: %1.2f %% threshold: %1.2f %% uncommitted: " SIZE_FORMAT "B base expansion amount and scale: " SIZE_FORMAT "B (%1.2f%%)",
+                              recent_gc_overhead, threshold, uncommitted_bytes, expand_bytes, scale_factor * 100);
+
+    expand_bytes = static_cast<size_t>(expand_bytes * scale_factor);
+
+    // Ensure the expansion size is at least the minimum growth amount
+    // and at most the remaining uncommitted byte size.
+    expand_bytes = MAX2(expand_bytes, min_expand_bytes);
+    expand_bytes = MIN2(expand_bytes, uncommitted_bytes);
+
+    clear_ratio_check_data();
+  } else {
+    // An expansion was not triggered. If we've started counting, increment
+    // the number of checks we've made in the current window.  If we've
+    // reached the end of the window without resizing, clear the counters to
+    // start again the next time we see a ratio above the threshold.
+    if (_ratio_over_threshold_count > 0) {
+      _pauses_since_start++;
+      if (_pauses_since_start > _num_prev_pauses_for_heuristics) {
+        clear_ratio_check_data();
+      }
+    }
+  }
+
+  return expand_bytes;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/gc/g1/g1HeapSizingPolicy.hpp	Wed Mar 23 23:36:29 2016 +0100
@@ -0,0 +1,63 @@
+/*
+ * 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_G1HEAPSIZINGPOLICY_HPP
+#define SHARE_VM_GC_G1_G1HEAPSIZINGPOLICY_HPP
+
+#include "memory/allocation.hpp"
+
+class G1Analytics;
+class G1CollectedHeap;
+
+class G1HeapSizingPolicy: public CHeapObj<mtGC> {
+  // MinOverThresholdForGrowth must be less than the number of recorded
+  // pause times in G1Analytics, representing the minimum number of pause
+  // time ratios that exceed GCTimeRatio before a heap expansion will be triggered.
+  const static uint MinOverThresholdForGrowth = 4;
+
+  const G1CollectedHeap* _g1;
+  const G1Analytics* _analytics;
+
+  const uint _num_prev_pauses_for_heuristics;
+  // Ratio check data for determining if heap growth is necessary.
+  uint _ratio_over_threshold_count;
+  double _ratio_over_threshold_sum;
+  uint _pauses_since_start;
+
+
+protected:
+  G1HeapSizingPolicy(const G1CollectedHeap* g1, const G1Analytics* analytics);
+public:
+
+  // If an expansion would be appropriate, because recent GC overhead had
+  // exceeded the desired limit, return an amount to expand by.
+  virtual size_t expansion_amount();
+
+  // Clear ratio tracking data used by expansion_amount().
+  void clear_ratio_check_data();
+
+  static G1HeapSizingPolicy* create(const G1CollectedHeap* g1, const G1Analytics* analytics);
+};
+
+#endif // SRC_SHARE_VM_GC_G1_G1HEAPSIZINGPOLICY_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/gc/g1/g1HeapSizingPolicy_ext.cpp	Wed Mar 23 23:36:29 2016 +0100
@@ -0,0 +1,30 @@
+/*
+ * 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/g1HeapSizingPolicy.hpp"
+
+G1HeapSizingPolicy* G1HeapSizingPolicy::create(const G1CollectedHeap* g1, const G1Analytics* analytics) {
+  return new G1HeapSizingPolicy(g1, analytics);
+}
--- a/hotspot/src/share/vm/gc/g1/g1HeapTransition.cpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/gc/g1/g1HeapTransition.cpp	Wed Mar 23 23:36:29 2016 +0100
@@ -82,8 +82,8 @@
 void G1HeapTransition::print() {
   Data after(_g1_heap);
 
-  size_t eden_capacity_bytes_after_gc = _g1_heap->g1_policy()->young_list_target_length() - after._survivor_length;
-  size_t survivor_capacity_bytes_after_gc = _g1_heap->g1_policy()->max_survivor_regions();
+  size_t eden_capacity_length_after_gc = _g1_heap->g1_policy()->young_list_target_length() - after._survivor_length;
+  size_t survivor_capacity_length_after_gc = _g1_heap->g1_policy()->max_survivor_regions();
 
   DetailedUsage usage;
   if (log_is_enabled(Trace, gc, heap)) {
@@ -100,11 +100,11 @@
   }
 
   log_info(gc, heap)("Eden regions: " SIZE_FORMAT "->" SIZE_FORMAT "("  SIZE_FORMAT ")",
-                     _before._eden_length, after._eden_length, eden_capacity_bytes_after_gc);
+                     _before._eden_length, after._eden_length, eden_capacity_length_after_gc);
   log_trace(gc, heap)(" Used: 0K, Waste: 0K");
 
   log_info(gc, heap)("Survivor regions: " SIZE_FORMAT "->" SIZE_FORMAT "("  SIZE_FORMAT ")",
-                     _before._survivor_length, after._survivor_length, survivor_capacity_bytes_after_gc);
+                     _before._survivor_length, after._survivor_length, survivor_capacity_length_after_gc);
   log_trace(gc, heap)(" Used: " SIZE_FORMAT "K, Waste: " SIZE_FORMAT "K",
       usage._survivor_used / K, ((after._survivor_length * HeapRegion::GrainBytes) - usage._survivor_used) / K);
 
--- a/hotspot/src/share/vm/gc/g1/g1HotCardCache.cpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/gc/g1/g1HotCardCache.cpp	Wed Mar 23 23:36:29 2016 +0100
@@ -36,7 +36,7 @@
     _use_cache = true;
 
     _hot_cache_size = (size_t)1 << G1ConcRSLogCacheSize;
-    _hot_cache = _hot_cache_memory.allocate(_hot_cache_size);
+    _hot_cache = ArrayAllocator<jbyte*, mtGC>::allocate(_hot_cache_size);
 
     reset_hot_cache_internal();
 
@@ -51,7 +51,7 @@
 G1HotCardCache::~G1HotCardCache() {
   if (default_use_cache()) {
     assert(_hot_cache != NULL, "Logic");
-    _hot_cache_memory.free();
+    ArrayAllocator<jbyte*, mtGC>::free(_hot_cache, _hot_cache_size);
     _hot_cache = NULL;
   }
 }
--- a/hotspot/src/share/vm/gc/g1/g1HotCardCache.hpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/gc/g1/g1HotCardCache.hpp	Wed Mar 23 23:36:29 2016 +0100
@@ -61,7 +61,6 @@
 
   G1CardCounts      _card_counts;
 
-  ArrayAllocator<jbyte*, mtGC> _hot_cache_memory;
 
   // The card cache table
   jbyte**           _hot_cache;
--- a/hotspot/src/share/vm/gc/g1/g1MarkSweep.cpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/gc/g1/g1MarkSweep.cpp	Wed Mar 23 23:36:29 2016 +0100
@@ -122,7 +122,7 @@
 void G1MarkSweep::mark_sweep_phase1(bool& marked_for_unloading,
                                     bool clear_all_softrefs) {
   // Recursively traverse all live objects and mark them
-  GCTraceTime(Trace, gc) tm("Phase 1: Mark live objects", gc_timer());
+  GCTraceTime(Info, gc, phases) tm("Phase 1: Mark live objects", gc_timer());
 
   G1CollectedHeap* g1h = G1CollectedHeap::heap();
 
@@ -137,34 +137,49 @@
                                         &follow_code_closure);
   }
 
-  // Process reference objects found during marking
-  ReferenceProcessor* rp = GenMarkSweep::ref_processor();
-  assert(rp == g1h->ref_processor_stw(), "Sanity");
+  {
+    GCTraceTime(Debug, gc, phases) trace("Reference Processing", gc_timer());
+
+    // Process reference objects found during marking
+    ReferenceProcessor* rp = GenMarkSweep::ref_processor();
+    assert(rp == g1h->ref_processor_stw(), "Sanity");
 
-  rp->setup_policy(clear_all_softrefs);
-  const ReferenceProcessorStats& stats =
-    rp->process_discovered_references(&GenMarkSweep::is_alive,
-                                      &GenMarkSweep::keep_alive,
-                                      &GenMarkSweep::follow_stack_closure,
-                                      NULL,
-                                      gc_timer());
-  gc_tracer()->report_gc_reference_stats(stats);
-
+    rp->setup_policy(clear_all_softrefs);
+    const ReferenceProcessorStats& stats =
+        rp->process_discovered_references(&GenMarkSweep::is_alive,
+                                          &GenMarkSweep::keep_alive,
+                                          &GenMarkSweep::follow_stack_closure,
+                                          NULL,
+                                          gc_timer());
+    gc_tracer()->report_gc_reference_stats(stats);
+  }
 
   // This is the point where the entire marking should have completed.
   assert(GenMarkSweep::_marking_stack.is_empty(), "Marking should have completed");
 
-  // Unload classes and purge the SystemDictionary.
-  bool purged_class = SystemDictionary::do_unloading(&GenMarkSweep::is_alive);
+  {
+    GCTraceTime(Debug, gc, phases) trace("Class Unloading", gc_timer());
 
-  // Unload nmethods.
-  CodeCache::do_unloading(&GenMarkSweep::is_alive, purged_class);
+    // Unload classes and purge the SystemDictionary.
+    bool purged_class = SystemDictionary::do_unloading(&GenMarkSweep::is_alive);
+
+    // Unload nmethods.
+    CodeCache::do_unloading(&GenMarkSweep::is_alive, purged_class);
 
-  // Prune dead klasses from subklass/sibling/implementor lists.
-  Klass::clean_weak_klass_links(&GenMarkSweep::is_alive);
+    // Prune dead klasses from subklass/sibling/implementor lists.
+    Klass::clean_weak_klass_links(&GenMarkSweep::is_alive);
+  }
 
-  // Delete entries for dead interned string and clean up unreferenced symbols in symbol table.
-  g1h->unlink_string_and_symbol_table(&GenMarkSweep::is_alive);
+  {
+    GCTraceTime(Debug, gc, phases) trace("Scrub String and Symbol Tables", gc_timer());
+    // Delete entries for dead interned string and clean up unreferenced symbols in symbol table.
+    g1h->unlink_string_and_symbol_table(&GenMarkSweep::is_alive);
+  }
+
+  if (G1StringDedup::is_enabled()) {
+    GCTraceTime(Debug, gc, phases) trace("String Deduplication Unlink", gc_timer());
+    G1StringDedup::unlink(&GenMarkSweep::is_alive);
+  }
 
   if (VerifyDuringGC) {
     HandleMark hm;  // handle scope
@@ -197,7 +212,7 @@
   // phase2, phase3 and phase4, but the ValidateMarkSweep live oops
   // tracking expects us to do so. See comment under phase4.
 
-  GCTraceTime(Trace, gc) tm("Phase 2: Compute new object addresses", gc_timer());
+  GCTraceTime(Info, gc, phases) tm("Phase 2: Compute new object addresses", gc_timer());
 
   prepare_compaction();
 }
@@ -220,17 +235,11 @@
   }
 };
 
-class G1AlwaysTrueClosure: public BoolObjectClosure {
-public:
-  bool do_object_b(oop p) { return true; }
-};
-static G1AlwaysTrueClosure always_true;
-
 void G1MarkSweep::mark_sweep_phase3() {
   G1CollectedHeap* g1h = G1CollectedHeap::heap();
 
   // Adjust the pointers to reflect the new locations
-  GCTraceTime(Trace, gc) tm("Phase 3: Adjust pointers", gc_timer());
+  GCTraceTime(Info, gc, phases) tm("Phase 3: Adjust pointers", gc_timer());
 
   // Need cleared claim bits for the roots processing
   ClassLoaderDataGraph::clear_claimed_marks();
@@ -248,7 +257,7 @@
 
   // Now adjust pointers in remaining weak roots.  (All of which should
   // have been cleared if they pointed to non-surviving objects.)
-  JNIHandles::weak_oops_do(&always_true, &GenMarkSweep::adjust_pointer_closure);
+  JNIHandles::weak_oops_do(&GenMarkSweep::adjust_pointer_closure);
 
   if (G1StringDedup::is_enabled()) {
     G1StringDedup::oops_do(&GenMarkSweep::adjust_pointer_closure);
@@ -291,7 +300,7 @@
   // to use a higher index (saved from phase2) when verifying perm_gen.
   G1CollectedHeap* g1h = G1CollectedHeap::heap();
 
-  GCTraceTime(Trace, gc) tm("Phase 4: Move objects", gc_timer());
+  GCTraceTime(Info, gc, phases) tm("Phase 4: Move objects", gc_timer());
 
   G1SpaceCompactClosure blk;
   g1h->heap_region_iterate(&blk);
--- a/hotspot/src/share/vm/gc/g1/g1MonitoringSupport.cpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/gc/g1/g1MonitoringSupport.cpp	Wed Mar 23 23:36:29 2016 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 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
@@ -178,7 +178,7 @@
   // of a GC).
 
   uint young_list_length = g1->young_list()->length();
-  uint survivor_list_length = g1->g1_policy()->recorded_survivor_regions();
+  uint survivor_list_length = g1->young_list()->survivor_length();
   assert(young_list_length >= survivor_list_length, "invariant");
   uint eden_list_length = young_list_length - survivor_list_length;
   // Max length includes any potential extensions to the young gen
--- a/hotspot/src/share/vm/gc/g1/g1ParScanThreadState.cpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/gc/g1/g1ParScanThreadState.cpp	Wed Mar 23 23:36:29 2016 +0100
@@ -25,6 +25,7 @@
 #include "precompiled.hpp"
 #include "gc/g1/g1Allocator.inline.hpp"
 #include "gc/g1/g1CollectedHeap.inline.hpp"
+#include "gc/g1/g1CollectionSet.hpp"
 #include "gc/g1/g1OopClosures.inline.hpp"
 #include "gc/g1/g1ParScanThreadState.inline.hpp"
 #include "gc/g1/g1RootClosures.hpp"
@@ -80,7 +81,7 @@
   _plab_allocator->flush_and_retire_stats();
   _g1h->g1_policy()->record_age_table(&_age_table);
 
-  uint length = _g1h->g1_policy()->young_cset_region_length();
+  uint length = _g1h->collection_set()->young_region_length();
   for (uint region_index = 0; region_index < length; region_index++) {
     surviving_young_words[region_index] += _surviving_young_words[region_index];
   }
--- a/hotspot/src/share/vm/gc/g1/g1StringDedup.cpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/gc/g1/g1StringDedup.cpp	Wed Mar 23 23:36:29 2016 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 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
@@ -47,7 +47,7 @@
 
 void G1StringDedup::stop() {
   assert(is_enabled(), "String deduplication not enabled");
-  G1StringDedupThread::stop();
+  G1StringDedupThread::thread()->stop();
 }
 
 bool G1StringDedup::is_candidate_from_mark(oop obj) {
--- a/hotspot/src/share/vm/gc/g1/g1StringDedupThread.cpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/gc/g1/g1StringDedupThread.cpp	Wed Mar 23 23:36:29 2016 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 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
@@ -81,11 +81,9 @@
   StringTable::shared_oops_do(&sharedStringDedup);
 }
 
-void G1StringDedupThread::run() {
+void G1StringDedupThread::run_service() {
   G1StringDedupStat total_stat;
 
-  initialize_in_thread();
-  wait_for_universe_init();
   deduplicate_shared_strings(total_stat);
 
   // Main loop
@@ -96,7 +94,7 @@
 
     // Wait for the queue to become non-empty
     G1StringDedupQueue::wait();
-    if (_should_terminate) {
+    if (should_terminate()) {
       break;
     }
 
@@ -133,23 +131,10 @@
     }
   }
 
-  terminate();
 }
 
-void G1StringDedupThread::stop() {
-  {
-    MonitorLockerEx ml(Terminator_lock);
-    _thread->_should_terminate = true;
-  }
-
+void G1StringDedupThread::stop_service() {
   G1StringDedupQueue::cancel_wait();
-
-  {
-    MonitorLockerEx ml(Terminator_lock);
-    while (!_thread->_has_terminated) {
-      ml.wait();
-    }
-  }
 }
 
 void G1StringDedupThread::print(const G1StringDedupStat& last_stat, const G1StringDedupStat& total_stat) {
--- a/hotspot/src/share/vm/gc/g1/g1StringDedupThread.hpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/gc/g1/g1StringDedupThread.hpp	Wed Mar 23 23:36:29 2016 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 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
@@ -45,14 +45,14 @@
 
   void print(const G1StringDedupStat& last_stat, const G1StringDedupStat& total_stat);
 
+  void run_service();
+  void stop_service();
+
 public:
   static void create();
-  static void stop();
 
   static G1StringDedupThread* thread();
 
-  virtual void run();
-
   void deduplicate_shared_strings(G1StringDedupStat& stat);
 };
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/gc/g1/g1YoungGenSizer.cpp	Wed Mar 23 23:36:29 2016 +0100
@@ -0,0 +1,122 @@
+/*
+ * 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/g1YoungGenSizer.hpp"
+#include "gc/g1/heapRegion.hpp"
+
+G1YoungGenSizer::G1YoungGenSizer() : _sizer_kind(SizerDefaults), _adaptive_size(true),
+        _min_desired_young_length(0), _max_desired_young_length(0) {
+  if (FLAG_IS_CMDLINE(NewRatio)) {
+    if (FLAG_IS_CMDLINE(NewSize) || FLAG_IS_CMDLINE(MaxNewSize)) {
+      warning("-XX:NewSize and -XX:MaxNewSize override -XX:NewRatio");
+    } else {
+      _sizer_kind = SizerNewRatio;
+      _adaptive_size = false;
+      return;
+    }
+  }
+
+  if (NewSize > MaxNewSize) {
+    if (FLAG_IS_CMDLINE(MaxNewSize)) {
+      warning("NewSize (" SIZE_FORMAT "k) is greater than the MaxNewSize (" SIZE_FORMAT "k). "
+              "A new max generation size of " SIZE_FORMAT "k will be used.",
+              NewSize/K, MaxNewSize/K, NewSize/K);
+    }
+    MaxNewSize = NewSize;
+  }
+
+  if (FLAG_IS_CMDLINE(NewSize)) {
+    _min_desired_young_length = MAX2((uint) (NewSize / HeapRegion::GrainBytes),
+                                     1U);
+    if (FLAG_IS_CMDLINE(MaxNewSize)) {
+      _max_desired_young_length =
+                             MAX2((uint) (MaxNewSize / HeapRegion::GrainBytes),
+                                  1U);
+      _sizer_kind = SizerMaxAndNewSize;
+      _adaptive_size = _min_desired_young_length == _max_desired_young_length;
+    } else {
+      _sizer_kind = SizerNewSizeOnly;
+    }
+  } else if (FLAG_IS_CMDLINE(MaxNewSize)) {
+    _max_desired_young_length =
+                             MAX2((uint) (MaxNewSize / HeapRegion::GrainBytes),
+                                  1U);
+    _sizer_kind = SizerMaxNewSizeOnly;
+  }
+}
+
+uint G1YoungGenSizer::calculate_default_min_length(uint new_number_of_heap_regions) {
+  uint default_value = (new_number_of_heap_regions * G1NewSizePercent) / 100;
+  return MAX2(1U, default_value);
+}
+
+uint G1YoungGenSizer::calculate_default_max_length(uint new_number_of_heap_regions) {
+  uint default_value = (new_number_of_heap_regions * G1MaxNewSizePercent) / 100;
+  return MAX2(1U, default_value);
+}
+
+void G1YoungGenSizer::recalculate_min_max_young_length(uint number_of_heap_regions, uint* min_young_length, uint* max_young_length) {
+  assert(number_of_heap_regions > 0, "Heap must be initialized");
+
+  switch (_sizer_kind) {
+    case SizerDefaults:
+      *min_young_length = calculate_default_min_length(number_of_heap_regions);
+      *max_young_length = calculate_default_max_length(number_of_heap_regions);
+      break;
+    case SizerNewSizeOnly:
+      *max_young_length = calculate_default_max_length(number_of_heap_regions);
+      *max_young_length = MAX2(*min_young_length, *max_young_length);
+      break;
+    case SizerMaxNewSizeOnly:
+      *min_young_length = calculate_default_min_length(number_of_heap_regions);
+      *min_young_length = MIN2(*min_young_length, *max_young_length);
+      break;
+    case SizerMaxAndNewSize:
+      // Do nothing. Values set on the command line, don't update them at runtime.
+      break;
+    case SizerNewRatio:
+      *min_young_length = number_of_heap_regions / (NewRatio + 1);
+      *max_young_length = *min_young_length;
+      break;
+    default:
+      ShouldNotReachHere();
+  }
+
+  assert(*min_young_length <= *max_young_length, "Invalid min/max young gen size values");
+}
+
+uint G1YoungGenSizer::max_young_length(uint number_of_heap_regions) {
+  // We need to pass the desired values because recalculation may not update these
+  // values in some cases.
+  uint temp = _min_desired_young_length;
+  uint result = _max_desired_young_length;
+  recalculate_min_max_young_length(number_of_heap_regions, &temp, &result);
+  return result;
+}
+
+void G1YoungGenSizer::heap_size_changed(uint new_number_of_heap_regions) {
+  recalculate_min_max_young_length(new_number_of_heap_regions, &_min_desired_young_length,
+          &_max_desired_young_length);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/gc/g1/g1YoungGenSizer.hpp	Wed Mar 23 23:36:29 2016 +0100
@@ -0,0 +1,101 @@
+/*
+ * 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 "memory/allocation.hpp"
+
+// There are three command line options related to the young gen size:
+// NewSize, MaxNewSize and NewRatio (There is also -Xmn, but that is
+// just a short form for NewSize==MaxNewSize). G1 will use its internal
+// heuristics to calculate the actual young gen size, so these options
+// basically only limit the range within which G1 can pick a young gen
+// size. Also, these are general options taking byte sizes. G1 will
+// internally work with a number of regions instead. So, some rounding
+// will occur.
+//
+// If nothing related to the the young gen size is set on the command
+// line we should allow the young gen to be between G1NewSizePercent
+// and G1MaxNewSizePercent of the heap size. This means that every time
+// the heap size changes, the limits for the young gen size will be
+// recalculated.
+//
+// If only -XX:NewSize is set we should use the specified value as the
+// minimum size for young gen. Still using G1MaxNewSizePercent of the
+// heap as maximum.
+//
+// If only -XX:MaxNewSize is set we should use the specified value as the
+// maximum size for young gen. Still using G1NewSizePercent of the heap
+// as minimum.
+//
+// If -XX:NewSize and -XX:MaxNewSize are both specified we use these values.
+// No updates when the heap size changes. There is a special case when
+// NewSize==MaxNewSize. This is interpreted as "fixed" and will use a
+// different heuristic for calculating the collection set when we do mixed
+// collection.
+//
+// If only -XX:NewRatio is set we should use the specified ratio of the heap
+// as both min and max. This will be interpreted as "fixed" just like the
+// NewSize==MaxNewSize case above. But we will update the min and max
+// every time the heap size changes.
+//
+// NewSize and MaxNewSize override NewRatio. So, NewRatio is ignored if it is
+// combined with either NewSize or MaxNewSize. (A warning message is printed.)
+class G1YoungGenSizer : public CHeapObj<mtGC> {
+private:
+  enum SizerKind {
+    SizerDefaults,
+    SizerNewSizeOnly,
+    SizerMaxNewSizeOnly,
+    SizerMaxAndNewSize,
+    SizerNewRatio
+  };
+  SizerKind _sizer_kind;
+  uint _min_desired_young_length;
+  uint _max_desired_young_length;
+  bool _adaptive_size;
+  uint calculate_default_min_length(uint new_number_of_heap_regions);
+  uint calculate_default_max_length(uint new_number_of_heap_regions);
+
+  // Update the given values for minimum and maximum young gen length in regions
+  // given the number of heap regions depending on the kind of sizing algorithm.
+  void recalculate_min_max_young_length(uint number_of_heap_regions, uint* min_young_length, uint* max_young_length);
+
+public:
+  G1YoungGenSizer();
+  // Calculate the maximum length of the young gen given the number of regions
+  // depending on the sizing algorithm.
+  uint max_young_length(uint number_of_heap_regions);
+
+  void heap_size_changed(uint new_number_of_heap_regions);
+  uint min_desired_young_length() {
+    return _min_desired_young_length;
+  }
+  uint max_desired_young_length() {
+    return _max_desired_young_length;
+  }
+
+  bool adaptive_young_list_length() const {
+    return _adaptive_size;
+  }
+};
+
--- a/hotspot/src/share/vm/gc/g1/g1YoungRemSetSamplingThread.cpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/gc/g1/g1YoungRemSetSamplingThread.cpp	Wed Mar 23 23:36:29 2016 +0100
@@ -25,38 +25,13 @@
 #include "precompiled.hpp"
 #include "gc/g1/g1CollectedHeap.inline.hpp"
 #include "gc/g1/g1CollectorPolicy.hpp"
+#include "gc/g1/g1CollectionSet.hpp"
 #include "gc/g1/g1YoungRemSetSamplingThread.hpp"
 #include "gc/g1/heapRegion.inline.hpp"
 #include "gc/g1/heapRegionRemSet.hpp"
 #include "gc/g1/suspendibleThreadSet.hpp"
 #include "runtime/mutexLocker.hpp"
 
-void G1YoungRemSetSamplingThread::run() {
-  initialize_in_thread();
-  wait_for_universe_init();
-
-  run_service();
-
-  terminate();
-}
-
-void G1YoungRemSetSamplingThread::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();
-    }
-  }
-}
-
 G1YoungRemSetSamplingThread::G1YoungRemSetSamplingThread() :
     ConcurrentGCThread(),
     _monitor(Mutex::nonleaf,
@@ -69,7 +44,7 @@
 
 void G1YoungRemSetSamplingThread::sleep_before_next_cycle() {
   MutexLockerEx x(&_monitor, Mutex::_no_safepoint_check_flag);
-  if (!_should_terminate) {
+  if (!should_terminate()) {
     uintx waitms = G1ConcRefinementServiceIntervalMillis; // 300, really should be?
     _monitor.wait(Mutex::_no_safepoint_check_flag, waitms);
   }
@@ -78,7 +53,7 @@
 void G1YoungRemSetSamplingThread::run_service() {
   double vtime_start = os::elapsedVTime();
 
-  while (!_should_terminate) {
+  while (!should_terminate()) {
     sample_young_list_rs_lengths();
 
     if (os::supports_vtime()) {
@@ -114,7 +89,7 @@
       // retired as the current allocation region).
       if (hr->in_collection_set()) {
         // Update the collection set policy information for this region
-        g1p->update_incremental_cset_info(hr, rs_length);
+        g1h->collection_set()->update_young_region_prediction(hr, rs_length);
       }
 
       ++regions_visited;
--- a/hotspot/src/share/vm/gc/g1/g1YoungRemSetSamplingThread.hpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/gc/g1/g1YoungRemSetSamplingThread.hpp	Wed Mar 23 23:36:29 2016 +0100
@@ -55,9 +55,6 @@
 public:
   G1YoungRemSetSamplingThread();
   double vtime_accum() { return _vtime_accum; }
-
-  virtual void run();
-  void stop();
 };
 
 #endif // SHARE_VM_GC_G1_G1YOUNGREMSETSAMPLINGTHREAD_HPP
--- a/hotspot/src/share/vm/gc/g1/g1_globals.hpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/gc/g1/g1_globals.hpp	Wed Mar 23 23:36:29 2016 +0100
@@ -233,10 +233,6 @@
           "Raise a fatal VM exit out of memory failure in the event "       \
           " that heap expansion fails due to running out of swap.")         \
                                                                             \
-  develop(uintx, G1ConcMarkForceOverflow, 0,                                \
-          "The number of times we'll force an overflow during "             \
-          "concurrent marking")                                             \
-                                                                            \
   experimental(uintx, G1MaxNewSizePercent, 60,                              \
           "Percentage (0-100) of the heap size to use as default "          \
           " maximum young gen size.")                                       \
--- a/hotspot/src/share/vm/gc/g1/ptrQueue.cpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/gc/g1/ptrQueue.cpp	Wed Mar 23 23:36:29 2016 +0100
@@ -43,16 +43,12 @@
 
 void PtrQueue::flush_impl() {
   if (!_permanent && _buf != NULL) {
-    if (_index == _sz) {
+    BufferNode* node = BufferNode::make_node_from_buffer(_buf, _index);
+    if (is_empty()) {
       // No work to do.
-      qset()->deallocate_buffer(_buf);
+      qset()->deallocate_buffer(node);
     } else {
-      // We must NULL out the unused entries, then enqueue.
-      size_t limit = byte_index_to_index(_index);
-      for (size_t i = 0; i < limit; ++i) {
-        _buf[i] = NULL;
-      }
-      qset()->enqueue_complete_buffer(_buf);
+      qset()->enqueue_complete_buffer(node);
     }
     _buf = NULL;
     _index = 0;
@@ -74,7 +70,7 @@
   assert(_index <= _sz, "Invariant.");
 }
 
-void PtrQueue::locking_enqueue_completed_buffer(void** buf) {
+void PtrQueue::locking_enqueue_completed_buffer(BufferNode* node) {
   assert(_lock->owned_by_self(), "Required.");
 
   // We have to unlock _lock (which may be Shared_DirtyCardQ_lock) before
@@ -82,7 +78,7 @@
   // have the same rank and we may get the "possible deadlock" message
   _lock->unlock();
 
-  qset()->enqueue_complete_buffer(buf);
+  qset()->enqueue_complete_buffer(node);
   // We must relock only because the caller will unlock, for the normal
   // case.
   _lock->lock_without_safepoint_check();
@@ -157,10 +153,9 @@
   return BufferNode::make_buffer_from_node(node);
 }
 
-void PtrQueueSet::deallocate_buffer(void** buf) {
+void PtrQueueSet::deallocate_buffer(BufferNode* node) {
   assert(_sz > 0, "Didn't set a buffer size.");
   MutexLockerEx x(_fl_owner->_fl_lock, Mutex::_no_safepoint_check_flag);
-  BufferNode *node = BufferNode::make_node_from_buffer(buf);
   node->set_next(_fl_owner->_buf_free_list);
   _fl_owner->_buf_free_list = node;
   _fl_owner->_buf_free_list_sz++;
@@ -211,10 +206,10 @@
       // preventing the subsequent the multiple enqueue, and
       // install a newly allocated buffer below.
 
-      void** buf = _buf;   // local pointer to completed buffer
+      BufferNode* node = BufferNode::make_node_from_buffer(_buf, _index);
       _buf = NULL;         // clear shared _buf field
 
-      locking_enqueue_completed_buffer(buf);  // enqueue completed buffer
+      locking_enqueue_completed_buffer(node); // enqueue completed buffer
 
       // While the current thread was enqueueing the buffer another thread
       // may have a allocated a new buffer and inserted it into this pointer
@@ -224,9 +219,11 @@
 
       if (_buf != NULL) return;
     } else {
-      if (qset()->process_or_enqueue_complete_buffer(_buf)) {
+      BufferNode* node = BufferNode::make_node_from_buffer(_buf, _index);
+      if (qset()->process_or_enqueue_complete_buffer(node)) {
         // Recycle the buffer. No allocation.
-        _sz = qset()->buffer_size();
+        assert(_buf == BufferNode::make_buffer_from_node(node), "invariant");
+        assert(_sz == qset()->buffer_size(), "invariant");
         _index = _sz;
         return;
       }
@@ -238,12 +235,12 @@
   _index = _sz;
 }
 
-bool PtrQueueSet::process_or_enqueue_complete_buffer(void** buf) {
+bool PtrQueueSet::process_or_enqueue_complete_buffer(BufferNode* node) {
   if (Thread::current()->is_Java_thread()) {
     // We don't lock. It is fine to be epsilon-precise here.
     if (_max_completed_queue == 0 || _max_completed_queue > 0 &&
         _n_completed_buffers >= _max_completed_queue + _completed_queue_padding) {
-      bool b = mut_process_buffer(buf);
+      bool b = mut_process_buffer(node);
       if (b) {
         // True here means that the buffer hasn't been deallocated and the caller may reuse it.
         return true;
@@ -251,14 +248,12 @@
     }
   }
   // The buffer will be enqueued. The caller will have to get a new one.
-  enqueue_complete_buffer(buf);
+  enqueue_complete_buffer(node);
   return false;
 }
 
-void PtrQueueSet::enqueue_complete_buffer(void** buf, size_t index) {
+void PtrQueueSet::enqueue_complete_buffer(BufferNode* cbn) {
   MutexLockerEx x(_cbl_mon, Mutex::_no_safepoint_check_flag);
-  BufferNode* cbn = BufferNode::make_node_from_buffer(buf);
-  cbn->set_index(index);
   cbn->set_next(NULL);
   if (_completed_buffers_tail == NULL) {
     assert(_completed_buffers_head == NULL, "Well-formedness");
--- a/hotspot/src/share/vm/gc/g1/ptrQueue.hpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/gc/g1/ptrQueue.hpp	Wed Mar 23 23:36:29 2016 +0100
@@ -33,6 +33,7 @@
 // the addresses of modified old-generation objects.  This type supports
 // this operation.
 
+class BufferNode;
 class PtrQueueSet;
 class PtrQueue VALUE_OBJ_CLASS_SPEC {
   friend class VMStructs;
@@ -104,7 +105,7 @@
   // get into an infinite loop).
   virtual bool should_enqueue_buffer() { return true; }
   void handle_zero_index();
-  void locking_enqueue_completed_buffer(void** buf);
+  void locking_enqueue_completed_buffer(BufferNode* node);
 
   void enqueue_known_active(void* ptr);
 
@@ -136,6 +137,10 @@
     return ind / sizeof(void*);
   }
 
+  static size_t index_to_byte_index(size_t ind) {
+    return ind * sizeof(void*);
+  }
+
   // To support compiler.
 
 protected:
@@ -186,10 +191,13 @@
   // Free a BufferNode.
   static void deallocate(BufferNode* node);
 
-  // Return the BufferNode containing the buffer.
-  static BufferNode* make_node_from_buffer(void** buffer) {
-    return reinterpret_cast<BufferNode*>(
-      reinterpret_cast<char*>(buffer) - buffer_offset());
+  // Return the BufferNode containing the buffer, after setting its index.
+  static BufferNode* make_node_from_buffer(void** buffer, size_t index) {
+    BufferNode* node =
+      reinterpret_cast<BufferNode*>(
+        reinterpret_cast<char*>(buffer) - buffer_offset());
+    node->set_index(index);
+    return node;
   }
 
   // Return the buffer for node.
@@ -243,7 +251,7 @@
   // A mutator thread does the the work of processing a buffer.
   // Returns "true" iff the work is complete (and the buffer may be
   // deallocated).
-  virtual bool mut_process_buffer(void** buf) {
+  virtual bool mut_process_buffer(BufferNode* node) {
     ShouldNotReachHere();
     return false;
   }
@@ -267,13 +275,13 @@
 
   // Return an empty buffer to the free list.  The "buf" argument is
   // required to be a pointer to the head of an array of length "_sz".
-  void deallocate_buffer(void** buf);
+  void deallocate_buffer(BufferNode* node);
 
   // Declares that "buf" is a complete buffer.
-  void enqueue_complete_buffer(void** buf, size_t index = 0);
+  void enqueue_complete_buffer(BufferNode* node);
 
   // To be invoked by the mutator.
-  bool process_or_enqueue_complete_buffer(void** buf);
+  bool process_or_enqueue_complete_buffer(BufferNode* node);
 
   bool completed_buffers_exist_dirty() {
     return _n_completed_buffers > 0;
--- a/hotspot/src/share/vm/gc/g1/satbMarkQueue.cpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/gc/g1/satbMarkQueue.cpp	Wed Mar 23 23:36:29 2016 +0100
@@ -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
@@ -100,6 +100,10 @@
   return true;
 }
 
+inline bool retain_entry(const void* entry, G1CollectedHeap* heap) {
+  return requires_marking(entry, heap) && !heap->isMarkedNext((oop)entry);
+}
+
 // This method removes entries from a SATB buffer that will not be
 // useful to the concurrent marking threads.  Entries are retained if
 // they require marking and are not already marked. Retained entries
@@ -114,43 +118,28 @@
     return;
   }
 
-  // Used for sanity checking at the end of the loop.
-  DEBUG_ONLY(size_t entries = 0; size_t retained = 0;)
+  assert(_index <= _sz, "invariant");
 
-  assert(_index <= _sz, "invariant");
-  void** limit = &buf[byte_index_to_index(_index)];
-  void** src = &buf[byte_index_to_index(_sz)];
-  void** dst = src;
-
-  while (limit < src) {
-    DEBUG_ONLY(entries += 1;)
-    --src;
+  // Two-fingered compaction toward the end.
+  void** src = &buf[byte_index_to_index(_index)];
+  void** dst = &buf[byte_index_to_index(_sz)];
+  for ( ; src < dst; ++src) {
+    // Search low to high for an entry to keep.
     void* entry = *src;
-    // NULL the entry so that unused parts of the buffer contain NULLs
-    // at the end. If we are going to retain it we will copy it to its
-    // final place. If we have retained all entries we have visited so
-    // far, we'll just end up copying it to the same place.
-    *src = NULL;
-
-    if (requires_marking(entry, g1h) && !g1h->isMarkedNext((oop)entry)) {
-      --dst;
-      assert(*dst == NULL, "filtering destination should be clear");
-      *dst = entry;
-      DEBUG_ONLY(retained += 1;);
+    if (retain_entry(entry, g1h)) {
+      // Found keeper.  Search high to low for an entry to discard.
+      while (src < --dst) {
+        if (!retain_entry(*dst, g1h)) {
+          *dst = entry;         // Replace discard with keeper.
+          break;
+        }
+      }
+      // If discard search failed (src == dst), the outer loop will also end.
     }
   }
-  size_t new_index = pointer_delta(dst, buf, 1);
-
-#ifdef ASSERT
-  size_t entries_calc = (_sz - _index) / sizeof(void*);
-  assert(entries == entries_calc, "the number of entries we counted "
-         "should match the number of entries we calculated");
-  size_t retained_calc = (_sz - new_index) / sizeof(void*);
-  assert(retained == retained_calc, "the number of retained entries we counted "
-         "should match the number of retained entries we calculated");
-#endif // ASSERT
-
-  _index = new_index;
+  // dst points to the lowest retained entry, or the end of the buffer
+  // if all the entries were filtered out.
+  _index = pointer_delta(dst, buf, 1);
 }
 
 // This method will first apply the above filtering to the buffer. If
@@ -286,19 +275,11 @@
   }
   if (nd != NULL) {
     void **buf = BufferNode::make_buffer_from_node(nd);
-    // Skip over NULL entries at beginning (e.g. push end) of buffer.
-    // Filtering can result in non-full completed buffers; see
-    // should_enqueue_buffer.
-    assert(_sz % sizeof(void*) == 0, "invariant");
-    size_t limit = SATBMarkQueue::byte_index_to_index(_sz);
-    for (size_t i = 0; i < limit; ++i) {
-      if (buf[i] != NULL) {
-        // Found the end of the block of NULLs; process the remainder.
-        cl->do_buffer(buf + i, limit - i);
-        break;
-      }
-    }
-    deallocate_buffer(buf);
+    size_t index = SATBMarkQueue::byte_index_to_index(nd->index());
+    size_t size = SATBMarkQueue::byte_index_to_index(_sz);
+    assert(index <= size, "invariant");
+    cl->do_buffer(buf + index, size - index);
+    deallocate_buffer(nd);
     return true;
   } else {
     return false;
@@ -355,7 +336,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);
   }
   assert(SafepointSynchronize::is_at_safepoint(), "Must be at safepoint.");
   // So we can safely manipulate these queues.
--- a/hotspot/src/share/vm/gc/g1/satbMarkQueue.hpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/gc/g1/satbMarkQueue.hpp	Wed Mar 23 23:36:29 2016 +0100
@@ -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
@@ -115,9 +115,8 @@
 
   // If there exists some completed buffer, pop and process it, and
   // return true.  Otherwise return false.  Processing a buffer
-  // consists of applying the closure to the buffer range starting
-  // with the first non-NULL entry to the end of the buffer; the
-  // leading entries may be NULL due to filtering.
+  // consists of applying the closure to the active range of the
+  // buffer; the leading entries may be excluded due to filtering.
   bool apply_closure_to_completed_buffer(SATBBufferClosure* cl);
 
 #ifndef PRODUCT
--- a/hotspot/src/share/vm/gc/g1/vm_operations_g1.cpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/gc/g1/vm_operations_g1.cpp	Wed Mar 23 23:36:29 2016 +0100
@@ -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
@@ -205,30 +205,18 @@
 }
 
 void VM_CGC_Operation::acquire_pending_list_lock() {
-  assert(_needs_pll, "don't call this otherwise");
-  // The caller may block while communicating
-  // with the SLT thread in order to acquire/release the PLL.
-  SurrogateLockerThread* slt = ConcurrentMarkThread::slt();
-  if (slt != NULL) {
-    slt->manipulatePLL(SurrogateLockerThread::acquirePLL);
-  } else {
-    SurrogateLockerThread::report_missing_slt();
-  }
+  _pending_list_locker.lock();
 }
 
 void VM_CGC_Operation::release_and_notify_pending_list_lock() {
-  assert(_needs_pll, "don't call this otherwise");
-  // The caller may block while communicating
-  // with the SLT thread in order to acquire/release the PLL.
-  ConcurrentMarkThread::slt()->
-    manipulatePLL(SurrogateLockerThread::releaseAndNotifyPLL);
+  _pending_list_locker.unlock();
 }
 
 void VM_CGC_Operation::doit() {
   GCIdMark gc_id_mark(_gc_id);
   GCTraceCPUTime tcpu;
   G1CollectedHeap* g1h = G1CollectedHeap::heap();
-  GCTraceTime(Info, gc) t(_printGCMessage, g1h->gc_timer_cm(), GCCause::_no_gc, true);
+  GCTraceTime(Info, gc) t(_printGCMessage, g1h->concurrent_mark()->gc_timer_cm(), GCCause::_no_gc, true);
   IsGCActiveMark x;
   _cl->do_void();
 }
@@ -236,10 +224,9 @@
 bool VM_CGC_Operation::doit_prologue() {
   // Note the relative order of the locks must match that in
   // VM_GC_Operation::doit_prologue() or deadlocks can occur
-  if (_needs_pll) {
+  if (_needs_pending_list_lock) {
     acquire_pending_list_lock();
   }
-
   Heap_lock->lock();
   return true;
 }
@@ -248,7 +235,7 @@
   // Note the relative order of the unlocks must match that in
   // VM_GC_Operation::doit_epilogue()
   Heap_lock->unlock();
-  if (_needs_pll) {
+  if (_needs_pending_list_lock) {
     release_and_notify_pending_list_lock();
   }
 }
--- a/hotspot/src/share/vm/gc/g1/vm_operations_g1.hpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/gc/g1/vm_operations_g1.hpp	Wed Mar 23 23:36:29 2016 +0100
@@ -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
@@ -27,6 +27,7 @@
 
 #include "gc/g1/g1AllocationContext.hpp"
 #include "gc/shared/gcId.hpp"
+#include "gc/shared/referencePendingListLocker.hpp"
 #include "gc/shared/vmGCOperations.hpp"
 
 // VM_operations for the G1 collector.
@@ -102,10 +103,11 @@
 // Concurrent GC stop-the-world operations such as remark and cleanup;
 // consider sharing these with CMS's counterparts.
 class VM_CGC_Operation: public VM_Operation {
-  VoidClosure* _cl;
-  const char* _printGCMessage;
-  bool _needs_pll;
-  uint _gc_id;
+  VoidClosure*               _cl;
+  const char*                _printGCMessage;
+  bool                       _needs_pending_list_lock;
+  ReferencePendingListLocker _pending_list_locker;
+  uint                       _gc_id;
 
 protected:
   // java.lang.ref.Reference support
@@ -113,8 +115,8 @@
   void release_and_notify_pending_list_lock();
 
 public:
-  VM_CGC_Operation(VoidClosure* cl, const char *printGCMsg, bool needs_pll)
-    : _cl(cl), _printGCMessage(printGCMsg), _needs_pll(needs_pll), _gc_id(GCId::current()) { }
+  VM_CGC_Operation(VoidClosure* cl, const char *printGCMsg, bool needs_pending_list_lock)
+    : _cl(cl), _printGCMessage(printGCMsg), _needs_pending_list_lock(needs_pending_list_lock), _gc_id(GCId::current()) {}
   virtual VMOp_Type type() const { return VMOp_CGC_Operation; }
   virtual void doit();
   virtual bool doit_prologue();
--- a/hotspot/src/share/vm/gc/g1/youngList.cpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/gc/g1/youngList.cpp	Wed Mar 23 23:36:29 2016 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 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
@@ -24,6 +24,7 @@
 
 #include "precompiled.hpp"
 #include "gc/g1/g1CollectedHeap.hpp"
+#include "gc/g1/g1CollectionSet.hpp"
 #include "gc/g1/g1CollectorPolicy.hpp"
 #include "gc/g1/heapRegion.hpp"
 #include "gc/g1/heapRegion.inline.hpp"
@@ -153,7 +154,7 @@
     // The region is a non-empty survivor so let's add it to
     // the incremental collection set for the next evacuation
     // pause.
-    _g1h->g1_policy()->add_region_to_incremental_cset_rhs(curr);
+    _g1h->collection_set()->add_survivor_regions(curr);
     young_index_in_cset += 1;
   }
   assert((uint) young_index_in_cset == _survivor_length, "post-condition");
--- a/hotspot/src/share/vm/gc/parallel/gcTaskThread.cpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/gc/parallel/gcTaskThread.cpp	Wed Mar 23 23:36:29 2016 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 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
@@ -113,8 +113,8 @@
     }
     if (!os::bind_to_processor(processor_id())) {
       DEBUG_ONLY(
-        warning("Couldn't bind GCTaskThread %u to processor %u",
-                      which(), processor_id());
+        log_warning(gc)("Couldn't bind GCTaskThread %u to processor %u",
+                        which(), processor_id());
       )
     }
   }
--- a/hotspot/src/share/vm/gc/parallel/mutableSpace.cpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/gc/parallel/mutableSpace.cpp	Wed Mar 23 23:36:29 2016 +0100
@@ -58,7 +58,7 @@
 }
 
 void MutableSpace::pretouch_pages(MemRegion mr) {
-  os::pretouch_memory((char*)mr.start(), (char*)mr.end());
+  os::pretouch_memory(mr.start(), mr.end());
 }
 
 void MutableSpace::initialize(MemRegion mr,
--- a/hotspot/src/share/vm/gc/parallel/parallelScavengeHeap.cpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/gc/parallel/parallelScavengeHeap.cpp	Wed Mar 23 23:36:29 2016 +0100
@@ -325,8 +325,8 @@
     loop_count++;
     if ((result == NULL) && (QueuedAllocationWarningCount > 0) &&
         (loop_count % QueuedAllocationWarningCount == 0)) {
-      warning("ParallelScavengeHeap::mem_allocate retries %d times \n\t"
-              " size=" SIZE_FORMAT, loop_count, size);
+      log_warning(gc)("ParallelScavengeHeap::mem_allocate retries %d times", loop_count);
+      log_warning(gc)("\tsize=" SIZE_FORMAT, size);
     }
   }
 
--- a/hotspot/src/share/vm/gc/parallel/psMarkSweep.cpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/gc/parallel/psMarkSweep.cpp	Wed Mar 23 23:36:29 2016 +0100
@@ -493,7 +493,7 @@
 
 void PSMarkSweep::mark_sweep_phase1(bool clear_all_softrefs) {
   // Recursively traverse all live objects and mark them
-  GCTraceTime(Trace, gc) tm("Phase 1: Mark live objects", _gc_timer);
+  GCTraceTime(Info, gc, phases) tm("Phase 1: Mark live objects", _gc_timer);
 
   ParallelScavengeHeap* heap = ParallelScavengeHeap::heap();
 
@@ -523,6 +523,8 @@
 
   // Process reference objects found during marking
   {
+    GCTraceTime(Debug, gc, phases) t("Reference Processing", _gc_timer);
+
     ref_processor()->setup_policy(clear_all_softrefs);
     const ReferenceProcessorStats& stats =
       ref_processor()->process_discovered_references(
@@ -533,26 +535,37 @@
   // This is the point where the entire marking should have completed.
   assert(_marking_stack.is_empty(), "Marking should have completed");
 
-  // Unload classes and purge the SystemDictionary.
-  bool purged_class = SystemDictionary::do_unloading(is_alive_closure());
+  {
+    GCTraceTime(Debug, gc, phases) t("Class Unloading", _gc_timer);
+
+    // Unload classes and purge the SystemDictionary.
+    bool purged_class = SystemDictionary::do_unloading(is_alive_closure());
 
-  // Unload nmethods.
-  CodeCache::do_unloading(is_alive_closure(), purged_class);
+    // Unload nmethods.
+    CodeCache::do_unloading(is_alive_closure(), purged_class);
+
+    // Prune dead klasses from subklass/sibling/implementor lists.
+    Klass::clean_weak_klass_links(is_alive_closure());
+  }
 
-  // Prune dead klasses from subklass/sibling/implementor lists.
-  Klass::clean_weak_klass_links(is_alive_closure());
+  {
+    GCTraceTime(Debug, gc, phases) t("Scrub String Table", _gc_timer);
+    // Delete entries for dead interned strings.
+    StringTable::unlink(is_alive_closure());
+  }
 
-  // Delete entries for dead interned strings.
-  StringTable::unlink(is_alive_closure());
+  {
+    GCTraceTime(Debug, gc, phases) t("Scrub Symbol Table", _gc_timer);
+    // Clean up unreferenced symbols in symbol table.
+    SymbolTable::unlink();
+  }
 
-  // Clean up unreferenced symbols in symbol table.
-  SymbolTable::unlink();
   _gc_tracer->report_object_count_after_gc(is_alive_closure());
 }
 
 
 void PSMarkSweep::mark_sweep_phase2() {
-  GCTraceTime(Trace, gc) tm("Phase 2: Compute new object addresses", _gc_timer);
+  GCTraceTime(Info, gc, phases) tm("Phase 2: Compute new object addresses", _gc_timer);
 
   // Now all live objects are marked, compute the new object addresses.
 
@@ -570,16 +583,9 @@
   old_gen->precompact();
 }
 
-// This should be moved to the shared markSweep code!
-class PSAlwaysTrueClosure: public BoolObjectClosure {
-public:
-  bool do_object_b(oop p) { return true; }
-};
-static PSAlwaysTrueClosure always_true;
-
 void PSMarkSweep::mark_sweep_phase3() {
   // Adjust the pointers to reflect the new locations
-  GCTraceTime(Trace, gc) tm("Phase 3: Adjust pointers", _gc_timer);
+  GCTraceTime(Info, gc, phases) tm("Phase 3: Adjust pointers", _gc_timer);
 
   ParallelScavengeHeap* heap = ParallelScavengeHeap::heap();
   PSYoungGen* young_gen = heap->young_gen();
@@ -603,7 +609,7 @@
   // Now adjust pointers in remaining weak roots.  (All of which should
   // have been cleared if they pointed to non-surviving objects.)
   // Global (weak) JNI handles
-  JNIHandles::weak_oops_do(&always_true, adjust_pointer_closure());
+  JNIHandles::weak_oops_do(adjust_pointer_closure());
 
   CodeBlobToOopClosure adjust_from_blobs(adjust_pointer_closure(), CodeBlobToOopClosure::FixRelocations);
   CodeCache::blobs_do(&adjust_from_blobs);
@@ -619,7 +625,7 @@
 
 void PSMarkSweep::mark_sweep_phase4() {
   EventMark m("4 compact heap");
-  GCTraceTime(Trace, gc) tm("Phase 4: Move objects", _gc_timer);
+  GCTraceTime(Info, gc, phases) tm("Phase 4: Move objects", _gc_timer);
 
   // All pointers are now adjusted, move objects accordingly
 
@@ -638,7 +644,7 @@
   jlong ret_val = now - _time_of_last_gc;
   // XXX See note in genCollectedHeap::millis_since_last_gc().
   if (ret_val < 0) {
-    NOT_PRODUCT(warning("time warp: " JLONG_FORMAT, ret_val);)
+    NOT_PRODUCT(log_warning(gc)("time warp: " JLONG_FORMAT, ret_val);)
     return 0;
   }
   return ret_val;
--- a/hotspot/src/share/vm/gc/parallel/psOldGen.cpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/gc/parallel/psOldGen.cpp	Wed Mar 23 23:36:29 2016 +0100
@@ -309,7 +309,7 @@
   const size_t remaining_bytes = virtual_space()->uncommitted_size();
   if (remaining_bytes > 0) {
     result = expand_by(remaining_bytes);
-    DEBUG_ONLY(if (!result) warning("grow to reserve failed"));
+    DEBUG_ONLY(if (!result) log_warning(gc)("grow to reserve failed"));
   }
   return result;
 }
--- a/hotspot/src/share/vm/gc/parallel/psParallelCompact.cpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/gc/parallel/psParallelCompact.cpp	Wed Mar 23 23:36:29 2016 +0100
@@ -195,10 +195,10 @@
 };
 
 void PSParallelCompact::print_region_ranges() {
-  if (!log_develop_is_enabled(Trace, gc, compaction, phases)) {
+  if (!log_develop_is_enabled(Trace, gc, compaction)) {
     return;
   }
-  LogHandle(gc, compaction, phases) log;
+  LogHandle(gc, compaction) log;
   ResourceMark rm;
   Universe::print_on(log.trace_stream());
   log.trace("space  bottom     top        end        new_top");
@@ -225,7 +225,7 @@
 
   ParallelCompactData& sd = PSParallelCompact::summary_data();
   size_t dci = c->destination() ? sd.addr_to_region_idx(c->destination()) : 0;
-  log_develop_trace(gc, compaction, phases)(
+  log_develop_trace(gc, compaction)(
       REGION_IDX_FORMAT " " PTR_FORMAT " "
       REGION_IDX_FORMAT " " PTR_FORMAT " "
       REGION_DATA_FORMAT " " REGION_DATA_FORMAT " "
@@ -258,14 +258,14 @@
     ++i;
   }
 
-  log_develop_trace(gc, compaction, phases)("summary_data_bytes=" SIZE_FORMAT, total_words * HeapWordSize);
+  log_develop_trace(gc, compaction)("summary_data_bytes=" SIZE_FORMAT, total_words * HeapWordSize);
 }
 
 void
 print_generic_summary_data(ParallelCompactData& summary_data,
                            SpaceInfo* space_info)
 {
-  if (!log_develop_is_enabled(Trace, gc, compaction, phases)) {
+  if (!log_develop_is_enabled(Trace, gc, compaction)) {
     return;
   }
 
@@ -296,7 +296,7 @@
   size_t i = summary_data.addr_to_region_idx(space->bottom());
   while (i < end_region && summary_data.region(i)->data_size() == region_size) {
     ParallelCompactData::RegionData* c = summary_data.region(i);
-    log_develop_trace(gc, compaction, phases)(
+    log_develop_trace(gc, compaction)(
         SIZE_FORMAT_W(5) " " PTR_FORMAT " " SIZE_FORMAT_W(5) " " SIZE_FORMAT_W(5) " " SIZE_FORMAT_W(5) " " SIZE_FORMAT_W(5) " %d",
         i, p2i(c->destination()),
         c->partial_obj_size(), c->live_obj_size(),
@@ -330,7 +330,7 @@
     }
 
     ParallelCompactData::RegionData* c = summary_data.region(i);
-    log_develop_trace(gc, compaction, phases)(
+    log_develop_trace(gc, compaction)(
         SIZE_FORMAT_W(5) " " PTR_FORMAT " " SIZE_FORMAT_W(5) " " SIZE_FORMAT_W(5) " " SIZE_FORMAT_W(5) " " SIZE_FORMAT_W(5) " %d"
         "%12.10f " SIZE_FORMAT_W(10) " " SIZE_FORMAT_W(10),
         i, p2i(c->destination()),
@@ -346,21 +346,21 @@
   // Any remaining regions are empty.  Print one more if there is one.
   if (i < end_region) {
     ParallelCompactData::RegionData* c = summary_data.region(i);
-    log_develop_trace(gc, compaction, phases)(
+    log_develop_trace(gc, compaction)(
         SIZE_FORMAT_W(5) " " PTR_FORMAT " " SIZE_FORMAT_W(5) " " SIZE_FORMAT_W(5) " " SIZE_FORMAT_W(5) " " SIZE_FORMAT_W(5) " %d",
          i, p2i(c->destination()),
          c->partial_obj_size(), c->live_obj_size(),
          c->data_size(), c->source_region(), c->destination_count());
   }
 
-  log_develop_trace(gc, compaction, phases)("max:  " SIZE_FORMAT_W(4) " d2r=" SIZE_FORMAT_W(10) " l2r=" SIZE_FORMAT_W(10) " max_ratio=%14.12f",
-                                            max_reclaimed_ratio_region, max_dead_to_right, max_live_to_right, max_reclaimed_ratio);
+  log_develop_trace(gc, compaction)("max:  " SIZE_FORMAT_W(4) " d2r=" SIZE_FORMAT_W(10) " l2r=" SIZE_FORMAT_W(10) " max_ratio=%14.12f",
+                                    max_reclaimed_ratio_region, max_dead_to_right, max_live_to_right, max_reclaimed_ratio);
 }
 
 void
 print_initial_summary_data(ParallelCompactData& summary_data,
                            SpaceInfo* space_info) {
-  if (!log_develop_is_enabled(Trace, gc, compaction, phases)) {
+  if (!log_develop_is_enabled(Trace, gc, compaction)) {
     return;
   }
 
@@ -621,7 +621,7 @@
                                          sr->partial_obj_size()));
     const size_t end_idx = addr_to_region_idx(target_end);
 
-    log_develop_trace(gc, compaction, phases)("split:  clearing source_region field in [" SIZE_FORMAT ", " SIZE_FORMAT ")", beg_idx, end_idx);
+    log_develop_trace(gc, compaction)("split:  clearing source_region field in [" SIZE_FORMAT ", " SIZE_FORMAT ")", beg_idx, end_idx);
     for (size_t idx = beg_idx; idx < end_idx; ++idx) {
       _region_data[idx].set_source_region(0);
     }
@@ -641,22 +641,22 @@
   *target_next = split_destination + partial_obj_size;
   HeapWord* const source_next = region_to_addr(split_region) + partial_obj_size;
 
-  if (log_develop_is_enabled(Trace, gc, compaction, phases)) {
+  if (log_develop_is_enabled(Trace, gc, compaction)) {
     const char * split_type = partial_obj_size == 0 ? "easy" : "hard";
-    log_develop_trace(gc, compaction, phases)("%s split:  src=" PTR_FORMAT " src_c=" SIZE_FORMAT " pos=" SIZE_FORMAT,
-                                              split_type, p2i(source_next), split_region, partial_obj_size);
-    log_develop_trace(gc, compaction, phases)("%s split:  dst=" PTR_FORMAT " dst_c=" SIZE_FORMAT " tn=" PTR_FORMAT,
-                                              split_type, p2i(split_destination),
-                                              addr_to_region_idx(split_destination),
-                                              p2i(*target_next));
+    log_develop_trace(gc, compaction)("%s split:  src=" PTR_FORMAT " src_c=" SIZE_FORMAT " pos=" SIZE_FORMAT,
+                                      split_type, p2i(source_next), split_region, partial_obj_size);
+    log_develop_trace(gc, compaction)("%s split:  dst=" PTR_FORMAT " dst_c=" SIZE_FORMAT " tn=" PTR_FORMAT,
+                                      split_type, p2i(split_destination),
+                                      addr_to_region_idx(split_destination),
+                                      p2i(*target_next));
 
     if (partial_obj_size != 0) {
       HeapWord* const po_beg = split_info.destination();
       HeapWord* const po_end = po_beg + split_info.partial_obj_size();
-      log_develop_trace(gc, compaction, phases)("%s split:  po_beg=" PTR_FORMAT " " SIZE_FORMAT " po_end=" PTR_FORMAT " " SIZE_FORMAT,
-                                                split_type,
-                                                p2i(po_beg), addr_to_region_idx(po_beg),
-                                                p2i(po_end), addr_to_region_idx(po_end));
+      log_develop_trace(gc, compaction)("%s split:  po_beg=" PTR_FORMAT " " SIZE_FORMAT " po_end=" PTR_FORMAT " " SIZE_FORMAT,
+                                        split_type,
+                                        p2i(po_beg), addr_to_region_idx(po_beg),
+                                        p2i(po_end), addr_to_region_idx(po_end));
     }
   }
 
@@ -670,7 +670,7 @@
                                     HeapWord** target_next)
 {
   HeapWord* const source_next_val = source_next == NULL ? NULL : *source_next;
-  log_develop_trace(gc, compaction, phases)(
+  log_develop_trace(gc, compaction)(
       "sb=" PTR_FORMAT " se=" PTR_FORMAT " sn=" PTR_FORMAT
       "tb=" PTR_FORMAT " te=" PTR_FORMAT " tn=" PTR_FORMAT,
       p2i(source_beg), p2i(source_end), p2i(source_next_val),
@@ -938,7 +938,7 @@
   // at each young gen gc.  Do the update unconditionally (even though a
   // promotion failure does not swap spaces) because an unknown number of young
   // collections will have swapped the spaces an unknown number of times.
-  GCTraceTime(Trace, gc, phases) tm("Pre Compact", &_gc_timer);
+  GCTraceTime(Debug, gc, phases) tm("Pre Compact", &_gc_timer);
   ParallelScavengeHeap* heap = ParallelScavengeHeap::heap();
   _space_info[from_space_id].set_space(heap->young_gen()->from_space());
   _space_info[to_space_id].set_space(heap->young_gen()->to_space());
@@ -981,7 +981,7 @@
 
 void PSParallelCompact::post_compact()
 {
-  GCTraceTime(Trace, gc, phases) tm("Post Compact", &_gc_timer);
+  GCTraceTime(Info, gc, phases) tm("Post Compact", &_gc_timer);
 
   for (unsigned int id = old_space_id; id < last_space_id; ++id) {
     // Clear the marking bitmap, summary data and split info.
@@ -1524,7 +1524,7 @@
     }
   }
 
-  if (log_develop_is_enabled(Trace, gc, compaction, phases)) {
+  if (log_develop_is_enabled(Trace, gc, compaction)) {
     const size_t region_size = ParallelCompactData::RegionSize;
     HeapWord* const dense_prefix_end = _space_info[id].dense_prefix();
     const size_t dp_region = _summary_data.addr_to_region_idx(dense_prefix_end);
@@ -1532,7 +1532,7 @@
     HeapWord* const new_top = _space_info[id].new_top();
     const HeapWord* nt_aligned_up = _summary_data.region_align_up(new_top);
     const size_t cr_words = pointer_delta(nt_aligned_up, dense_prefix_end);
-    log_develop_trace(gc, compaction, phases)(
+    log_develop_trace(gc, compaction)(
         "id=%d cap=" SIZE_FORMAT " dp=" PTR_FORMAT " "
         "dp_region=" SIZE_FORMAT " " "dp_count=" SIZE_FORMAT " "
         "cr_count=" SIZE_FORMAT " " "nt=" PTR_FORMAT,
@@ -1548,7 +1548,7 @@
                                           SpaceId src_space_id,
                                           HeapWord* src_beg, HeapWord* src_end)
 {
-  log_develop_trace(gc, compaction, phases)(
+  log_develop_trace(gc, compaction)(
       "Summarizing %d [%s] into %d [%s]:  "
       "src=" PTR_FORMAT "-" PTR_FORMAT " "
       SIZE_FORMAT "-" SIZE_FORMAT " "
@@ -1568,7 +1568,7 @@
 void PSParallelCompact::summary_phase(ParCompactionManager* cm,
                                       bool maximum_compaction)
 {
-  GCTraceTime(Trace, gc, phases) tm("Summary Phase", &_gc_timer);
+  GCTraceTime(Info, gc, phases) tm("Summary Phase", &_gc_timer);
 
 #ifdef  ASSERT
   if (TraceParallelOldGCMarkingPhase) {
@@ -1584,7 +1584,7 @@
   // Quick summarization of each space into itself, to see how much is live.
   summarize_spaces_quick();
 
-  log_develop_trace(gc, compaction, phases)("summary phase:  after summarizing each space to self");
+  log_develop_trace(gc, compaction)("summary phase:  after summarizing each space to self");
   NOT_PRODUCT(print_region_ranges());
   NOT_PRODUCT(print_initial_summary_data(_summary_data, _space_info));
 
@@ -1660,7 +1660,7 @@
     }
   }
 
-  log_develop_trace(gc, compaction, phases)("Summary_phase:  after final summarization");
+  log_develop_trace(gc, compaction)("Summary_phase:  after final summarization");
   NOT_PRODUCT(print_region_ranges());
   NOT_PRODUCT(print_initial_summary_data(_summary_data, _space_info));
 }
@@ -2042,7 +2042,7 @@
                                       bool maximum_heap_compaction,
                                       ParallelOldTracer *gc_tracer) {
   // Recursively traverse all live objects and mark them
-  GCTraceTime(Trace, gc, phases) tm("Marking Phase", &_gc_timer);
+  GCTraceTime(Info, gc, phases) tm("Marking Phase", &_gc_timer);
 
   ParallelScavengeHeap* heap = ParallelScavengeHeap::heap();
   uint parallel_gc_threads = heap->gc_task_manager()->workers();
@@ -2057,7 +2057,7 @@
   ClassLoaderDataGraph::clear_claimed_marks();
 
   {
-    GCTraceTime(Trace, gc, phases) tm("Par Mark", &_gc_timer);
+    GCTraceTime(Debug, gc, phases) tm("Par Mark", &_gc_timer);
 
     ParallelScavengeHeap::ParStrongRootsScope psrs;
 
@@ -2086,7 +2086,7 @@
 
   // Process reference objects found during marking
   {
-    GCTraceTime(Trace, gc, phases) tm("Reference Processing", &_gc_timer);
+    GCTraceTime(Debug, gc, phases) tm("Reference Processing", &_gc_timer);
 
     ReferenceProcessorStats stats;
     if (ref_processor()->processing_is_mt()) {
@@ -2103,38 +2103,40 @@
     gc_tracer->report_gc_reference_stats(stats);
   }
 
-  GCTraceTime(Trace, gc) tm_m("Class Unloading", &_gc_timer);
-
   // This is the point where the entire marking should have completed.
   assert(cm->marking_stacks_empty(), "Marking should have completed");
 
-  // Follow system dictionary roots and unload classes.
-  bool purged_class = SystemDictionary::do_unloading(is_alive_closure());
-
-  // Unload nmethods.
-  CodeCache::do_unloading(is_alive_closure(), purged_class);
-
-  // Prune dead klasses from subklass/sibling/implementor lists.
-  Klass::clean_weak_klass_links(is_alive_closure());
-
-  // Delete entries for dead interned strings.
-  StringTable::unlink(is_alive_closure());
-
-  // Clean up unreferenced symbols in symbol table.
-  SymbolTable::unlink();
+  {
+    GCTraceTime(Debug, gc, phases) tm_m("Class Unloading", &_gc_timer);
+
+    // Follow system dictionary roots and unload classes.
+    bool purged_class = SystemDictionary::do_unloading(is_alive_closure());
+
+    // Unload nmethods.
+    CodeCache::do_unloading(is_alive_closure(), purged_class);
+
+    // Prune dead klasses from subklass/sibling/implementor lists.
+    Klass::clean_weak_klass_links(is_alive_closure());
+  }
+
+  {
+    GCTraceTime(Debug, gc, phases) t("Scrub String Table", &_gc_timer);
+    // Delete entries for dead interned strings.
+    StringTable::unlink(is_alive_closure());
+  }
+
+  {
+    GCTraceTime(Debug, gc, phases) t("Scrub Symbol Table", &_gc_timer);
+    // Clean up unreferenced symbols in symbol table.
+    SymbolTable::unlink();
+  }
+
   _gc_tracer.report_object_count_after_gc(is_alive_closure());
 }
 
-// This should be moved to the shared markSweep code!
-class PSAlwaysTrueClosure: public BoolObjectClosure {
-public:
-  bool do_object_b(oop p) { return true; }
-};
-static PSAlwaysTrueClosure always_true;
-
 void PSParallelCompact::adjust_roots(ParCompactionManager* cm) {
   // Adjust the pointers to reflect the new locations
-  GCTraceTime(Trace, gc, phases) tm("Adjust Roots", &_gc_timer);
+  GCTraceTime(Info, gc, phases) tm("Adjust Roots", &_gc_timer);
 
   // Need new claim bits when tracing through and adjusting pointers.
   ClassLoaderDataGraph::clear_claimed_marks();
@@ -2157,7 +2159,7 @@
   // Now adjust pointers in remaining weak roots.  (All of which should
   // have been cleared if they pointed to non-surviving objects.)
   // Global (weak) JNI handles
-  JNIHandles::weak_oops_do(&always_true, &oop_closure);
+  JNIHandles::weak_oops_do(&oop_closure);
 
   CodeBlobToOopClosure adjust_from_blobs(&oop_closure, CodeBlobToOopClosure::FixRelocations);
   CodeCache::blobs_do(&adjust_from_blobs);
@@ -2408,7 +2410,7 @@
 #endif // #ifdef ASSERT
 
 void PSParallelCompact::compact() {
-  GCTraceTime(Trace, gc, phases) tm("Compaction Phase", &_gc_timer);
+  GCTraceTime(Info, gc, phases) tm("Compaction Phase", &_gc_timer);
 
   ParallelScavengeHeap* heap = ParallelScavengeHeap::heap();
   PSOldGen* old_gen = heap->old_gen();
@@ -2467,9 +2469,8 @@
   for (cur_region = beg_region; cur_region < new_top_region; ++cur_region) {
     const RegionData* const c = sd.region(cur_region);
     if (!c->completed()) {
-      warning("region " SIZE_FORMAT " not filled:  "
-              "destination_count=%u",
-              cur_region, c->destination_count());
+      log_warning(gc)("region " SIZE_FORMAT " not filled: destination_count=%u",
+                      cur_region, c->destination_count());
       issued_a_warning = true;
     }
   }
@@ -2477,9 +2478,8 @@
   for (cur_region = new_top_region; cur_region < old_top_region; ++cur_region) {
     const RegionData* const c = sd.region(cur_region);
     if (!c->available()) {
-      warning("region " SIZE_FORMAT " not empty:   "
-              "destination_count=%u",
-              cur_region, c->destination_count());
+      log_warning(gc)("region " SIZE_FORMAT " not empty: destination_count=%u",
+                      cur_region, c->destination_count());
       issued_a_warning = true;
     }
   }
@@ -3013,7 +3013,7 @@
   jlong ret_val = now - _time_of_last_gc;
   // XXX See note in genCollectedHeap::millis_since_last_gc().
   if (ret_val < 0) {
-    NOT_PRODUCT(warning("time warp: " JLONG_FORMAT, ret_val);)
+    NOT_PRODUCT(log_warning(gc)("time warp: " JLONG_FORMAT, ret_val);)
     return 0;
   }
   return ret_val;
--- a/hotspot/src/share/vm/gc/parallel/psPromotionManager.cpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/gc/parallel/psPromotionManager.cpp	Wed Mar 23 23:36:29 2016 +0100
@@ -29,6 +29,7 @@
 #include "gc/parallel/psPromotionManager.inline.hpp"
 #include "gc/parallel/psScavenge.inline.hpp"
 #include "gc/shared/gcTrace.hpp"
+#include "gc/shared/preservedMarks.inline.hpp"
 #include "gc/shared/taskqueue.inline.hpp"
 #include "logging/log.hpp"
 #include "memory/allocation.inline.hpp"
@@ -41,6 +42,7 @@
 
 PaddedEnd<PSPromotionManager>* PSPromotionManager::_manager_array = NULL;
 OopStarTaskQueueSet*           PSPromotionManager::_stack_array_depth = NULL;
+PreservedMarksSet*             PSPromotionManager::_preserved_marks_set = NULL;
 PSOldGen*                      PSPromotionManager::_old_gen = NULL;
 MutableSpace*                  PSPromotionManager::_young_space = NULL;
 
@@ -50,10 +52,12 @@
   _old_gen = heap->old_gen();
   _young_space = heap->young_gen()->to_space();
 
+  const uint promotion_manager_num = ParallelGCThreads + 1;
+
   // To prevent false sharing, we pad the PSPromotionManagers
   // and make sure that the first instance starts at a cache line.
   assert(_manager_array == NULL, "Attempt to initialize twice");
-  _manager_array = PaddedArray<PSPromotionManager, mtGC>::create_unfreeable(ParallelGCThreads + 1);
+  _manager_array = PaddedArray<PSPromotionManager, mtGC>::create_unfreeable(promotion_manager_num);
   guarantee(_manager_array != NULL, "Could not initialize promotion manager");
 
   _stack_array_depth = new OopStarTaskQueueSet(ParallelGCThreads);
@@ -65,6 +69,14 @@
   }
   // The VMThread gets its own PSPromotionManager, which is not available
   // for work stealing.
+
+  assert(_preserved_marks_set == NULL, "Attempt to initialize twice");
+  _preserved_marks_set = new PreservedMarksSet(true /* in_c_heap */);
+  guarantee(_preserved_marks_set != NULL, "Could not initialize preserved marks set");
+  _preserved_marks_set->init(promotion_manager_num);
+  for (uint i = 0; i < promotion_manager_num; i += 1) {
+    _manager_array[i].register_preserved_marks(_preserved_marks_set->get(i));
+  }
 }
 
 // Helper functions to get around the circular dependency between
@@ -90,6 +102,7 @@
 void PSPromotionManager::pre_scavenge() {
   ParallelScavengeHeap* heap = ParallelScavengeHeap::heap();
 
+  _preserved_marks_set->assert_empty();
   _young_space = heap->young_gen()->to_space();
 
   for(uint i=0; i<ParallelGCThreads+1; i++) {
@@ -110,6 +123,11 @@
     }
     manager->flush_labs();
   }
+  if (!promotion_failure_occurred) {
+    // If there was no promotion failure, the preserved mark stacks
+    // should be empty.
+    _preserved_marks_set->assert_empty();
+  }
   return promotion_failure_occurred;
 }
 
@@ -187,6 +205,8 @@
   // let's choose 1.5x the chunk size
   _min_array_size_for_chunking = 3 * _array_chunk_size / 2;
 
+  _preserved_marks = NULL;
+
   reset();
 }
 
@@ -211,6 +231,10 @@
   TASKQUEUE_STATS_ONLY(reset_stats());
 }
 
+void PSPromotionManager::register_preserved_marks(PreservedMarks* preserved_marks) {
+  assert(_preserved_marks == NULL, "do not set it twice");
+  _preserved_marks = preserved_marks;
+}
 
 void PSPromotionManager::drain_stacks_depth(bool totally_drain) {
   totally_drain = totally_drain || _totally_drain;
@@ -422,8 +446,7 @@
 
     push_contents(obj);
 
-    // Save the mark if needed
-    PSScavenge::oop_promotion_failed(obj, obj_mark);
+    _preserved_marks->push_if_necessary(obj, obj_mark);
   }  else {
     // We lost, someone else "owns" this object
     guarantee(obj->is_forwarded(), "Object must be forwarded if the cas failed.");
--- a/hotspot/src/share/vm/gc/parallel/psPromotionManager.hpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/gc/parallel/psPromotionManager.hpp	Wed Mar 23 23:36:29 2016 +0100
@@ -28,6 +28,7 @@
 #include "gc/parallel/psPromotionLAB.hpp"
 #include "gc/shared/copyFailedInfo.hpp"
 #include "gc/shared/gcTrace.hpp"
+#include "gc/shared/preservedMarks.hpp"
 #include "gc/shared/taskqueue.hpp"
 #include "memory/allocation.hpp"
 #include "memory/padded.hpp"
@@ -55,6 +56,7 @@
  private:
   static PaddedEnd<PSPromotionManager>* _manager_array;
   static OopStarTaskQueueSet*           _stack_array_depth;
+  static PreservedMarksSet*             _preserved_marks_set;
   static PSOldGen*                      _old_gen;
   static MutableSpace*                  _young_space;
 
@@ -84,6 +86,7 @@
   uint                                _array_chunk_size;
   uint                                _min_array_size_for_chunking;
 
+  PreservedMarks*                     _preserved_marks;
   PromotionFailedInfo                 _promotion_failed_info;
 
   // Accessors
@@ -176,6 +179,8 @@
   oop oop_promotion_failed(oop obj, markOop obj_mark);
 
   void reset();
+  void register_preserved_marks(PreservedMarks* preserved_marks);
+  static void restore_preserved_marks() { _preserved_marks_set->restore(); }
 
   void flush_labs();
   void drain_stacks(bool totally_drain) {
--- a/hotspot/src/share/vm/gc/parallel/psScavenge.cpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/gc/parallel/psScavenge.cpp	Wed Mar 23 23:36:29 2016 +0100
@@ -68,8 +68,6 @@
 elapsedTimer               PSScavenge::_accumulated_time;
 STWGCTimer                 PSScavenge::_gc_timer;
 ParallelScavengeTracer     PSScavenge::_gc_tracer;
-Stack<markOop, mtGC>       PSScavenge::_preserved_mark_stack;
-Stack<oop, mtGC>           PSScavenge::_preserved_oop_stack;
 CollectorCounters*         PSScavenge::_counters = NULL;
 
 // Define before use
@@ -123,14 +121,6 @@
   }
 };
 
-class PSPromotionFailedClosure : public ObjectClosure {
-  virtual void do_object(oop obj) {
-    if (obj->is_forwarded()) {
-      obj->init_mark();
-    }
-  }
-};
-
 class PSRefProcTaskProxy: public GCTask {
   typedef AbstractRefProcTaskExecutor::ProcessTask ProcessTask;
   ProcessTask & _rp_task;
@@ -257,9 +247,6 @@
   assert(SafepointSynchronize::is_at_safepoint(), "should be at safepoint");
   assert(Thread::current() == (Thread*)VMThread::vm_thread(), "should be in vm thread");
 
-  assert(_preserved_mark_stack.is_empty(), "should be empty");
-  assert(_preserved_oop_stack.is_empty(), "should be empty");
-
   _gc_timer.register_gc_start();
 
   TimeStamp scavenge_entry;
@@ -417,7 +404,7 @@
 
     // Process reference objects discovered during scavenge
     {
-      GCTraceTime(Debug, gc, phases) tm("References", &_gc_timer);
+      GCTraceTime(Debug, gc, phases) tm("Reference Processing", &_gc_timer);
 
       reference_processor()->setup_policy(false); // not always_clear
       reference_processor()->set_active_mt_degree(active_workers);
@@ -446,7 +433,7 @@
     }
 
     {
-      GCTraceTime(Debug, gc, phases) tm("StringTable", &_gc_timer);
+      GCTraceTime(Debug, gc, phases) tm("Scrub String Table", &_gc_timer);
       // Unlink any dead interned Strings and process the remaining live ones.
       PSScavengeRootsClosure root_closure(promotion_manager);
       StringTable::unlink_or_oops_do(&_is_alive_closure, &root_closure);
@@ -656,52 +643,20 @@
 }
 
 // This method iterates over all objects in the young generation,
-// unforwarding markOops. It then restores any preserved mark oops,
-// and clears the _preserved_mark_stack.
+// removing all forwarding references. It then restores any preserved marks.
 void PSScavenge::clean_up_failed_promotion() {
   ParallelScavengeHeap* heap = ParallelScavengeHeap::heap();
   PSYoungGen* young_gen = heap->young_gen();
 
-  {
-    ResourceMark rm;
-
-    // Unforward all pointers in the young gen.
-    PSPromotionFailedClosure unforward_closure;
-    young_gen->object_iterate(&unforward_closure);
-
-    log_trace(gc, ergo)("Restoring " SIZE_FORMAT " marks", _preserved_oop_stack.size());
+  RemoveForwardedPointerClosure remove_fwd_ptr_closure;
+  young_gen->object_iterate(&remove_fwd_ptr_closure);
 
-    // Restore any saved marks.
-    while (!_preserved_oop_stack.is_empty()) {
-      oop obj      = _preserved_oop_stack.pop();
-      markOop mark = _preserved_mark_stack.pop();
-      obj->set_mark(mark);
-    }
-
-    // Clear the preserved mark and oop stack caches.
-    _preserved_mark_stack.clear(true);
-    _preserved_oop_stack.clear(true);
-  }
+  PSPromotionManager::restore_preserved_marks();
 
   // Reset the PromotionFailureALot counters.
   NOT_PRODUCT(heap->reset_promotion_should_fail();)
 }
 
-// This method is called whenever an attempt to promote an object
-// fails. Some markOops will need preservation, some will not. Note
-// that the entire eden is traversed after a failed promotion, with
-// all forwarded headers replaced by the default markOop. This means
-// it is not necessary to preserve most markOops.
-void PSScavenge::oop_promotion_failed(oop obj, markOop obj_mark) {
-  if (obj_mark->must_be_preserved_for_promotion_failure(obj)) {
-    // Should use per-worker private stacks here rather than
-    // locking a common pair of stacks.
-    ThreadCritical tc;
-    _preserved_oop_stack.push(obj);
-    _preserved_mark_stack.push(obj_mark);
-  }
-}
-
 bool PSScavenge::should_attempt_scavenge() {
   ParallelScavengeHeap* heap = ParallelScavengeHeap::heap();
   PSGCAdaptivePolicyCounters* counters = heap->gc_policy_counters();
--- a/hotspot/src/share/vm/gc/parallel/psScavenge.hpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/gc/parallel/psScavenge.hpp	Wed Mar 23 23:36:29 2016 +0100
@@ -79,8 +79,6 @@
   static HeapWord*            _young_generation_boundary;
   // Used to optimize compressed oops young gen boundary checking.
   static uintptr_t            _young_generation_boundary_compressed;
-  static Stack<markOop, mtGC> _preserved_mark_stack; // List of marks to be restored after failed promotion
-  static Stack<oop, mtGC>     _preserved_oop_stack;  // List of oops that need their mark restored.
   static CollectorCounters*   _counters;             // collector performance counters
 
   static void clean_up_failed_promotion();
@@ -127,9 +125,6 @@
   // Return true if a collection was done; false otherwise.
   static bool invoke_no_policy();
 
-  // If an attempt to promote fails, this method is invoked
-  static void oop_promotion_failed(oop obj, markOop obj_mark);
-
   template <class T> static inline bool should_scavenge(T* p);
 
   // These call should_scavenge() above and, if it returns true, also check that
--- a/hotspot/src/share/vm/gc/serial/defNewGeneration.cpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/gc/serial/defNewGeneration.cpp	Wed Mar 23 23:36:29 2016 +0100
@@ -594,7 +594,7 @@
 
   init_assuming_no_promotion_failure();
 
-  GCTraceTime(Trace, gc) tm("DefNew", NULL, gch->gc_cause());
+  GCTraceTime(Trace, gc, phases) tm("DefNew", NULL, gch->gc_cause());
 
   gch->trace_heap_before_gc(&gc_tracer);
 
--- a/hotspot/src/share/vm/gc/serial/genMarkSweep.cpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/gc/serial/genMarkSweep.cpp	Wed Mar 23 23:36:29 2016 +0100
@@ -180,7 +180,7 @@
 
 void GenMarkSweep::mark_sweep_phase1(bool clear_all_softrefs) {
   // Recursively traverse all live objects and mark them
-  GCTraceTime(Trace, gc) tm("Phase 1: Mark live objects", _gc_timer);
+  GCTraceTime(Info, gc, phases) tm("Phase 1: Mark live objects", _gc_timer);
 
   GenCollectedHeap* gch = GenCollectedHeap::heap();
 
@@ -208,6 +208,8 @@
 
   // Process reference objects found during marking
   {
+    GCTraceTime(Debug, gc, phases) tm_m("Reference Processing", gc_timer());
+
     ref_processor()->setup_policy(clear_all_softrefs);
     const ReferenceProcessorStats& stats =
       ref_processor()->process_discovered_references(
@@ -218,20 +220,30 @@
   // This is the point where the entire marking should have completed.
   assert(_marking_stack.is_empty(), "Marking should have completed");
 
-  // Unload classes and purge the SystemDictionary.
-  bool purged_class = SystemDictionary::do_unloading(&is_alive);
+  {
+    GCTraceTime(Debug, gc, phases) tm_m("Class Unloading", gc_timer());
 
-  // Unload nmethods.
-  CodeCache::do_unloading(&is_alive, purged_class);
+    // Unload classes and purge the SystemDictionary.
+    bool purged_class = SystemDictionary::do_unloading(&is_alive);
+
+    // Unload nmethods.
+    CodeCache::do_unloading(&is_alive, purged_class);
 
-  // Prune dead klasses from subklass/sibling/implementor lists.
-  Klass::clean_weak_klass_links(&is_alive);
+    // Prune dead klasses from subklass/sibling/implementor lists.
+    Klass::clean_weak_klass_links(&is_alive);
+  }
 
-  // Delete entries for dead interned strings.
-  StringTable::unlink(&is_alive);
+  {
+    GCTraceTime(Debug, gc, phases) t("Scrub String Table", gc_timer());
+    // Delete entries for dead interned strings.
+    StringTable::unlink(&is_alive);
+  }
 
-  // Clean up unreferenced symbols in symbol table.
-  SymbolTable::unlink();
+  {
+    GCTraceTime(Debug, gc, phases) t("Scrub Symbol Table", gc_timer());
+    // Clean up unreferenced symbols in symbol table.
+    SymbolTable::unlink();
+  }
 
   gc_tracer()->report_object_count_after_gc(&is_alive);
 }
@@ -253,7 +265,7 @@
 
   GenCollectedHeap* gch = GenCollectedHeap::heap();
 
-  GCTraceTime(Trace, gc) tm("Phase 2: Compute new object addresses", _gc_timer);
+  GCTraceTime(Info, gc, phases) tm("Phase 2: Compute new object addresses", _gc_timer);
 
   gch->prepare_for_compaction();
 }
@@ -269,7 +281,7 @@
   GenCollectedHeap* gch = GenCollectedHeap::heap();
 
   // Adjust the pointers to reflect the new locations
-  GCTraceTime(Trace, gc) tm("Phase 3: Adjust pointers", _gc_timer);
+  GCTraceTime(Info, gc, phases) tm("Phase 3: Adjust pointers", gc_timer());
 
   // Need new claim bits for the pointer adjustment tracing.
   ClassLoaderDataGraph::clear_claimed_marks();
@@ -321,7 +333,7 @@
   // to use a higher index (saved from phase2) when verifying perm_gen.
   GenCollectedHeap* gch = GenCollectedHeap::heap();
 
-  GCTraceTime(Trace, gc) tm("Phase 4: Move objects", _gc_timer);
+  GCTraceTime(Info, gc, phases) tm("Phase 4: Move objects", _gc_timer);
 
   GenCompactClosure blk;
   gch->generation_iterate(&blk, true);
--- a/hotspot/src/share/vm/gc/shared/barrierSet.cpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/gc/shared/barrierSet.cpp	Wed Mar 23 23:36:29 2016 +0100
@@ -30,10 +30,6 @@
 // count is number of array elements being written
 void BarrierSet::static_write_ref_array_pre(HeapWord* start, size_t count) {
   assert(count <= (size_t)max_intx, "count too large");
-#if 0
-  warning("Pre: \t" INTPTR_FORMAT "[" SIZE_FORMAT "]\t",
-                   start,            count);
-#endif
   if (UseCompressedOops) {
     Universe::heap()->barrier_set()->write_ref_array_pre((narrowOop*)start, (int)count, false);
   } else {
--- a/hotspot/src/share/vm/gc/shared/barrierSet.inline.hpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/gc/shared/barrierSet.inline.hpp	Wed Mar 23 23:36:29 2016 +0100
@@ -78,10 +78,6 @@
   // If compressed oops were not being used, these should already be aligned
   assert(UseCompressedOops || (aligned_start == start && aligned_end == end),
          "Expected heap word alignment of start and end");
-#if 0
-  warning("Post:\t" INTPTR_FORMAT "[" SIZE_FORMAT "] : [" INTPTR_FORMAT "," INTPTR_FORMAT ")\t",
-                   start,            count,              aligned_start,   aligned_end);
-#endif
   write_ref_array_work(MemRegion(aligned_start, aligned_end));
 }
 
--- a/hotspot/src/share/vm/gc/shared/cardGeneration.cpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/gc/shared/cardGeneration.cpp	Wed Mar 23 23:36:29 2016 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 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
@@ -144,7 +144,7 @@
   const size_t remaining_bytes = _virtual_space.uncommitted_size();
   if (remaining_bytes > 0) {
     success = grow_by(remaining_bytes);
-    DEBUG_ONLY(if (!success) warning("grow to reserved failed");)
+    DEBUG_ONLY(if (!success) log_warning(gc)("grow to reserved failed");)
   }
   return success;
 }
@@ -254,19 +254,22 @@
     if (capacity_after_gc > maximum_desired_capacity) {
       // Capacity too large, compute shrinking size
       shrink_bytes = capacity_after_gc - maximum_desired_capacity;
-      // We don't want shrink all the way back to initSize if people call
-      // System.gc(), because some programs do that between "phases" and then
-      // we'd just have to grow the heap up again for the next phase.  So we
-      // damp the shrinking: 0% on the first call, 10% on the second call, 40%
-      // on the third call, and 100% by the fourth call.  But if we recompute
-      // size without shrinking, it goes back to 0%.
-      shrink_bytes = shrink_bytes / 100 * current_shrink_factor;
+      if (ShrinkHeapInSteps) {
+        // If ShrinkHeapInSteps is true (the default),
+        // we don't want to shrink all the way back to initSize if people call
+        // System.gc(), because some programs do that between "phases" and then
+        // we'd just have to grow the heap up again for the next phase.  So we
+        // damp the shrinking: 0% on the first call, 10% on the second call, 40%
+        // on the third call, and 100% by the fourth call.  But if we recompute
+        // size without shrinking, it goes back to 0%.
+        shrink_bytes = shrink_bytes / 100 * current_shrink_factor;
+        if (current_shrink_factor == 0) {
+          _shrink_factor = 10;
+        } else {
+          _shrink_factor = MIN2(current_shrink_factor * 4, (size_t) 100);
+        }
+      }
       assert(shrink_bytes <= max_shrink_bytes, "invalid shrink size");
-      if (current_shrink_factor == 0) {
-        _shrink_factor = 10;
-      } else {
-        _shrink_factor = MIN2(current_shrink_factor * 4, (size_t) 100);
-      }
       log_trace(gc, heap)("    shrinking:  initSize: %.1fK  maximum_desired_capacity: %.1fK",
                                initial_size() / (double) K, maximum_desired_capacity / (double) K);
       log_trace(gc, heap)("    shrink_bytes: %.1fK  current_shrink_factor: " SIZE_FORMAT "  new shrink factor: " SIZE_FORMAT "  _min_heap_delta_bytes: %.1fK",
--- a/hotspot/src/share/vm/gc/shared/cardTableRS.cpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/gc/shared/cardTableRS.cpp	Wed Mar 23 23:36:29 2016 +0100
@@ -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
@@ -325,17 +325,17 @@
   // In the case of CMS+ParNew, issue a warning
   if (!ur.contains(urasm)) {
     assert(UseConcMarkSweepGC, "Tautology: see assert above");
-    warning("CMS+ParNew: Did you forget to call save_marks()? "
-            "[" PTR_FORMAT ", " PTR_FORMAT ") is not contained in "
-            "[" PTR_FORMAT ", " PTR_FORMAT ")",
-             p2i(urasm.start()), p2i(urasm.end()), p2i(ur.start()), p2i(ur.end()));
+    log_warning(gc)("CMS+ParNew: Did you forget to call save_marks()? "
+                    "[" PTR_FORMAT ", " PTR_FORMAT ") is not contained in "
+                    "[" PTR_FORMAT ", " PTR_FORMAT ")",
+                    p2i(urasm.start()), p2i(urasm.end()), p2i(ur.start()), p2i(ur.end()));
     MemRegion ur2 = sp->used_region();
     MemRegion urasm2 = sp->used_region_at_save_marks();
     if (!ur.equals(ur2)) {
-      warning("CMS+ParNew: Flickering used_region()!!");
+      log_warning(gc)("CMS+ParNew: Flickering used_region()!!");
     }
     if (!urasm.equals(urasm2)) {
-      warning("CMS+ParNew: Flickering used_region_at_save_marks()!!");
+      log_warning(gc)("CMS+ParNew: Flickering used_region_at_save_marks()!!");
     }
     ShouldNotReachHere();
   }
--- a/hotspot/src/share/vm/gc/shared/collectedHeap.cpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/gc/shared/collectedHeap.cpp	Wed Mar 23 23:36:29 2016 +0100
@@ -213,7 +213,7 @@
       do_full_collection(false);        // don't clear all soft refs
       break;
     }
-    case GCCause::_last_ditch_collection: {
+    case GCCause::_metadata_GC_clear_soft_refs: {
       HandleMark hm;
       do_full_collection(true);         // do clear all soft refs
       break;
--- a/hotspot/src/share/vm/gc/shared/collectedHeap.hpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/gc/shared/collectedHeap.hpp	Wed Mar 23 23:36:29 2016 +0100
@@ -438,6 +438,12 @@
   // remembered set.
   virtual void flush_deferred_store_barrier(JavaThread* thread);
 
+  // Should return true if the reference pending list lock is
+  // acquired from non-Java threads, such as a concurrent GC thread.
+  virtual bool needs_reference_pending_list_locker_thread() const {
+    return false;
+  }
+
   // Perform a collection of the heap; intended for use in implementing
   // "System.gc".  This probably implies as full a collection as the
   // "CollectedHeap" supports.
--- a/hotspot/src/share/vm/gc/shared/collectorPolicy.cpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/gc/shared/collectorPolicy.cpp	Wed Mar 23 23:36:29 2016 +0100
@@ -96,6 +96,9 @@
   }
 
   // Check heap parameter properties
+  if (MaxHeapSize < 2 * M) {
+    vm_exit_during_initialization("Too small maximum heap");
+  }
   if (InitialHeapSize < M) {
     vm_exit_during_initialization("Too small initial heap");
   }
--- a/hotspot/src/share/vm/gc/shared/concurrentGCThread.cpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/gc/shared/concurrentGCThread.cpp	Wed Mar 23 23:36:29 2016 +0100
@@ -37,12 +37,12 @@
   _should_terminate(false), _has_terminated(false) {
 };
 
-void ConcurrentGCThread::create_and_start() {
+void ConcurrentGCThread::create_and_start(ThreadPriority prio) {
   if (os::create_thread(this, os::cgc_thread)) {
     // XXX: need to set this to low priority
     // unless "aggressive mode" set; priority
     // should be just less than that of VMThread.
-    os::set_priority(this, NearMaxPriority);
+    os::set_priority(this, prio);
     if (!_should_terminate && !DisableStartThread) {
       os::start_thread(this);
     }
@@ -75,130 +75,30 @@
   }
 }
 
-static void _sltLoop(JavaThread* thread, TRAPS) {
-  SurrogateLockerThread* slt = (SurrogateLockerThread*)thread;
-  slt->loop();
-}
-
-SurrogateLockerThread::SurrogateLockerThread() :
-  JavaThread(&_sltLoop),
-  _monitor(Mutex::nonleaf, "SLTMonitor", false,
-           Monitor::_safepoint_check_sometimes),
-  _buffer(empty)
-{}
-
-SurrogateLockerThread* SurrogateLockerThread::make(TRAPS) {
-  Klass* k =
-    SystemDictionary::resolve_or_fail(vmSymbols::java_lang_Thread(),
-                                      true, CHECK_NULL);
-  instanceKlassHandle klass (THREAD, k);
-  instanceHandle thread_oop = klass->allocate_instance_handle(CHECK_NULL);
-
-  const char thread_name[] = "Surrogate Locker Thread (Concurrent GC)";
-  Handle string = java_lang_String::create_from_str(thread_name, CHECK_NULL);
+void ConcurrentGCThread::run() {
+  initialize_in_thread();
+  wait_for_universe_init();
 
-  // Initialize thread_oop to put it into the system threadGroup
-  Handle thread_group (THREAD, Universe::system_thread_group());
-  JavaValue result(T_VOID);
-  JavaCalls::call_special(&result, thread_oop,
-                          klass,
-                          vmSymbols::object_initializer_name(),
-                          vmSymbols::threadgroup_string_void_signature(),
-                          thread_group,
-                          string,
-                          CHECK_NULL);
-
-  SurrogateLockerThread* res;
-  {
-    MutexLocker mu(Threads_lock);
-    res = new SurrogateLockerThread();
+  run_service();
 
-    // At this point it may be possible that no osthread was created for the
-    // JavaThread due to lack of memory. We would have to throw an exception
-    // in that case. However, since this must work and we do not allow
-    // exceptions anyway, check and abort if this fails.
-    if (res == NULL || res->osthread() == NULL) {
-      vm_exit_during_initialization("java.lang.OutOfMemoryError",
-                                    os::native_thread_creation_failed_msg());
-    }
-    java_lang_Thread::set_thread(thread_oop(), res);
-    java_lang_Thread::set_priority(thread_oop(), NearMaxPriority);
-    java_lang_Thread::set_daemon(thread_oop());
-
-    res->set_threadObj(thread_oop());
-    Threads::add(res);
-    Thread::start(res);
-  }
-  os::naked_yield(); // This seems to help with initial start-up of SLT
-  return res;
+  terminate();
 }
 
-void SurrogateLockerThread::report_missing_slt() {
-  vm_exit_during_initialization(
-    "GC before GC support fully initialized: "
-    "SLT is needed but has not yet been created.");
-  ShouldNotReachHere();
-}
+void ConcurrentGCThread::stop() {
+  // it is ok to take late safepoints here, if needed
+  {
+    MutexLockerEx mu(Terminator_lock);
+    assert(!_has_terminated,   "stop should only be called once");
+    assert(!_should_terminate, "stop should only be called once");
+    _should_terminate = true;
+  }
 
-void SurrogateLockerThread::manipulatePLL(SLT_msg_type msg) {
-  MutexLockerEx x(&_monitor, Mutex::_no_safepoint_check_flag);
-  assert(_buffer == empty, "Should be empty");
-  assert(msg != empty, "empty message");
-  assert(!Heap_lock->owned_by_self(), "Heap_lock owned by requesting thread");
+  stop_service();
 
-  _buffer = msg;
-  while (_buffer != empty) {
-    _monitor.notify();
-    _monitor.wait(Mutex::_no_safepoint_check_flag);
+  {
+    MutexLockerEx mu(Terminator_lock);
+    while (!_has_terminated) {
+      Terminator_lock->wait();
+    }
   }
 }
-
-// ======= Surrogate Locker Thread =============
-
-void SurrogateLockerThread::loop() {
-  BasicLock pll_basic_lock;
-  SLT_msg_type msg;
-  debug_only(unsigned int owned = 0;)
-
-  while (/* !isTerminated() */ 1) {
-    {
-      MutexLocker x(&_monitor);
-      // Since we are a JavaThread, we can't be here at a safepoint.
-      assert(!SafepointSynchronize::is_at_safepoint(),
-             "SLT is a JavaThread");
-      // wait for msg buffer to become non-empty
-      while (_buffer == empty) {
-        _monitor.notify();
-        _monitor.wait();
-      }
-      msg = _buffer;
-    }
-    switch(msg) {
-      case acquirePLL: {
-        InstanceRefKlass::acquire_pending_list_lock(&pll_basic_lock);
-        debug_only(owned++;)
-        break;
-      }
-      case releaseAndNotifyPLL: {
-        assert(owned > 0, "Don't have PLL");
-        InstanceRefKlass::release_and_notify_pending_list_lock(&pll_basic_lock);
-        debug_only(owned--;)
-        break;
-      }
-      case empty:
-      default: {
-        guarantee(false,"Unexpected message in _buffer");
-        break;
-      }
-    }
-    {
-      MutexLocker x(&_monitor);
-      // Since we are a JavaThread, we can't be here at a safepoint.
-      assert(!SafepointSynchronize::is_at_safepoint(),
-             "SLT is a JavaThread");
-      _buffer = empty;
-      _monitor.notify();
-    }
-  }
-  assert(!_monitor.owned_by_self(), "Should unlock before exit.");
-}
--- a/hotspot/src/share/vm/gc/shared/concurrentGCThread.hpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/gc/shared/concurrentGCThread.hpp	Wed Mar 23 23:36:29 2016 +0100
@@ -31,13 +31,9 @@
 class ConcurrentGCThread: public NamedThread {
   friend class VMStructs;
 
-protected:
   bool volatile _should_terminate;
   bool _has_terminated;
 
-  // Create and start the thread (setting it's priority high.)
-  void create_and_start();
-
   // Do initialization steps in the thread: record stack base and size,
   // init thread local storage, set JNI handle block.
   void initialize_in_thread();
@@ -49,44 +45,29 @@
   // concurrent work.
   void terminate();
 
+protected:
+  // Create and start the thread (setting it's priority.)
+  void create_and_start(ThreadPriority prio = NearMaxPriority);
+
+  // Do the specific GC work. Called by run() after initialization complete.
+  virtual void run_service() = 0;
+
+  // Shut down the specific GC work. Called by stop() as part of termination protocol.
+  virtual void stop_service()  = 0;
+
 public:
   ConcurrentGCThread();
 
   // Tester
   bool is_ConcurrentGC_thread() const { return true; }
-};
+
+  virtual void run();
 
-// The SurrogateLockerThread is used by concurrent GC threads for
-// manipulating Java monitors, in particular, currently for
-// manipulating the pending_list_lock. XXX
-class SurrogateLockerThread: public JavaThread {
-  friend class VMStructs;
- public:
-  enum SLT_msg_type {
-    empty = 0,           // no message
-    acquirePLL,          // acquire pending list lock
-    releaseAndNotifyPLL  // notify and release pending list lock
-  };
- private:
-  // the following are shared with the CMSThread
-  SLT_msg_type  _buffer;  // communication buffer
-  Monitor       _monitor; // monitor controlling buffer
-  BasicLock     _basicLock; // used for PLL locking
+  // shutdown following termination protocol
+  virtual void stop();
 
- public:
-  static SurrogateLockerThread* make(TRAPS);
-
-  // Terminate VM with error message that SLT needed but not yet created.
-  static void report_missing_slt();
-
-  SurrogateLockerThread();
-
-  bool is_hidden_from_external_view() const     { return true; }
-
-  void loop(); // main method
-
-  void manipulatePLL(SLT_msg_type msg);
-
+  bool should_terminate() { return _should_terminate; }
+  bool has_terminated()   { return _has_terminated; }
 };
 
 #endif // SHARE_VM_GC_SHARED_CONCURRENTGCTHREAD_HPP
--- a/hotspot/src/share/vm/gc/shared/gcCause.cpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/gc/shared/gcCause.cpp	Wed Mar 23 23:36:29 2016 +0100
@@ -57,6 +57,9 @@
     case _wb_conc_mark:
       return "WhiteBox Initiated Concurrent Mark";
 
+    case _wb_full_gc:
+      return "WhiteBox Initiated Full GC";
+
     case _update_allocation_context_stats_inc:
     case _update_allocation_context_stats_full:
       return "Update Allocation Context Stats";
@@ -73,6 +76,9 @@
     case _metadata_GC_threshold:
       return "Metadata GC Threshold";
 
+    case _metadata_GC_clear_soft_refs:
+      return "Metadata GC Clear Soft References";
+
     case _cms_generation_full:
       return "CMS Generation Full";
 
@@ -100,9 +106,6 @@
     case _g1_humongous_allocation:
       return "G1 Humongous Allocation";
 
-    case _last_ditch_collection:
-      return "Last ditch collection";
-
     case _dcmd_gc_run:
       return "Diagnostic Command";
 
--- a/hotspot/src/share/vm/gc/shared/gcCause.hpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/gc/shared/gcCause.hpp	Wed Mar 23 23:36:29 2016 +0100
@@ -33,6 +33,9 @@
 // use of this class grows, we should split it into public
 // and implementation-private "causes".
 //
+// The definitions in the SA code should be kept in sync
+// with the definitions here.
+//
 
 class GCCause : public AllStatic {
  public:
@@ -48,6 +51,7 @@
     _heap_dump,
     _wb_young_gc,
     _wb_conc_mark,
+    _wb_full_gc,
     _update_allocation_context_stats_inc,
     _update_allocation_context_stats_full,
 
@@ -60,6 +64,7 @@
 
     _tenured_generation_full,
     _metadata_GC_threshold,
+    _metadata_GC_clear_soft_refs,
 
     _cms_generation_full,
     _cms_initial_mark,
@@ -73,8 +78,6 @@
     _g1_inc_collection_pause,
     _g1_humongous_allocation,
 
-    _last_ditch_collection,
-
     _dcmd_gc_run,
 
     _last_gc_cause
@@ -103,22 +106,18 @@
     // _allocation_failure is the generic cause a collection which could result
     // in the collection of the tenured generation if there is not enough space
     // in the tenured generation to support a young GC.
-    // _last_ditch_collection is a collection done to include SoftReferences.
     return (cause == GCCause::_tenured_generation_full ||
             cause == GCCause::_cms_generation_full ||
             cause == GCCause::_adaptive_size_policy ||
-            cause == GCCause::_allocation_failure ||
-            cause == GCCause::_last_ditch_collection);
+            cause == GCCause::_allocation_failure);
   }
 
   // Causes for collection of the young generation
   inline static bool is_allocation_failure_gc(GCCause::Cause cause) {
     // _allocation_failure is the generic cause a collection for allocation failure
     // _adaptive_size_policy is for a collecton done before a full GC
-    // _last_ditch_collection is a collection done to include SoftReferences.
     return (cause == GCCause::_allocation_failure ||
-            cause == GCCause::_adaptive_size_policy ||
-            cause == GCCause::_last_ditch_collection);
+            cause == GCCause::_adaptive_size_policy);
   }
 
   // Return a string describing the GCCause.
--- a/hotspot/src/share/vm/gc/shared/gcTrace.cpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/gc/shared/gcTrace.cpp	Wed Mar 23 23:36:29 2016 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 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
@@ -242,4 +242,12 @@
                                 prediction_active);
 }
 
+void G1OldTracer::report_gc_start_impl(GCCause::Cause cause, const Ticks& timestamp) {
+  _shared_gc_info.set_start_timestamp(timestamp);
+}
+
+void G1OldTracer::set_gc_cause(GCCause::Cause cause) {
+  _shared_gc_info.set_cause(cause);
+}
+
 #endif
--- a/hotspot/src/share/vm/gc/shared/gcTrace.hpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/gc/shared/gcTrace.hpp	Wed Mar 23 23:36:29 2016 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 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
@@ -126,7 +126,7 @@
 
  protected:
   GCTracer(GCName name) : _shared_gc_info(name) {}
-  void report_gc_start_impl(GCCause::Cause cause, const Ticks& timestamp);
+  virtual void report_gc_start_impl(GCCause::Cause cause, const Ticks& timestamp);
   virtual void report_gc_end_impl(const Ticks& timestamp, TimePartitions* time_partitions);
 
  private:
@@ -297,8 +297,11 @@
 };
 
 class G1OldTracer : public OldGCTracer {
+ protected:
+  void report_gc_start_impl(GCCause::Cause cause, const Ticks& timestamp);
  public:
   G1OldTracer() : OldGCTracer(G1Old) {}
+  void set_gc_cause(GCCause::Cause cause);
 };
 
 #endif // SHARE_VM_GC_SHARED_GCTRACE_HPP
--- a/hotspot/src/share/vm/gc/shared/gcTraceTime.inline.hpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/gc/shared/gcTraceTime.inline.hpp	Wed Mar 23 23:36:29 2016 +0100
@@ -33,7 +33,6 @@
 #include "memory/universe.hpp"
 #include "prims/jni_md.h"
 #include "utilities/ticks.hpp"
-#include "runtime/timer.hpp"
 
 #define LOG_STOP_TIME_FORMAT "(%.3fs, %.3fs) %.3fms"
 #define LOG_STOP_HEAP_FORMAT SIZE_FORMAT "M->" SIZE_FORMAT "M("  SIZE_FORMAT "M)"
--- a/hotspot/src/share/vm/gc/shared/genCollectedHeap.cpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/gc/shared/genCollectedHeap.cpp	Wed Mar 23 23:36:29 2016 +0100
@@ -295,7 +295,8 @@
 }
 
 bool GenCollectedHeap::must_clear_all_soft_refs() {
-  return _gc_cause == GCCause::_last_ditch_collection;
+  return _gc_cause == GCCause::_metadata_GC_clear_soft_refs ||
+         _gc_cause == GCCause::_wb_full_gc;
 }
 
 bool GenCollectedHeap::should_do_concurrent_full_gc(GCCause::Cause cause) {
@@ -315,7 +316,7 @@
                                           bool is_tlab, bool run_verification, bool clear_soft_refs,
                                           bool restore_marks_for_biased_locking) {
   FormatBuffer<> title("Collect gen: %s", gen->short_name());
-  GCTraceTime(Debug, gc) t1(title);
+  GCTraceTime(Trace, gc, phases) t1(title);
   TraceCollectorStats tcs(gen->counters());
   TraceMemoryManagerStats tmms(gen->kind(),gc_cause());
 
@@ -684,15 +685,8 @@
   _process_strong_tasks->all_tasks_completed(scope->n_threads());
 }
 
-
-class AlwaysTrueClosure: public BoolObjectClosure {
-public:
-  bool do_object_b(oop p) { return true; }
-};
-static AlwaysTrueClosure always_true;
-
 void GenCollectedHeap::gen_process_weak_roots(OopClosure* root_closure) {
-  JNIHandles::weak_oops_do(&always_true, root_closure);
+  JNIHandles::weak_oops_do(root_closure);
   _young_gen->ref_processor()->weak_oops_do(root_closure);
   _old_gen->ref_processor()->weak_oops_do(root_closure);
 }
@@ -1272,7 +1266,7 @@
   // back a time later than 'now'.
   jlong retVal = now - tolgc_cl.time();
   if (retVal < 0) {
-    NOT_PRODUCT(warning("time warp: " JLONG_FORMAT, retVal);)
+    NOT_PRODUCT(log_warning(gc)("time warp: " JLONG_FORMAT, retVal);)
     return 0;
   }
   return retVal;
@@ -1281,7 +1275,7 @@
 void GenCollectedHeap::stop() {
 #if INCLUDE_ALL_GCS
   if (UseConcMarkSweepGC) {
-    ConcurrentMarkSweepThread::stop();
+    ConcurrentMarkSweepThread::cmst()->stop();
   }
 #endif
 }
--- a/hotspot/src/share/vm/gc/shared/genCollectedHeap.hpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/gc/shared/genCollectedHeap.hpp	Wed Mar 23 23:36:29 2016 +0100
@@ -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
@@ -281,6 +281,10 @@
     return UseConcMarkSweepGC;
   }
 
+  virtual bool needs_reference_pending_list_locker_thread() const {
+    return UseConcMarkSweepGC;
+  }
+
   // We don't need barriers for stores to objects in the
   // young gen and, a fortiori, for initializing stores to
   // objects therein. This applies to DefNew+Tenured and ParNew+CMS
--- a/hotspot/src/share/vm/gc/shared/generation.hpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/gc/shared/generation.hpp	Wed Mar 23 23:36:29 2016 +0100
@@ -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
@@ -27,6 +27,7 @@
 
 #include "gc/shared/collectorCounters.hpp"
 #include "gc/shared/referenceProcessor.hpp"
+#include "logging/log.hpp"
 #include "memory/allocation.hpp"
 #include "memory/memRegion.hpp"
 #include "memory/universe.hpp"
@@ -377,7 +378,7 @@
     // have to guard against non-monotonicity.
     NOT_PRODUCT(
       if (now < _time_of_last_gc) {
-        warning("time warp: " JLONG_FORMAT " to " JLONG_FORMAT, _time_of_last_gc, now);
+        log_warning(gc)("time warp: " JLONG_FORMAT " to " JLONG_FORMAT, _time_of_last_gc, now);
       }
     )
     return _time_of_last_gc;
--- a/hotspot/src/share/vm/gc/shared/plab.cpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/gc/shared/plab.cpp	Wed Mar 23 23:36:29 2016 +0100
@@ -136,7 +136,7 @@
 
 // Calculates plab size for current number of gc worker threads.
 size_t PLABStats::desired_plab_sz(uint no_of_gc_workers) {
-  return MAX2(min_size(), (size_t)align_object_size(_desired_net_plab_sz / no_of_gc_workers));
+  return (size_t)align_object_size(MIN2(MAX2(min_size(), _desired_net_plab_sz / no_of_gc_workers), max_size()));
 }
 
 // Compute desired plab size for one gc worker thread and latch result for later
@@ -175,14 +175,9 @@
   size_t recent_plab_sz = used / target_refills;
   // Take historical weighted average
   _filter.sample(recent_plab_sz);
-  // Clip from above and below, and align to object boundary
-  size_t new_plab_sz = MAX2(min_size(), (size_t)_filter.average());
-  new_plab_sz = MIN2(max_size(), new_plab_sz);
-  new_plab_sz = align_object_size(new_plab_sz);
-  // Latch the result
-  _desired_net_plab_sz = new_plab_sz;
+  _desired_net_plab_sz = MAX2(min_size(), (size_t)_filter.average());
 
-  log_sizing(recent_plab_sz, new_plab_sz);
+  log_sizing(recent_plab_sz, _desired_net_plab_sz);
 
   reset();
 }
--- a/hotspot/src/share/vm/gc/shared/preservedMarks.cpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/gc/shared/preservedMarks.cpp	Wed Mar 23 23:36:29 2016 +0100
@@ -62,9 +62,14 @@
 }
 
 void PreservedMarksSet::restore() {
+  size_t total_size = 0;
   for (uint i = 0; i < _num; i += 1) {
+    total_size += get(i)->size();
     get(i)->restore();
   }
+  assert_empty();
+
+  log_trace(gc)("Restored " SIZE_FORMAT " marks", total_size);
 }
 
 void PreservedMarksSet::reclaim() {
--- a/hotspot/src/share/vm/gc/shared/preservedMarks.hpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/gc/shared/preservedMarks.hpp	Wed Mar 23 23:36:29 2016 +0100
@@ -53,6 +53,7 @@
 
 public:
   bool is_empty() const { return _stack.is_empty(); }
+  size_t size() const { return _stack.size(); }
   inline void push_if_necessary(oop obj, markOop m);
   // Iterate over the stack, restore the preserved marks, then reclaim
   // the memory taken up by stack chunks.
@@ -65,7 +66,7 @@
   virtual void do_object(oop obj);
 };
 
-class PreservedMarksSet VALUE_OBJ_CLASS_SPEC {
+class PreservedMarksSet : public CHeapObj<mtGC> {
 private:
   // true -> _stacks will be allocated in the C heap
   // false -> _stacks will be allocated in the resource arena
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/gc/shared/referencePendingListLocker.cpp	Wed Mar 23 23:36:29 2016 +0100
@@ -0,0 +1,222 @@
+/*
+ * 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 "classfile/javaClasses.hpp"
+#include "classfile/systemDictionary.hpp"
+#include "gc/shared/collectedHeap.hpp"
+#include "gc/shared/referencePendingListLocker.hpp"
+#include "memory/universe.hpp"
+#include "runtime/javaCalls.hpp"
+#include "utilities/preserveException.hpp"
+
+ReferencePendingListLockerThread::ReferencePendingListLockerThread() :
+  JavaThread(&start),
+  _monitor(Monitor::nonleaf, "ReferencePendingListLocker", false, Monitor::_safepoint_check_sometimes),
+  _message(NONE) {}
+
+ReferencePendingListLockerThread* ReferencePendingListLockerThread::create(TRAPS) {
+  // Create Java thread objects
+  instanceKlassHandle thread_klass = SystemDictionary::resolve_or_fail(vmSymbols::java_lang_Thread(), true, CHECK_NULL);
+  instanceHandle thread_object = thread_klass->allocate_instance_handle(CHECK_NULL);
+  Handle thread_name = java_lang_String::create_from_str("Reference Pending List Locker", CHECK_NULL);
+  Handle thread_group = Universe::system_thread_group();
+  JavaValue result(T_VOID);
+  JavaCalls::call_special(&result,
+                          thread_object,
+                          thread_klass,
+                          vmSymbols::object_initializer_name(),
+                          vmSymbols::threadgroup_string_void_signature(),
+                          thread_group,
+                          thread_name,
+                          CHECK_NULL);
+
+  {
+    MutexLocker ml(Threads_lock);
+
+    // Allocate thread
+    ReferencePendingListLockerThread* thread = new ReferencePendingListLockerThread();
+    if (thread == NULL || thread->osthread() == NULL) {
+      vm_exit_during_initialization("java.lang.OutOfMemoryError",
+                                    os::native_thread_creation_failed_msg());
+    }
+
+    // Initialize thread
+    java_lang_Thread::set_thread(thread_object(), thread);
+    java_lang_Thread::set_priority(thread_object(), NearMaxPriority);
+    java_lang_Thread::set_daemon(thread_object());
+    thread->set_threadObj(thread_object());
+
+    // Start thread
+    Threads::add(thread);
+    Thread::start(thread);
+
+    return thread;
+  }
+}
+
+void ReferencePendingListLockerThread::start(JavaThread* thread, TRAPS) {
+  ReferencePendingListLockerThread* locker_thread = static_cast<ReferencePendingListLockerThread*>(thread);
+  locker_thread->receive_and_handle_messages();
+}
+
+bool ReferencePendingListLockerThread::is_hidden_from_external_view() const {
+  return true;
+}
+
+void ReferencePendingListLockerThread::send_message(Message message) {
+  assert(message != NONE, "Should not be none");
+  MonitorLockerEx ml(&_monitor, Monitor::_no_safepoint_check_flag);
+
+  // Wait for completion of current message
+  while (_message != NONE) {
+    ml.wait(Monitor::_no_safepoint_check_flag);
+  }
+
+  // Send new message
+  _message = message;
+  ml.notify_all();
+
+  // Wait for completion of new message
+  while (_message != NONE) {
+    ml.wait(Monitor::_no_safepoint_check_flag);
+  }
+}
+
+void ReferencePendingListLockerThread::receive_and_handle_messages() {
+  ReferencePendingListLocker pending_list_locker;
+  MonitorLockerEx ml(&_monitor);
+
+  // Main loop, never terminates
+  for (;;) {
+    // Wait for message
+    while (_message == NONE) {
+      ml.wait();
+    }
+
+    // Handle message
+    if (_message == LOCK) {
+      pending_list_locker.lock();
+    } else if (_message == UNLOCK) {
+      pending_list_locker.unlock();
+    } else {
+      ShouldNotReachHere();
+    }
+
+    // Clear message
+    _message = NONE;
+    ml.notify_all();
+  }
+}
+
+void ReferencePendingListLockerThread::lock() {
+  send_message(LOCK);
+}
+
+void ReferencePendingListLockerThread::unlock() {
+  send_message(UNLOCK);
+}
+
+bool ReferencePendingListLocker::_is_initialized = false;
+ReferencePendingListLockerThread* ReferencePendingListLocker::_locker_thread = NULL;
+
+void ReferencePendingListLocker::initialize(bool needs_locker_thread, TRAPS) {
+  if (needs_locker_thread) {
+    _locker_thread = ReferencePendingListLockerThread::create(CHECK);
+  }
+
+  _is_initialized = true;
+}
+
+bool ReferencePendingListLocker::is_initialized() {
+  return _is_initialized;
+}
+
+bool ReferencePendingListLocker::is_locked_by_self() {
+  oop pending_list_lock = java_lang_ref_Reference::pending_list_lock();
+  if (pending_list_lock == NULL) {
+    return false;
+  }
+
+  JavaThread* thread = JavaThread::current();
+  Handle handle(thread, pending_list_lock);
+  return ObjectSynchronizer::current_thread_holds_lock(thread, handle);
+}
+
+void ReferencePendingListLocker::lock() {
+  assert(!Heap_lock->owned_by_self(), "Heap_lock must not be owned by requesting thread");
+
+  if (Thread::current()->is_Java_thread()) {
+    assert(java_lang_ref_Reference::pending_list_lock() != NULL, "Not initialized");
+
+    // We may enter this with a pending exception
+    PRESERVE_EXCEPTION_MARK;
+
+    HandleMark hm;
+    Handle handle(THREAD, java_lang_ref_Reference::pending_list_lock());
+
+    // Lock
+    ObjectSynchronizer::fast_enter(handle, &_basic_lock, false, THREAD);
+
+    assert(is_locked_by_self(), "Locking failed");
+
+    if (HAS_PENDING_EXCEPTION) {
+      CLEAR_PENDING_EXCEPTION;
+    }
+  } else {
+    // Delegate operation to locker thread
+    assert(_locker_thread != NULL, "Locker thread not created");
+    _locker_thread->lock();
+  }
+}
+
+void ReferencePendingListLocker::unlock() {
+  if (Thread::current()->is_Java_thread()) {
+    assert(java_lang_ref_Reference::pending_list_lock() != NULL, "Not initialized");
+
+    // We may enter this with a pending exception
+    PRESERVE_EXCEPTION_MARK;
+
+    HandleMark hm;
+    Handle handle(THREAD, java_lang_ref_Reference::pending_list_lock());
+
+    assert(is_locked_by_self(), "Should be locked by self");
+
+    // Notify waiters if the pending list is non-empty
+    if (java_lang_ref_Reference::pending_list() != NULL) {
+      ObjectSynchronizer::notifyall(handle, THREAD);
+    }
+
+    // Unlock
+    ObjectSynchronizer::fast_exit(handle(), &_basic_lock, THREAD);
+
+    if (HAS_PENDING_EXCEPTION) {
+      CLEAR_PENDING_EXCEPTION;
+    }
+  } else {
+    // Delegate operation to locker thread
+    assert(_locker_thread != NULL, "Locker thread not created");
+    _locker_thread->unlock();
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/gc/shared/referencePendingListLocker.hpp	Wed Mar 23 23:36:29 2016 +0100
@@ -0,0 +1,95 @@
+/*
+ * 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_SHARED_REFERENCEPENDINGLISTLOCKER_HPP
+#define SHARE_VM_GC_SHARED_REFERENCEPENDINGLISTLOCKER_HPP
+
+#include "memory/allocation.hpp"
+#include "runtime/basicLock.hpp"
+#include "runtime/mutex.hpp"
+#include "runtime/thread.hpp"
+#include "utilities/exceptions.hpp"
+
+//
+// The ReferencePendingListLockerThread locks and unlocks the reference
+// pending list lock on behalf a non-Java thread, typically a concurrent
+// GC thread. This interface should not be directly accessed. All uses
+// should instead go through the ReferencePendingListLocker, which calls
+// this thread if needed.
+//
+class ReferencePendingListLockerThread : public JavaThread {
+private:
+  enum Message {
+    NONE,
+    LOCK,
+    UNLOCK
+  };
+
+  Monitor _monitor;
+  Message _message;
+
+  ReferencePendingListLockerThread();
+
+  static void start(JavaThread* thread, TRAPS);
+
+  void send_message(Message message);
+  void receive_and_handle_messages();
+
+public:
+  static ReferencePendingListLockerThread* create(TRAPS);
+
+  virtual bool is_hidden_from_external_view() const;
+
+  void lock();
+  void unlock();
+};
+
+//
+// The ReferencePendingListLocker is the main interface for locking and
+// unlocking the reference pending list lock, which needs to be held by
+// the GC when adding references to the pending list. Since this is a
+// Java-level monitor it can only be locked/unlocked by a Java thread.
+// For this reason there is an option to spawn a helper thread, the
+// ReferencePendingListLockerThread, during initialization. If a helper
+// thread is spawned all lock operations from non-Java threads will be
+// delegated to the helper thread. The helper thread is typically needed
+// by concurrent GCs.
+//
+class ReferencePendingListLocker VALUE_OBJ_CLASS_SPEC {
+private:
+  static bool                              _is_initialized;
+  static ReferencePendingListLockerThread* _locker_thread;
+  BasicLock                                _basic_lock;
+
+public:
+  static void initialize(bool needs_locker_thread, TRAPS);
+  static bool is_initialized();
+
+  static bool is_locked_by_self();
+
+  void lock();
+  void unlock();
+};
+
+#endif // SHARE_VM_GC_SHARED_REFERENCEPENDINGLISTLOCKER_HPP
--- a/hotspot/src/share/vm/gc/shared/referenceProcessor.cpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/gc/shared/referenceProcessor.cpp	Wed Mar 23 23:36:29 2016 +0100
@@ -134,7 +134,7 @@
   guarantee(!_discovering_refs, "Discovering refs?");
   for (uint i = 0; i < _max_num_q * number_of_subclasses_of_ref(); i++) {
     guarantee(_discovered_refs[i].is_empty(),
-              "Found non-empty discovered list");
+              "Found non-empty discovered list at %u", i);
   }
 }
 #endif
@@ -161,8 +161,8 @@
 
   NOT_PRODUCT(
   if (now < _soft_ref_timestamp_clock) {
-    warning("time warp: " JLONG_FORMAT " to " JLONG_FORMAT,
-            _soft_ref_timestamp_clock, now);
+    log_warning(gc)("time warp: " JLONG_FORMAT " to " JLONG_FORMAT,
+                    _soft_ref_timestamp_clock, now);
   }
   )
   // The values of now and _soft_ref_timestamp_clock are set using
@@ -266,11 +266,6 @@
 #ifndef PRODUCT
 // Calculate the number of jni handles.
 size_t ReferenceProcessor::count_jni_refs() {
-  class AlwaysAliveClosure: public BoolObjectClosure {
-  public:
-    virtual bool do_object_b(oop obj) { return true; }
-  };
-
   class CountHandleClosure: public OopClosure {
   private:
     size_t _count;
@@ -281,8 +276,7 @@
     size_t count() { return _count; }
   };
   CountHandleClosure global_handle_count;
-  AlwaysAliveClosure always_alive;
-  JNIHandles::weak_oops_do(&always_alive, &global_handle_count);
+  JNIHandles::weak_oops_do(&global_handle_count);
   return global_handle_count.count();
 }
 #endif
@@ -645,9 +639,7 @@
                     OopClosure& keep_alive,
                     VoidClosure& complete_gc)
   {
-    Thread* thr = Thread::current();
-    int refs_list_index = ((WorkerThread*)thr)->id();
-    _ref_processor.process_phase1(_refs_lists[refs_list_index], _policy,
+    _ref_processor.process_phase1(_refs_lists[i], _policy,
                                   &is_alive, &keep_alive, &complete_gc);
   }
 private:
@@ -683,11 +675,6 @@
                     OopClosure& keep_alive,
                     VoidClosure& complete_gc)
   {
-    // Don't use "refs_list_index" calculated in this way because
-    // balance_queues() has moved the Ref's into the first n queues.
-    // Thread* thr = Thread::current();
-    // int refs_list_index = ((WorkerThread*)thr)->id();
-    // _ref_processor.process_phase3(_refs_lists[refs_list_index], _clear_referent,
     _ref_processor.process_phase3(_refs_lists[i], _clear_referent,
                                   &is_alive, &keep_alive, &complete_gc);
   }
@@ -696,19 +683,30 @@
 };
 
 #ifndef PRODUCT
-void ReferenceProcessor::log_reflist_counts(DiscoveredList ref_lists[], size_t total_refs) {
+void ReferenceProcessor::log_reflist_counts(DiscoveredList ref_lists[], uint active_length, size_t total_refs) {
   if (!log_is_enabled(Trace, gc, ref)) {
     return;
   }
 
   stringStream st;
-  for (uint i = 0; i < _max_num_q; ++i) {
+  for (uint i = 0; i < active_length; ++i) {
     st.print(SIZE_FORMAT " ", ref_lists[i].length());
   }
   log_develop_trace(gc, ref)("%s= " SIZE_FORMAT, st.as_string(), total_refs);
+#ifdef ASSERT
+  for (uint i = active_length; i < _max_num_q; i++) {
+    assert(ref_lists[i].length() == 0, SIZE_FORMAT " unexpected References in %u",
+           ref_lists[i].length(), i);
+  }
+#endif
 }
 #endif
 
+void ReferenceProcessor::set_active_mt_degree(uint v) {
+  _num_q = v;
+  _next_id = 0;
+}
+
 // Balances reference queues.
 // Move entries from all queues[0, 1, ..., _max_num_q-1] to
 // queues[0, 1, ..., _num_q-1] because only the first _num_q
@@ -721,8 +719,8 @@
 
   for (uint i = 0; i < _max_num_q; ++i) {
     total_refs += ref_lists[i].length();
-    }
-  log_reflist_counts(ref_lists, total_refs);
+  }
+  log_reflist_counts(ref_lists, _max_num_q, total_refs);
   size_t avg_refs = total_refs / _num_q + 1;
   uint to_idx = 0;
   for (uint from_idx = 0; from_idx < _max_num_q; from_idx++) {
@@ -784,10 +782,10 @@
   }
 #ifdef ASSERT
   size_t balanced_total_refs = 0;
-  for (uint i = 0; i < _max_num_q; ++i) {
+  for (uint i = 0; i < _num_q; ++i) {
     balanced_total_refs += ref_lists[i].length();
-    }
-  log_reflist_counts(ref_lists, balanced_total_refs);
+  }
+  log_reflist_counts(ref_lists, _num_q, balanced_total_refs);
   assert(total_refs == balanced_total_refs, "Balancing was incomplete");
 #endif
 }
@@ -881,7 +879,7 @@
       id = next_id();
     }
   }
-  assert(id < _max_num_q, "Id is out-of-bounds (call Freud?)");
+  assert(id < _max_num_q, "Id is out-of-bounds id %u and max id %u)", id, _max_num_q);
 
   // Get the discovered queue to which we will add
   DiscoveredList* list = NULL;
--- a/hotspot/src/share/vm/gc/shared/referenceProcessor.hpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/gc/shared/referenceProcessor.hpp	Wed Mar 23 23:36:29 2016 +0100
@@ -225,7 +225,7 @@
 
   uint num_q()                             { return _num_q; }
   uint max_num_q()                         { return _max_num_q; }
-  void set_active_mt_degree(uint v)        { _num_q = v; }
+  void set_active_mt_degree(uint v);
 
   DiscoveredList* discovered_refs()        { return _discovered_refs; }
 
@@ -326,9 +326,11 @@
   // round-robin mod _num_q (not: _not_ mode _max_num_q)
   uint next_id() {
     uint id = _next_id;
+    assert(!_discovery_is_mt, "Round robin should only be used in serial discovery");
     if (++_next_id == _num_q) {
       _next_id = 0;
     }
+    assert(_next_id < _num_q, "_next_id %u _num_q %u _max_num_q %u", _next_id, _num_q, _max_num_q);
     return id;
   }
   DiscoveredList* get_discovered_list(ReferenceType rt);
@@ -340,7 +342,7 @@
   // Calculate the number of jni handles.
   size_t count_jni_refs();
 
-  void log_reflist_counts(DiscoveredList ref_lists[], size_t total_count) PRODUCT_RETURN;
+  void log_reflist_counts(DiscoveredList ref_lists[], uint active_length, size_t total_count) PRODUCT_RETURN;
 
   // Balances reference queues.
   void balance_queues(DiscoveredList ref_lists[]);
--- a/hotspot/src/share/vm/gc/shared/spaceDecorator.cpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/gc/shared/spaceDecorator.cpp	Wed Mar 23 23:36:29 2016 +0100
@@ -84,9 +84,7 @@
 void SpaceMangler::mangle_region(MemRegion mr) {
   assert(ZapUnusedHeapArea, "Mangling should not be in use");
 #ifdef ASSERT
-  log_develop_trace(gc)("Mangling [" PTR_FORMAT " to " PTR_FORMAT ")", p2i(mr.start()), p2i(mr.end()));
   Copy::fill_to_words(mr.start(), mr.word_size(), badHeapWord);
-  log_develop_trace(gc)("Mangling done.");
 #endif
 }
 
--- a/hotspot/src/share/vm/gc/shared/taskqueue.hpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/gc/shared/taskqueue.hpp	Wed Mar 23 23:36:29 2016 +0100
@@ -248,7 +248,6 @@
 
 template <class E, MEMFLAGS F, unsigned int N = TASKQUEUE_SIZE>
 class GenericTaskQueue: public TaskQueueSuper<N, F> {
-  ArrayAllocator<E, F> _array_allocator;
 protected:
   typedef typename TaskQueueSuper<N, F>::Age Age;
   typedef typename TaskQueueSuper<N, F>::idx_t idx_t;
--- a/hotspot/src/share/vm/gc/shared/taskqueue.inline.hpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/gc/shared/taskqueue.inline.hpp	Wed Mar 23 23:36:29 2016 +0100
@@ -44,12 +44,13 @@
 
 template<class E, MEMFLAGS F, unsigned int N>
 inline void GenericTaskQueue<E, F, N>::initialize() {
-  _elems = _array_allocator.allocate(N);
+  _elems = ArrayAllocator<E, F>::allocate(N);
 }
 
 template<class E, MEMFLAGS F, unsigned int N>
 inline GenericTaskQueue<E, F, N>::~GenericTaskQueue() {
-  FREE_C_HEAP_ARRAY(E, _elems);
+  assert(false, "This code is currently never called");
+  ArrayAllocator<E, F>::free(const_cast<E*>(_elems), N);
 }
 
 template<class E, MEMFLAGS F, unsigned int N>
--- a/hotspot/src/share/vm/gc/shared/threadLocalAllocBuffer.inline.hpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/gc/shared/threadLocalAllocBuffer.inline.hpp	Wed Mar 23 23:36:29 2016 +0100
@@ -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
@@ -61,7 +61,7 @@
   // unsafe_max_tlab_alloc is just a hint.
   const size_t available_size = Universe::heap()->unsafe_max_tlab_alloc(myThread()) /
                                                   HeapWordSize;
-  size_t new_tlab_size = MIN2(available_size, desired_size() + aligned_obj_size);
+  size_t new_tlab_size = MIN3(available_size, desired_size() + aligned_obj_size, max_size());
 
   // Make sure there's enough room for object and filler int[].
   const size_t obj_plus_filler_size = aligned_obj_size + alignment_reserve();
--- a/hotspot/src/share/vm/gc/shared/vmGCOperations.cpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/gc/shared/vmGCOperations.cpp	Wed Mar 23 23:36:29 2016 +0100
@@ -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
@@ -30,10 +30,8 @@
 #include "gc/shared/gcLocker.inline.hpp"
 #include "gc/shared/genCollectedHeap.hpp"
 #include "gc/shared/vmGCOperations.hpp"
+#include "logging/log.hpp"
 #include "memory/oopFactory.hpp"
-#include "logging/log.hpp"
-#include "oops/instanceKlass.hpp"
-#include "oops/instanceRefKlass.hpp"
 #include "runtime/handles.inline.hpp"
 #include "runtime/init.hpp"
 #include "runtime/interfaceSupport.hpp"
@@ -64,14 +62,11 @@
 }
 
 void VM_GC_Operation::acquire_pending_list_lock() {
-  // we may enter this with pending exception set
-  InstanceRefKlass::acquire_pending_list_lock(&_pending_list_basic_lock);
+  _pending_list_locker.lock();
 }
 
-
 void VM_GC_Operation::release_and_notify_pending_list_lock() {
-
-  InstanceRefKlass::release_and_notify_pending_list_lock(&_pending_list_basic_lock);
+  _pending_list_locker.unlock();
 }
 
 // Allocations may fail in several threads at about the same time,
@@ -160,7 +155,7 @@
       // be about to attempt holds value for us only
       // if it happens now and not if it happens in the eventual
       // future.
-      warning("GC locker is held; pre-dump GC was skipped");
+      log_warning(gc)("GC locker is held; pre-dump GC was skipped");
     }
   }
   HeapInspection inspect(_csv_format, _print_help, _print_class_stats,
@@ -276,12 +271,8 @@
     return;
   }
 
-  // If expansion failed, do a last-ditch collection and try allocating
-  // again.  A last-ditch collection will clear softrefs.  This
-  // behavior is similar to the last-ditch collection done for perm
-  // gen when it was full and a collection for failed allocation
-  // did not free perm gen space.
-  heap->collect_as_vm_thread(GCCause::_last_ditch_collection);
+  // If expansion failed, do a collection clearing soft references.
+  heap->collect_as_vm_thread(GCCause::_metadata_GC_clear_soft_refs);
   _result = _loader_data->metaspace_non_null()->allocate(_size, _mdtype);
   if (_result != NULL) {
     return;
--- a/hotspot/src/share/vm/gc/shared/vmGCOperations.hpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/gc/shared/vmGCOperations.hpp	Wed Mar 23 23:36:29 2016 +0100
@@ -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
@@ -27,6 +27,7 @@
 
 #include "gc/shared/collectedHeap.hpp"
 #include "gc/shared/genCollectedHeap.hpp"
+#include "gc/shared/referencePendingListLocker.hpp"
 #include "memory/heapInspection.hpp"
 #include "prims/jvmtiExport.hpp"
 #include "runtime/handles.hpp"
@@ -69,8 +70,10 @@
 //
 
 class VM_GC_Operation: public VM_Operation {
+ private:
+  ReferencePendingListLocker _pending_list_locker;
+
  protected:
-  BasicLock      _pending_list_basic_lock; // for refs pending list notification (PLL)
   uint           _gc_count_before;         // gc count before acquiring PLL
   uint           _full_gc_count_before;    // full gc count before acquiring PLL
   bool           _full;                    // whether a "full" collection
--- a/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp	Wed Mar 23 23:36:29 2016 +0100
@@ -138,11 +138,11 @@
     BytecodeHistogram::_counters[(Bytecodes::Code)opcode]++;                                         \
     if (StopInterpreterAt && StopInterpreterAt == BytecodeCounter::_counter_value) os::breakpoint(); \
     if (TraceBytecodes) {                                                                            \
-      CALL_VM((void)SharedRuntime::trace_bytecode(THREAD, 0,               \
-                                   topOfStack[Interpreter::expr_index_at(1)],   \
-                                   topOfStack[Interpreter::expr_index_at(2)]),  \
-                                   handle_exception);                      \
-    }                                                                      \
+      CALL_VM((void)InterpreterRuntime::trace_bytecode(THREAD, 0,                    \
+                                        topOfStack[Interpreter::expr_index_at(1)],   \
+                                        topOfStack[Interpreter::expr_index_at(2)]),  \
+                                        handle_exception);                           \
+    }                                                                                \
 }
 #endif
 
--- a/hotspot/src/share/vm/interpreter/cppInterpreter.cpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/interpreter/cppInterpreter.cpp	Wed Mar 23 23:36:29 2016 +0100
@@ -27,7 +27,7 @@
 #include "interpreter/cppInterpreterGenerator.hpp"
 #include "interpreter/interpreter.hpp"
 #include "interpreter/interpreterRuntime.hpp"
-#include "runtime/logTimer.hpp"
+#include "runtime/timerTrace.hpp"
 
 #ifdef CC_INTERP
 
@@ -43,7 +43,7 @@
 
   // generate interpreter
   { ResourceMark rm;
-    TraceStartupTime timer("Interpreter generation");
+    TraceTime timer("Interpreter generation", TRACETIME_LOG(Info, startuptime));
     int code_size = InterpreterCodeSize;
     NOT_PRODUCT(code_size *= 4;)  // debug uses extra interpreter code space
     _code = new StubQueue(new InterpreterCodeletInterface, code_size, NULL,
--- a/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp	Wed Mar 23 23:36:29 2016 +0100
@@ -173,9 +173,6 @@
 
 
 IRT_ENTRY(void, InterpreterRuntime::anewarray(JavaThread* thread, ConstantPool* pool, int index, jint size))
-  // Note: no oopHandle for pool & klass needed since they are not used
-  //       anymore after new_objArray() and no GC can happen before.
-  //       (This may have to change if this code changes!)
   Klass*    klass = pool->klass_at(index, CHECK);
   objArrayOop obj = oopFactory::new_objArray(klass, size, CHECK);
   thread->set_vm_result(obj);
@@ -1414,3 +1411,17 @@
   }
 IRT_END
 #endif // INCLUDE_JVMTI
+
+#ifndef PRODUCT
+// This must be a IRT_LEAF function because the interpreter must save registers on x86 to
+// call this, which changes rsp and makes the interpreter's expression stack not walkable.
+// The generated code still uses call_VM because that will set up the frame pointer for
+// bcp and method.
+IRT_LEAF(intptr_t, InterpreterRuntime::trace_bytecode(JavaThread* thread, intptr_t preserve_this_value, intptr_t tos, intptr_t tos2))
+  const frame f = thread->last_frame();
+  assert(f.is_interpreted_frame(), "must be an interpreted frame");
+  methodHandle mh(thread, f.interpreter_frame_method());
+  BytecodeTracer::trace(mh, f.interpreter_frame_bcp(), tos, tos2);
+  return preserve_this_value;
+IRT_END
+#endif // !PRODUCT
--- a/hotspot/src/share/vm/interpreter/interpreterRuntime.hpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/interpreter/interpreterRuntime.hpp	Wed Mar 23 23:36:29 2016 +0100
@@ -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
@@ -166,6 +166,9 @@
   static void popframe_move_outgoing_args(JavaThread* thread, void* src_address, void* dest_address);
 #endif
 
+  // bytecode tracing is only used by the TraceBytecodes
+  static intptr_t trace_bytecode(JavaThread* thread, intptr_t preserve_this_value, intptr_t tos, intptr_t tos2) PRODUCT_RETURN0;
+
   // Platform dependent stuff
 #ifdef TARGET_ARCH_x86
 # include "interpreterRT_x86.hpp"
--- a/hotspot/src/share/vm/interpreter/templateInterpreter.cpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/interpreter/templateInterpreter.cpp	Wed Mar 23 23:36:29 2016 +0100
@@ -31,7 +31,7 @@
 #include "interpreter/templateInterpreterGenerator.hpp"
 #include "interpreter/templateTable.hpp"
 #include "memory/resourceArea.hpp"
-#include "runtime/logTimer.hpp"
+#include "runtime/timerTrace.hpp"
 
 #ifndef CC_INTERP
 
@@ -49,7 +49,7 @@
 
   // generate interpreter
   { ResourceMark rm;
-    TraceStartupTime timer("Interpreter generation");
+    TraceTime timer("Interpreter generation", TRACETIME_LOG(Info, startuptime));
     int code_size = InterpreterCodeSize;
     NOT_PRODUCT(code_size *= 4;)  // debug uses extra interpreter code space
 #if INCLUDE_JVMTI
--- a/hotspot/src/share/vm/interpreter/templateTable.cpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/interpreter/templateTable.cpp	Wed Mar 23 23:36:29 2016 +0100
@@ -26,7 +26,7 @@
 #include "gc/shared/collectedHeap.hpp"
 #include "interpreter/interp_masm.hpp"
 #include "interpreter/templateTable.hpp"
-#include "runtime/logTimer.hpp"
+#include "runtime/timerTrace.hpp"
 
 #ifdef CC_INTERP
 
@@ -245,7 +245,7 @@
   if (_is_initialized) return;
 
   // Initialize table
-  TraceStartupTime timer("TemplateTable initialization");
+  TraceTime timer("TemplateTable initialization", TRACETIME_LOG(Info, startuptime));
 
   _bs = Universe::heap()->barrier_set();
 
--- a/hotspot/src/share/vm/jvmci/jvmciCompilerToVM.cpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/jvmci/jvmciCompilerToVM.cpp	Wed Mar 23 23:36:29 2016 +0100
@@ -48,6 +48,7 @@
 #include "gc/g1/heapRegion.hpp"
 #include "runtime/javaCalls.hpp"
 #include "runtime/deoptimization.hpp"
+#include "runtime/timerTrace.hpp"
 #include "runtime/vframe.hpp"
 #include "runtime/vframe_hp.hpp"
 #include "runtime/vmStructs.hpp"
--- a/hotspot/src/share/vm/logging/log.cpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/logging/log.cpp	Wed Mar 23 23:36:29 2016 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 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
@@ -136,4 +136,27 @@
   LogConfiguration::parse_log_arguments("stdout", saved_config, NULL, NULL, log.error_stream());
   os::free(saved_config);
 }
+
+static int Test_logconfiguration_subscribe_triggered = 0;
+
+static void Test_logconfiguration_subscribe_helper() {
+  Test_logconfiguration_subscribe_triggered++;
+}
+
+void Test_logconfiguration_subscribe() {
+  ResourceMark rm;
+  LogHandle(logging) log;
+
+  LogConfiguration::register_update_listener(&Test_logconfiguration_subscribe_helper);
+
+  LogConfiguration::parse_log_arguments("stdout", "logging=trace", NULL, NULL, log.error_stream());
+  assert(Test_logconfiguration_subscribe_triggered == 1, "subscription not triggered (1)");
+
+  LogConfiguration::configure_stdout(LogLevel::Debug, true, LOG_TAGS(gc));
+  assert(Test_logconfiguration_subscribe_triggered == 2, "subscription not triggered (2)");
+
+  LogConfiguration::disable_logging();
+  assert(Test_logconfiguration_subscribe_triggered == 3, "subscription not triggered (3)");
+}
+
 #endif // PRODUCT
--- a/hotspot/src/share/vm/logging/logConfiguration.cpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/logging/logConfiguration.cpp	Wed Mar 23 23:36:29 2016 +0100
@@ -40,6 +40,9 @@
 LogOutput** LogConfiguration::_outputs = NULL;
 size_t      LogConfiguration::_n_outputs = 0;
 
+LogConfiguration::UpdateListenerFunction* LogConfiguration::_listener_callbacks = NULL;
+size_t      LogConfiguration::_n_listener_callbacks = 0;
+
 // Stack object to take the lock for configuring the logging.
 // Should only be held during the critical parts of the configuration
 // (when calling configure_output or reading/modifying the outputs array).
@@ -254,6 +257,7 @@
   for (size_t i = 0; i < _n_outputs; i++) {
     disable_output(i);
   }
+  notify_update_listeners();
 }
 
 void LogConfiguration::configure_stdout(LogLevelType level, bool exact_match, ...) {
@@ -282,6 +286,7 @@
   // Apply configuration to stdout (output #0), with the same decorators as before.
   ConfigurationLock cl;
   configure_output(0, expr, LogOutput::Stdout->decorators());
+  notify_update_listeners();
 }
 
 bool LogConfiguration::parse_command_line_arguments(const char* opts) {
@@ -373,6 +378,7 @@
     }
   }
   configure_output(idx, expr, decorators);
+  notify_update_listeners();
   return true;
 }
 
@@ -471,3 +477,20 @@
   }
 }
 
+void LogConfiguration::register_update_listener(UpdateListenerFunction cb) {
+  assert(cb != NULL, "Should not register NULL as listener");
+  ConfigurationLock cl;
+  size_t idx = _n_listener_callbacks++;
+  _listener_callbacks = REALLOC_C_HEAP_ARRAY(UpdateListenerFunction,
+                                             _listener_callbacks,
+                                             _n_listener_callbacks,
+                                             mtLogging);
+  _listener_callbacks[idx] = cb;
+}
+
+void LogConfiguration::notify_update_listeners() {
+  assert(ConfigurationLock::current_thread_has_lock(), "notify_update_listeners must be called in ConfigurationLock scope (lock held)");
+  for (size_t i = 0; i < _n_listener_callbacks; i++) {
+    _listener_callbacks[i]();
+  }
+}
--- a/hotspot/src/share/vm/logging/logConfiguration.hpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/logging/logConfiguration.hpp	Wed Mar 23 23:36:29 2016 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 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,10 +37,26 @@
 // kept implicitly in the LogTagSets and their LogOutputLists. During configuration the tagsets
 // are iterated over and updated accordingly.
 class LogConfiguration : public AllStatic {
+ public:
+  // Function for listeners
+  typedef void (*UpdateListenerFunction)(void);
+
+  // Register callback for config change.
+  // The callback is always called with ConfigurationLock held,
+  // hence doing log reconfiguration from the callback will deadlock.
+  // The main Java thread may call this callback if there is an early registration
+  // else the attach listener JavaThread, started via diagnostic command, will be executing thread.
+  // The main purpose of this callback is to see if a loglevel have been changed.
+  // There is no way to unregister.
+  static void register_update_listener(UpdateListenerFunction cb);
+
  private:
   static LogOutput**  _outputs;
   static size_t       _n_outputs;
 
+  static UpdateListenerFunction*    _listener_callbacks;
+  static size_t                     _n_listener_callbacks;
+
   // Create a new output. Returns NULL if failed.
   static LogOutput* new_output(char* name, const char* options, outputStream* errstream);
 
@@ -60,6 +76,9 @@
   // Configure output (add or update existing configuration) to log on tag-level combination using specified decorators.
   static void configure_output(size_t idx, const LogTagLevelExpression& tag_level_expression, const LogDecorators& decorators);
 
+  // This should be called after any configuration change while still holding ConfigurationLock
+  static void notify_update_listeners();
+
  public:
   // Initialization and finalization of log configuration, to be run at vm startup and shutdown respectively.
   static void initialize(jlong vm_start_time);
--- a/hotspot/src/share/vm/logging/logFileOutput.cpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/logging/logFileOutput.cpp	Wed Mar 23 23:36:29 2016 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 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
@@ -64,7 +64,7 @@
     }
     if (fclose(_stream) != 0) {
       jio_fprintf(defaultStream::error_stream(), "Could not close log file '%s' (%s).\n",
-                  _file_name, strerror(errno));
+                  _file_name, os::strerror(errno));
     }
   }
   os::free(_archive_name);
@@ -139,7 +139,7 @@
   }
   _stream = fopen(_file_name, FileOpenMode);
   if (_stream == NULL) {
-    log_error(logging)("Could not open log file '%s' (%s).\n", _file_name, strerror(errno));
+    log_error(logging)("Could not open log file '%s' (%s).\n", _file_name, os::strerror(errno));
     return false;
   }
   return true;
@@ -176,7 +176,7 @@
   // Rename the file from ex hotspot.log to hotspot.log.2
   if (rename(_file_name, _archive_name) == -1) {
     jio_fprintf(defaultStream::error_stream(), "Could not rename log file '%s' to '%s' (%s).\n",
-                _file_name, _archive_name, strerror(errno));
+                _file_name, _archive_name, os::strerror(errno));
   }
 }
 
@@ -194,7 +194,7 @@
 
   if (fclose(_stream)) {
     jio_fprintf(defaultStream::error_stream(), "Error closing file '%s' during log rotation (%s).\n",
-                _file_name, strerror(errno));
+                _file_name, os::strerror(errno));
   }
 
   // Archive the current log file
@@ -204,7 +204,7 @@
   _stream = fopen(_file_name, FileOpenMode);
   if (_stream == NULL) {
     jio_fprintf(defaultStream::error_stream(), "Could not reopen file '%s' during log rotation (%s).\n",
-                _file_name, strerror(errno));
+                _file_name, os::strerror(errno));
     return;
   }
 
--- a/hotspot/src/share/vm/logging/logPrefix.hpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/logging/logPrefix.hpp	Wed Mar 23 23:36:29 2016 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 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
@@ -42,19 +42,21 @@
   LOG_PREFIX(GCId::print_prefix, LOG_TAGS(gc)) \
   LOG_PREFIX(GCId::print_prefix, LOG_TAGS(gc, age)) \
   LOG_PREFIX(GCId::print_prefix, LOG_TAGS(gc, alloc)) \
+  LOG_PREFIX(GCId::print_prefix, LOG_TAGS(gc, alloc, region)) \
   LOG_PREFIX(GCId::print_prefix, LOG_TAGS(gc, barrier)) \
   LOG_PREFIX(GCId::print_prefix, LOG_TAGS(gc, classhisto)) \
   LOG_PREFIX(GCId::print_prefix, LOG_TAGS(gc, compaction)) \
-  LOG_PREFIX(GCId::print_prefix, LOG_TAGS(gc, compaction, phases)) \
   LOG_PREFIX(GCId::print_prefix, LOG_TAGS(gc, cpu)) \
   LOG_PREFIX(GCId::print_prefix, LOG_TAGS(gc, ergo)) \
   LOG_PREFIX(GCId::print_prefix, LOG_TAGS(gc, ergo, cset)) \
   LOG_PREFIX(GCId::print_prefix, LOG_TAGS(gc, ergo, heap)) \
   LOG_PREFIX(GCId::print_prefix, LOG_TAGS(gc, ergo, ihop)) \
   LOG_PREFIX(GCId::print_prefix, LOG_TAGS(gc, heap)) \
+  LOG_PREFIX(GCId::print_prefix, LOG_TAGS(gc, heap, region)) \
   LOG_PREFIX(GCId::print_prefix, LOG_TAGS(gc, freelist)) \
   LOG_PREFIX(GCId::print_prefix, LOG_TAGS(gc, ihop)) \
   LOG_PREFIX(GCId::print_prefix, LOG_TAGS(gc, liveness)) \
+  LOG_PREFIX(GCId::print_prefix, LOG_TAGS(gc, marking)) \
   LOG_PREFIX(GCId::print_prefix, LOG_TAGS(gc, metaspace)) \
   LOG_PREFIX(GCId::print_prefix, LOG_TAGS(gc, phases)) \
   LOG_PREFIX(GCId::print_prefix, LOG_TAGS(gc, phases, start)) \
--- a/hotspot/src/share/vm/logging/logTag.hpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/logging/logTag.hpp	Wed Mar 23 23:36:29 2016 +0100
@@ -24,6 +24,7 @@
 #ifndef SHARE_VM_LOGGING_LOGTAG_HPP
 #define SHARE_VM_LOGGING_LOGTAG_HPP
 
+#include "logging/logTag_ext.hpp"
 #include "memory/allocation.hpp"
 #include "utilities/globalDefinitions.hpp"
 
@@ -68,28 +69,34 @@
   LOG_TAG(phases) \
   LOG_TAG(plab) \
   LOG_TAG(promotion) \
+  LOG_TAG(preorder) /* Trace all classes loaded in order referenced (not loaded) */ \
   LOG_TAG(protectiondomain) /* "Trace protection domain verification" */ \
   LOG_TAG(ref) \
   LOG_TAG(refine) \
   LOG_TAG(region) \
   LOG_TAG(remset) \
   LOG_TAG(safepoint) \
+  LOG_TAG(safepointcleanup) \
   LOG_TAG(scavenge) \
   LOG_TAG(scrub) \
+  LOG_TAG(stacktrace) \
   LOG_TAG(start) \
   LOG_TAG(startuptime) \
   LOG_TAG(state) \
   LOG_TAG(stats) \
   LOG_TAG(stringdedup) \
+  LOG_TAG(stringtable) \
   LOG_TAG(survivor) \
   LOG_TAG(sweep) \
   LOG_TAG(task) \
   LOG_TAG(thread) \
   LOG_TAG(tlab) \
   LOG_TAG(time) \
+  LOG_TAG(verboseverification) \
   LOG_TAG(verify) \
   LOG_TAG(vmoperation) \
-  LOG_TAG(vtables)
+  LOG_TAG(vtables) \
+  LOG_TAG_LIST_EXT
 
 #define PREFIX_LOG_TAG(T) (LogTag::_##T)
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/logging/logTag_ext.hpp	Wed Mar 23 23:36:29 2016 +0100
@@ -0,0 +1,29 @@
+/*
+ * 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_LOGGING_LOGTAG_EXT_HPP
+#define SHARE_VM_LOGGING_LOGTAG_EXT_HPP
+
+#define LOG_TAG_LIST_EXT
+
+#endif // SHARE_VM_LOGGING_LOGTAG_EXT_HPP
--- a/hotspot/src/share/vm/memory/allocation.cpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/memory/allocation.cpp	Wed Mar 23 23:36:29 2016 +0100
@@ -242,7 +242,7 @@
    ChunkPool(size_t size) : _size(size) { _first = NULL; _num_chunks = _num_used = 0; }
 
   // Allocate a new chunk from the pool (might expand the pool)
-  _NOINLINE_ void* allocate(size_t bytes, AllocFailType alloc_failmode) {
+  NOINLINE void* allocate(size_t bytes, AllocFailType alloc_failmode) {
     assert(bytes == _size, "bad size");
     void* p = NULL;
     // No VM lock can be taken inside ThreadCritical lock, so os::malloc
--- a/hotspot/src/share/vm/memory/allocation.hpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/memory/allocation.hpp	Wed Mar 23 23:36:29 2016 +0100
@@ -41,18 +41,6 @@
 #define ARENA_ALIGN_MASK (~((size_t)ARENA_ALIGN_M1))
 #define ARENA_ALIGN(x) ((((size_t)(x)) + ARENA_ALIGN_M1) & ARENA_ALIGN_MASK)
 
-
-// noinline attribute
-#ifdef _WINDOWS
-  #define _NOINLINE_  __declspec(noinline)
-#else
-  #if __GNUC__ < 3    // gcc 2.x does not support noinline attribute
-    #define _NOINLINE_
-  #else
-    #define _NOINLINE_ __attribute__ ((noinline))
-  #endif
-#endif
-
 class AllocFailStrategy {
 public:
   enum AllocFailEnum { EXIT_OOM, RETURN_NULL };
@@ -178,17 +166,17 @@
 
 template <MEMFLAGS F> class CHeapObj ALLOCATION_SUPER_CLASS_SPEC {
  public:
-  _NOINLINE_ void* operator new(size_t size, const NativeCallStack& stack) throw();
-  _NOINLINE_ void* operator new(size_t size) throw();
-  _NOINLINE_ void* operator new (size_t size, const std::nothrow_t&  nothrow_constant,
+  NOINLINE void* operator new(size_t size, const NativeCallStack& stack) throw();
+  NOINLINE void* operator new(size_t size) throw();
+  NOINLINE void* operator new (size_t size, const std::nothrow_t&  nothrow_constant,
                                const NativeCallStack& stack) throw();
-  _NOINLINE_ void* operator new (size_t size, const std::nothrow_t&  nothrow_constant)
+  NOINLINE void* operator new (size_t size, const std::nothrow_t&  nothrow_constant)
                                throw();
-  _NOINLINE_ void* operator new [](size_t size, const NativeCallStack& stack) throw();
-  _NOINLINE_ void* operator new [](size_t size) throw();
-  _NOINLINE_ void* operator new [](size_t size, const std::nothrow_t&  nothrow_constant,
+  NOINLINE void* operator new [](size_t size, const NativeCallStack& stack) throw();
+  NOINLINE void* operator new [](size_t size) throw();
+  NOINLINE void* operator new [](size_t size, const std::nothrow_t&  nothrow_constant,
                                const NativeCallStack& stack) throw();
-  _NOINLINE_ void* operator new [](size_t size, const std::nothrow_t&  nothrow_constant)
+  NOINLINE void* operator new [](size_t size, const std::nothrow_t&  nothrow_constant)
                                throw();
   void  operator delete(void* p);
   void  operator delete [] (void* p);
@@ -724,30 +712,42 @@
 // is set so that we always use malloc except for Solaris where we set the
 // limit to get mapped memory.
 template <class E, MEMFLAGS F>
-class ArrayAllocator VALUE_OBJ_CLASS_SPEC {
-  char* _addr;
-  bool _use_malloc;
-  size_t _size;
-  bool _free_in_destructor;
+class ArrayAllocator : public AllStatic {
+ private:
+  static bool should_use_malloc(size_t length);
 
-  static bool should_use_malloc(size_t size) {
-    return size < ArrayAllocatorMallocLimit;
-  }
+  static E* allocate_malloc(size_t length);
+  static E* allocate_mmap(size_t length);
 
-  static char* allocate_inner(size_t& size, bool& use_malloc);
+  static void free_malloc(E* addr, size_t length);
+  static void free_mmap(E* addr, size_t length);
+
  public:
-  ArrayAllocator(bool free_in_destructor = true) :
-    _addr(NULL), _use_malloc(false), _size(0), _free_in_destructor(free_in_destructor) { }
+  static E* allocate(size_t length);
+  static E* reallocate(E* old_addr, size_t old_length, size_t new_length);
+  static void free(E* addr, size_t length);
+};
+
+// Uses mmaped memory for all allocations. All allocations are initially
+// zero-filled. No pre-touching.
+template <class E, MEMFLAGS F>
+class MmapArrayAllocator : public AllStatic {
+ private:
+  static size_t size_for(size_t length);
 
-  ~ArrayAllocator() {
-    if (_free_in_destructor) {
-      free();
-    }
-  }
+ public:
+  static E* allocate(size_t length);
+  static void free(E* addr, size_t length);
+};
 
-  E* allocate(size_t length);
-  E* reallocate(size_t new_length);
-  void free();
+// Uses malloc:ed memory for all allocations.
+template <class E, MEMFLAGS F>
+class MallocArrayAllocator : public AllStatic {
+ public:
+  static size_t size_for(size_t length);
+
+  static E* allocate(size_t length);
+  static void free(E* addr, size_t length);
 };
 
 #endif // SHARE_VM_MEMORY_ALLOCATION_HPP
--- a/hotspot/src/share/vm/memory/allocation.inline.hpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/memory/allocation.inline.hpp	Wed Mar 23 23:36:29 2016 +0100
@@ -151,66 +151,107 @@
 }
 
 template <class E, MEMFLAGS F>
-char* ArrayAllocator<E, F>::allocate_inner(size_t &size, bool &use_malloc) {
-  char* addr = NULL;
+size_t MmapArrayAllocator<E, F>::size_for(size_t length) {
+  size_t size = length * sizeof(E);
+  int alignment = os::vm_allocation_granularity();
+  return align_size_up(size, alignment);
+}
 
-  if (use_malloc) {
-    addr = AllocateHeap(size, F);
-    if (addr == NULL && size >= (size_t)os::vm_allocation_granularity()) {
-      // malloc failed let's try with mmap instead
-      use_malloc = false;
-    } else {
-      return addr;
-    }
-  }
+template <class E, MEMFLAGS F>
+E* MmapArrayAllocator<E, F>::allocate(size_t length) {
+  size_t size = size_for(length);
+  int alignment = os::vm_allocation_granularity();
 
-  int alignment = os::vm_allocation_granularity();
-  size = align_size_up(size, alignment);
-
-  addr = os::reserve_memory(size, NULL, alignment, F);
+  char* addr = os::reserve_memory(size, NULL, alignment, F);
   if (addr == NULL) {
     vm_exit_out_of_memory(size, OOM_MMAP_ERROR, "Allocator (reserve)");
   }
 
   os::commit_memory_or_exit(addr, size, !ExecMem, "Allocator (commit)");
-  return addr;
+
+  return (E*)addr;
+}
+
+template <class E, MEMFLAGS F>
+void MmapArrayAllocator<E, F>::free(E* addr, size_t length) {
+  bool result = os::release_memory((char*)addr, size_for(length));
+  assert(result, "Failed to release memory");
+}
+
+template <class E, MEMFLAGS F>
+size_t MallocArrayAllocator<E, F>::size_for(size_t length) {
+  return length * sizeof(E);
+}
+
+template <class E, MEMFLAGS F>
+E* MallocArrayAllocator<E, F>::allocate(size_t length) {
+  return (E*)AllocateHeap(size_for(length), F);
+}
+
+template<class E, MEMFLAGS F>
+void MallocArrayAllocator<E, F>::free(E* addr, size_t /*length*/) {
+  FreeHeap(addr);
+}
+
+template <class E, MEMFLAGS F>
+bool ArrayAllocator<E, F>::should_use_malloc(size_t length) {
+  return MallocArrayAllocator<E, F>::size_for(length) < ArrayAllocatorMallocLimit;
+}
+
+template <class E, MEMFLAGS F>
+E* ArrayAllocator<E, F>::allocate_malloc(size_t length) {
+  return MallocArrayAllocator<E, F>::allocate(length);
+}
+
+template <class E, MEMFLAGS F>
+E* ArrayAllocator<E, F>::allocate_mmap(size_t length) {
+  return MmapArrayAllocator<E, F>::allocate(length);
 }
 
 template <class E, MEMFLAGS F>
 E* ArrayAllocator<E, F>::allocate(size_t length) {
-  assert(_addr == NULL, "Already in use");
+  if (should_use_malloc(length)) {
+    return allocate_malloc(length);
+  }
 
-  _size = sizeof(E) * length;
-  _use_malloc = should_use_malloc(_size);
-  _addr = allocate_inner(_size, _use_malloc);
-
-  return (E*)_addr;
+  return allocate_mmap(length);
 }
 
 template <class E, MEMFLAGS F>
-E* ArrayAllocator<E, F>::reallocate(size_t new_length) {
-  size_t new_size = sizeof(E) * new_length;
-  bool use_malloc = should_use_malloc(new_size);
-  char* new_addr = allocate_inner(new_size, use_malloc);
+E* ArrayAllocator<E, F>::reallocate(E* old_addr, size_t old_length, size_t new_length) {
+  E* new_addr = (new_length > 0)
+      ? allocate(new_length)
+      : NULL;
 
-  memcpy(new_addr, _addr, MIN2(new_size, _size));
+  if (new_addr != NULL && old_addr != NULL) {
+    memcpy(new_addr, old_addr, MIN2(old_length, new_length) * sizeof(E));
+  }
 
-  free();
-  _size = new_size;
-  _use_malloc = use_malloc;
-  _addr = new_addr;
-  return (E*)new_addr;
+  if (old_addr != NULL) {
+    free(old_addr, old_length);
+  }
+
+  return new_addr;
 }
 
 template<class E, MEMFLAGS F>
-void ArrayAllocator<E, F>::free() {
-  if (_addr != NULL) {
-    if (_use_malloc) {
-      FreeHeap(_addr);
+void ArrayAllocator<E, F>::free_malloc(E* addr, size_t length) {
+  MallocArrayAllocator<E, F>::free(addr, length);
+}
+
+template<class E, MEMFLAGS F>
+void ArrayAllocator<E, F>::free_mmap(E* addr, size_t length) {
+  MmapArrayAllocator<E, F>::free(addr, length);
+}
+
+template<class E, MEMFLAGS F>
+void ArrayAllocator<E, F>::free(E* addr, size_t length) {
+  if (addr != NULL) {
+    if (should_use_malloc(length)) {
+      free_malloc(addr, length);
     } else {
-      os::release_memory(_addr, _size);
+      free_mmap(addr, length);
     }
-    _addr = NULL;
   }
 }
 
--- a/hotspot/src/share/vm/memory/filemap.cpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/memory/filemap.cpp	Wed Mar 23 23:36:29 2016 +0100
@@ -372,7 +372,7 @@
       fail_continue("Specified shared archive not found.");
     } else {
       fail_continue("Failed to open shared archive file (%s).",
-                    strerror(errno));
+                    os::strerror(errno));
     }
     return false;
   }
@@ -402,7 +402,7 @@
   int fd = open(_full_path, O_RDWR | O_CREAT | O_TRUNC | O_BINARY, 0444);
   if (fd < 0) {
     fail_stop("Unable to create shared archive file %s: (%s).", _full_path,
-              strerror(errno));
+              os::strerror(errno));
   }
   _fd = fd;
   _file_offset = 0;
--- a/hotspot/src/share/vm/memory/iterator.hpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/memory/iterator.hpp	Wed Mar 23 23:36:29 2016 +0100
@@ -213,6 +213,16 @@
   virtual bool do_object_b(oop obj) = 0;
 };
 
+class AlwaysTrueClosure: public BoolObjectClosure {
+ public:
+  bool do_object_b(oop p) { return true; }
+};
+
+class AlwaysFalseClosure : public BoolObjectClosure {
+ public:
+  bool do_object_b(oop p) { return false; }
+};
+
 // Applies an oop closure to all ref fields in objects iterated over in an
 // object iteration.
 class ObjectToOopClosure: public ObjectClosure {
--- a/hotspot/src/share/vm/memory/metaspace.cpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/memory/metaspace.cpp	Wed Mar 23 23:36:29 2016 +0100
@@ -759,7 +759,6 @@
 
   void verify();
   void verify_chunk_size(Metachunk* chunk);
-  NOT_PRODUCT(void mangle_freed_chunks();)
 #ifdef ASSERT
   void verify_allocated_blocks_words();
 #endif
@@ -1574,7 +1573,7 @@
       } else {
         _shrink_factor = MIN2(current_shrink_factor * 4, (uint) 100);
       }
-      log_trace(gc, metaspace)("    shrinking:  initSize: %.1fK  maximum_desired_capacity: %.1fK",
+      log_trace(gc, metaspace)("    shrinking:  initThreshold: %.1fK  maximum_desired_capacity: %.1fK",
                                MetaspaceSize / (double) K, maximum_desired_capacity / (double) K);
       log_trace(gc, metaspace)("    shrink_bytes: %.1fK  current_shrink_factor: %d  new shrink factor: %d  MinMetaspaceExpansion: %.1fK",
                                shrink_bytes / (double) K, current_shrink_factor, _shrink_factor, MinMetaspaceExpansion / (double) K);
@@ -2519,20 +2518,6 @@
                 " waste " SIZE_FORMAT, curr_total, used, free, capacity, waste);
 }
 
-#ifndef PRODUCT
-void SpaceManager::mangle_freed_chunks() {
-  for (ChunkIndex index = ZeroIndex;
-       index < NumberOfInUseLists;
-       index = next_chunk_index(index)) {
-    for (Metachunk* curr = chunks_in_use(index);
-         curr != NULL;
-         curr = curr->next()) {
-      curr->mangle();
-    }
-  }
-}
-#endif // PRODUCT
-
 // MetaspaceAux
 
 
--- a/hotspot/src/share/vm/memory/metaspaceShared.cpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/memory/metaspaceShared.cpp	Wed Mar 23 23:36:29 2016 +0100
@@ -40,7 +40,7 @@
 #include "memory/metaspaceShared.hpp"
 #include "oops/objArrayOop.hpp"
 #include "oops/oop.inline.hpp"
-#include "runtime/logTimer.hpp"
+#include "runtime/timerTrace.hpp"
 #include "runtime/os.hpp"
 #include "runtime/signature.hpp"
 #include "runtime/vmThread.hpp"
@@ -775,7 +775,7 @@
 // Preload classes from a list, populate the shared spaces and dump to a
 // file.
 void MetaspaceShared::preload_and_dump(TRAPS) {
-  { TraceStartupTime timer("Dump Shared Spaces");
+  { TraceTime timer("Dump Shared Spaces", TRACETIME_LOG(Info, startuptime));
     ResourceMark rm;
     char class_list_path_str[JVM_MAXPATHLEN];
 
@@ -882,7 +882,7 @@
 
         InstanceKlass* ik = InstanceKlass::cast(klass);
 
-        // Should be class load order as per -XX:+TraceClassLoadingPreorder
+        // Should be class load order as per -Xlog:classload+preorder
         class_promote_order->append(ik);
 
         // Link the class to cause the bytecodes to be rewritten and the
--- a/hotspot/src/share/vm/memory/universe.cpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/memory/universe.cpp	Wed Mar 23 23:36:29 2016 +0100
@@ -64,11 +64,10 @@
 #include "runtime/init.hpp"
 #include "runtime/java.hpp"
 #include "runtime/javaCalls.hpp"
-#include "runtime/logTimer.hpp"
 #include "runtime/sharedRuntime.hpp"
 #include "runtime/synchronizer.hpp"
 #include "runtime/thread.inline.hpp"
-#include "runtime/timer.hpp"
+#include "runtime/timerTrace.hpp"
 #include "runtime/vm_operations.hpp"
 #include "services/memoryService.hpp"
 #include "utilities/copy.hpp"
@@ -377,8 +376,7 @@
     // We can allocate directly in the permanent generation, so we do.
     int size;
     if (UseConcMarkSweepGC) {
-      warning("Using +FullGCALot with concurrent mark sweep gc "
-              "will not force all objects to relocate");
+      log_warning(gc)("Using +FullGCALot with concurrent mark sweep gc will not force all objects to relocate");
       size = FullGCALotDummies;
     } else {
       size = FullGCALotDummies * 2;
@@ -629,7 +627,7 @@
   guarantee(sizeof(oop) % sizeof(HeapWord) == 0,
             "oop size is not not a multiple of HeapWord size");
 
-  TraceStartupTime timer("Genesis");
+  TraceTime timer("Genesis", TRACETIME_LOG(Info, startuptime));
 
   JavaClasses::compute_hard_coded_offsets();
 
@@ -1098,19 +1096,19 @@
 
 void Universe::print_heap_before_gc() {
   LogHandle(gc, heap) log;
-  if (log.is_trace()) {
-    log.trace("Heap before GC invocations=%u (full %u):", heap()->total_collections(), heap()->total_full_collections());
+  if (log.is_debug()) {
+    log.debug("Heap before GC invocations=%u (full %u):", heap()->total_collections(), heap()->total_full_collections());
     ResourceMark rm;
-    heap()->print_on(log.trace_stream());
+    heap()->print_on(log.debug_stream());
   }
 }
 
 void Universe::print_heap_after_gc() {
   LogHandle(gc, heap) log;
-  if (log.is_trace()) {
-    log.trace("Heap after GC invocations=%u (full %u):", heap()->total_collections(), heap()->total_full_collections());
+  if (log.is_debug()) {
+    log.debug("Heap after GC invocations=%u (full %u):", heap()->total_collections(), heap()->total_full_collections());
     ResourceMark rm;
-    heap()->print_on(log.trace_stream());
+    heap()->print_on(log.debug_stream());
   }
 }
 
--- a/hotspot/src/share/vm/oops/constantPool.cpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/oops/constantPool.cpp	Wed Mar 23 23:36:29 2016 +0100
@@ -208,11 +208,11 @@
   if (k() != this_cp->pool_holder()) {
     // only print something if the classes are different
     if (source_file != NULL) {
-      log_info(classresolve)("%s %s %s:%d",
+      log_debug(classresolve)("%s %s %s:%d",
                  this_cp->pool_holder()->external_name(),
                  k->external_name(), source_file, line_number);
     } else {
-      log_info(classresolve)("%s %s",
+      log_debug(classresolve)("%s %s",
                  this_cp->pool_holder()->external_name(),
                  k->external_name());
     }
@@ -281,15 +281,10 @@
   ClassLoaderData* this_key = this_cp->pool_holder()->class_loader_data();
   this_key->record_dependency(k(), CHECK_NULL); // Can throw OOM
 
-  if (log_is_enabled(Info, classresolve) && !k->is_array_klass()) {
-    // skip resolving the constant pool so that this code gets
-    // called the next time some bytecodes refer to this class.
-    trace_class_resolution(this_cp, k);
-    return k();
-  } else {
-    this_cp->klass_at_put(which, k());
-  }
+  // logging for classresolve tag.
+  trace_class_resolution(this_cp, k);
 
+  this_cp->klass_at_put(which, k());
   entry = this_cp->resolved_klass_at(which);
   assert(entry.is_resolved() && entry.get_klass()->is_klass(), "must be resolved at this point");
   return entry.get_klass();
--- a/hotspot/src/share/vm/oops/generateOopMap.cpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/oops/generateOopMap.cpp	Wed Mar 23 23:36:29 2016 +0100
@@ -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
@@ -30,6 +30,7 @@
 #include "runtime/handles.inline.hpp"
 #include "runtime/java.hpp"
 #include "runtime/relocator.hpp"
+#include "runtime/timerTrace.hpp"
 #include "utilities/bitMap.inline.hpp"
 #include "prims/methodHandles.hpp"
 
--- a/hotspot/src/share/vm/oops/instanceKlass.inline.hpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/oops/instanceKlass.inline.hpp	Wed Mar 23 23:36:29 2016 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 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
@@ -36,16 +36,9 @@
 // The iteration over the oops in objects is a hot path in the GC code.
 // By force inlining the following functions, we get similar GC performance
 // as the previous macro based implementation.
-#ifdef TARGET_COMPILER_visCPP
-#define INLINE __forceinline
-#elif defined(TARGET_COMPILER_sparcWorks)
-#define INLINE __attribute__((always_inline))
-#else
-#define INLINE inline
-#endif
 
 template <bool nv, typename T, class OopClosureType>
-INLINE void InstanceKlass::oop_oop_iterate_oop_map(OopMapBlock* map, oop obj, OopClosureType* closure) {
+ALWAYSINLINE void InstanceKlass::oop_oop_iterate_oop_map(OopMapBlock* map, oop obj, OopClosureType* closure) {
   T* p         = (T*)obj->obj_field_addr<T>(map->offset());
   T* const end = p + map->count();
 
@@ -56,7 +49,7 @@
 
 #if INCLUDE_ALL_GCS
 template <bool nv, typename T, class OopClosureType>
-INLINE void InstanceKlass::oop_oop_iterate_oop_map_reverse(OopMapBlock* map, oop obj, OopClosureType* closure) {
+ALWAYSINLINE void InstanceKlass::oop_oop_iterate_oop_map_reverse(OopMapBlock* map, oop obj, OopClosureType* closure) {
   T* const start = (T*)obj->obj_field_addr<T>(map->offset());
   T*       p     = start + map->count();
 
@@ -68,7 +61,7 @@
 #endif
 
 template <bool nv, typename T, class OopClosureType>
-INLINE void InstanceKlass::oop_oop_iterate_oop_map_bounded(OopMapBlock* map, oop obj, OopClosureType* closure, MemRegion mr) {
+ALWAYSINLINE void InstanceKlass::oop_oop_iterate_oop_map_bounded(OopMapBlock* map, oop obj, OopClosureType* closure, MemRegion mr) {
   T* p   = (T*)obj->obj_field_addr<T>(map->offset());
   T* end = p + map->count();
 
@@ -91,7 +84,7 @@
 }
 
 template <bool nv, typename T, class OopClosureType>
-INLINE void InstanceKlass::oop_oop_iterate_oop_maps_specialized(oop obj, OopClosureType* closure) {
+ALWAYSINLINE void InstanceKlass::oop_oop_iterate_oop_maps_specialized(oop obj, OopClosureType* closure) {
   OopMapBlock* map           = start_of_nonstatic_oop_maps();
   OopMapBlock* const end_map = map + nonstatic_oop_map_count();
 
@@ -102,7 +95,7 @@
 
 #if INCLUDE_ALL_GCS
 template <bool nv, typename T, class OopClosureType>
-INLINE void InstanceKlass::oop_oop_iterate_oop_maps_specialized_reverse(oop obj, OopClosureType* closure) {
+ALWAYSINLINE void InstanceKlass::oop_oop_iterate_oop_maps_specialized_reverse(oop obj, OopClosureType* closure) {
   OopMapBlock* const start_map = start_of_nonstatic_oop_maps();
   OopMapBlock* map             = start_map + nonstatic_oop_map_count();
 
@@ -114,7 +107,7 @@
 #endif
 
 template <bool nv, typename T, class OopClosureType>
-INLINE void InstanceKlass::oop_oop_iterate_oop_maps_specialized_bounded(oop obj, OopClosureType* closure, MemRegion mr) {
+ALWAYSINLINE void InstanceKlass::oop_oop_iterate_oop_maps_specialized_bounded(oop obj, OopClosureType* closure, MemRegion mr) {
   OopMapBlock* map           = start_of_nonstatic_oop_maps();
   OopMapBlock* const end_map = map + nonstatic_oop_map_count();
 
@@ -124,7 +117,7 @@
 }
 
 template <bool nv, class OopClosureType>
-INLINE void InstanceKlass::oop_oop_iterate_oop_maps(oop obj, OopClosureType* closure) {
+ALWAYSINLINE void InstanceKlass::oop_oop_iterate_oop_maps(oop obj, OopClosureType* closure) {
   if (UseCompressedOops) {
     oop_oop_iterate_oop_maps_specialized<nv, narrowOop>(obj, closure);
   } else {
@@ -134,7 +127,7 @@
 
 #if INCLUDE_ALL_GCS
 template <bool nv, class OopClosureType>
-INLINE void InstanceKlass::oop_oop_iterate_oop_maps_reverse(oop obj, OopClosureType* closure) {
+ALWAYSINLINE void InstanceKlass::oop_oop_iterate_oop_maps_reverse(oop obj, OopClosureType* closure) {
   if (UseCompressedOops) {
     oop_oop_iterate_oop_maps_specialized_reverse<nv, narrowOop>(obj, closure);
   } else {
@@ -144,7 +137,7 @@
 #endif
 
 template <bool nv, class OopClosureType>
-INLINE void InstanceKlass::oop_oop_iterate_oop_maps_bounded(oop obj, OopClosureType* closure, MemRegion mr) {
+ALWAYSINLINE void InstanceKlass::oop_oop_iterate_oop_maps_bounded(oop obj, OopClosureType* closure, MemRegion mr) {
   if (UseCompressedOops) {
     oop_oop_iterate_oop_maps_specialized_bounded<nv, narrowOop>(obj, closure, mr);
   } else {
@@ -153,7 +146,7 @@
 }
 
 template <bool nv, class OopClosureType>
-INLINE int InstanceKlass::oop_oop_iterate(oop obj, OopClosureType* closure) {
+ALWAYSINLINE int InstanceKlass::oop_oop_iterate(oop obj, OopClosureType* closure) {
   if (Devirtualizer<nv>::do_metadata(closure)) {
     Devirtualizer<nv>::do_klass(closure, this);
   }
@@ -165,7 +158,7 @@
 
 #if INCLUDE_ALL_GCS
 template <bool nv, class OopClosureType>
-INLINE int InstanceKlass::oop_oop_iterate_reverse(oop obj, OopClosureType* closure) {
+ALWAYSINLINE int InstanceKlass::oop_oop_iterate_reverse(oop obj, OopClosureType* closure) {
   assert(!Devirtualizer<nv>::do_metadata(closure),
       "Code to handle metadata is not implemented");
 
@@ -176,7 +169,7 @@
 #endif
 
 template <bool nv, class OopClosureType>
-INLINE int InstanceKlass::oop_oop_iterate_bounded(oop obj, OopClosureType* closure, MemRegion mr) {
+ALWAYSINLINE int InstanceKlass::oop_oop_iterate_bounded(oop obj, OopClosureType* closure, MemRegion mr) {
   if (Devirtualizer<nv>::do_metadata(closure)) {
     if (mr.contains(obj)) {
       Devirtualizer<nv>::do_klass(closure, this);
@@ -188,8 +181,6 @@
   return size_helper();
 }
 
-#undef INLINE
-
 #define ALL_INSTANCE_KLASS_OOP_OOP_ITERATE_DEFN(OopClosureType, nv_suffix)  \
   OOP_OOP_ITERATE_DEFN(          InstanceKlass, OopClosureType, nv_suffix)  \
   OOP_OOP_ITERATE_DEFN_BOUNDED(  InstanceKlass, OopClosureType, nv_suffix)  \
--- a/hotspot/src/share/vm/oops/instanceRefKlass.cpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/oops/instanceRefKlass.cpp	Wed Mar 23 23:36:29 2016 +0100
@@ -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,13 +25,8 @@
 #include "precompiled.hpp"
 #include "classfile/javaClasses.hpp"
 #include "classfile/systemDictionary.hpp"
-#include "gc/shared/collectedHeap.inline.hpp"
-#include "gc/shared/genCollectedHeap.hpp"
-#include "gc/shared/specialized_oop_closures.hpp"
 #include "oops/instanceRefKlass.inline.hpp"
 #include "oops/oop.inline.hpp"
-#include "utilities/macros.hpp"
-#include "utilities/preserveException.hpp"
 
 void InstanceRefKlass::update_nonstatic_oop_maps(Klass* k) {
   // Clear the nonstatic oop-map entries corresponding to referent
@@ -87,48 +82,3 @@
     guarantee(InstanceKlass::cast(next->klass())->is_reference_instance_klass(), "next field verify failed");
   }
 }
-
-bool InstanceRefKlass::owns_pending_list_lock(JavaThread* thread) {
-  if (java_lang_ref_Reference::pending_list_lock() == NULL) return false;
-  Handle h_lock(thread, java_lang_ref_Reference::pending_list_lock());
-  return ObjectSynchronizer::current_thread_holds_lock(thread, h_lock);
-}
-
-void InstanceRefKlass::acquire_pending_list_lock(BasicLock *pending_list_basic_lock) {
-  // we may enter this with pending exception set
-  PRESERVE_EXCEPTION_MARK;  // exceptions are never thrown, needed for TRAPS argument
-
-  // Create a HandleMark in case we retry a GC multiple times.
-  // Each time we attempt the GC, we allocate the handle below
-  // to hold the pending list lock. We want to free this handle.
-  HandleMark hm;
-
-  Handle h_lock(THREAD, java_lang_ref_Reference::pending_list_lock());
-  ObjectSynchronizer::fast_enter(h_lock, pending_list_basic_lock, false, THREAD);
-  assert(ObjectSynchronizer::current_thread_holds_lock(
-           JavaThread::current(), h_lock),
-         "Locking should have succeeded");
-  if (HAS_PENDING_EXCEPTION) CLEAR_PENDING_EXCEPTION;
-}
-
-void InstanceRefKlass::release_and_notify_pending_list_lock(
-  BasicLock *pending_list_basic_lock) {
-  // we may enter this with pending exception set
-  PRESERVE_EXCEPTION_MARK;  // exceptions are never thrown, needed for TRAPS argument
-
-  // Create a HandleMark in case we retry a GC multiple times.
-  // Each time we attempt the GC, we allocate the handle below
-  // to hold the pending list lock. We want to free this handle.
-  HandleMark hm;
-
-  Handle h_lock(THREAD, java_lang_ref_Reference::pending_list_lock());
-  assert(ObjectSynchronizer::current_thread_holds_lock(
-           JavaThread::current(), h_lock),
-         "Lock should be held");
-  // Notify waiters on pending lists lock if there is any reference.
-  if (java_lang_ref_Reference::pending_list() != NULL) {
-    ObjectSynchronizer::notifyall(h_lock, THREAD);
-  }
-  ObjectSynchronizer::fast_exit(h_lock(), pending_list_basic_lock, THREAD);
-  if (HAS_PENDING_EXCEPTION) CLEAR_PENDING_EXCEPTION;
-}
--- a/hotspot/src/share/vm/oops/instanceRefKlass.hpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/oops/instanceRefKlass.hpp	Wed Mar 23 23:36:29 2016 +0100
@@ -118,10 +118,6 @@
   ALL_OOP_OOP_ITERATE_CLOSURES_2(OOP_OOP_ITERATE_DECL_BACKWARDS)
 #endif // INCLUDE_ALL_GCS
 
-  static void release_and_notify_pending_list_lock(BasicLock *pending_list_basic_lock);
-  static void acquire_pending_list_lock(BasicLock *pending_list_basic_lock);
-  static bool owns_pending_list_lock(JavaThread* thread);
-
   // Update non-static oop maps so 'referent', 'nextPending' and
   // 'discovered' will look like non-oops
   static void update_nonstatic_oop_maps(Klass* k);
--- a/hotspot/src/share/vm/oops/method.cpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/oops/method.cpp	Wed Mar 23 23:36:29 2016 +0100
@@ -30,6 +30,7 @@
 #include "gc/shared/collectedHeap.inline.hpp"
 #include "gc/shared/gcLocker.hpp"
 #include "gc/shared/generation.hpp"
+#include "gc/shared/referencePendingListLocker.hpp"
 #include "interpreter/bytecodeStream.hpp"
 #include "interpreter/bytecodeTracer.hpp"
 #include "interpreter/bytecodes.hpp"
@@ -374,7 +375,7 @@
 
   // Do not profile method if current thread holds the pending list lock,
   // which avoids deadlock for acquiring the MethodData_lock.
-  if (InstanceRefKlass::owns_pending_list_lock((JavaThread*)THREAD)) {
+  if (ReferencePendingListLocker::is_locked_by_self()) {
     return;
   }
 
--- a/hotspot/src/share/vm/opto/compile.hpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/opto/compile.hpp	Wed Mar 23 23:36:29 2016 +0100
@@ -39,6 +39,7 @@
 #include "opto/phase.hpp"
 #include "opto/regmask.hpp"
 #include "runtime/deoptimization.hpp"
+#include "runtime/timerTrace.hpp"
 #include "runtime/vmThread.hpp"
 #include "trace/tracing.hpp"
 #include "utilities/ticks.hpp"
--- a/hotspot/src/share/vm/prims/jni.cpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/prims/jni.cpp	Wed Mar 23 23:36:29 2016 +0100
@@ -349,7 +349,7 @@
                                                    &st,
                                                    CHECK_NULL);
 
-  if (log_is_enabled(Info, classresolve) && k != NULL) {
+  if (log_is_enabled(Debug, classresolve) && k != NULL) {
     trace_class_resolution(k);
   }
 
@@ -419,7 +419,7 @@
   result = find_class_from_class_loader(env, sym, true, loader,
                                         protection_domain, true, thread);
 
-  if (log_is_enabled(Info, classresolve) && result != NULL) {
+  if (log_is_enabled(Debug, classresolve) && result != NULL) {
     trace_class_resolution(java_lang_Class::as_Klass(JNIHandles::resolve_non_null(result)));
   }
 
@@ -3271,7 +3271,7 @@
   TempNewSymbol sym = SymbolTable::new_symbol(name, CHECK_NULL);
   jclass result =  find_class_from_class_loader(env, sym, true, loader, protection_domain, true, CHECK_NULL);
 
-  if (log_is_enabled(Info, classresolve) && result != NULL) {
+  if (log_is_enabled(Debug, classresolve) && result != NULL) {
     trace_class_resolution(java_lang_Class::as_Klass(JNIHandles::resolve_non_null(result)));
   }
   return result;
--- a/hotspot/src/share/vm/prims/jvm.cpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/prims/jvm.cpp	Wed Mar 23 23:36:29 2016 +0100
@@ -210,9 +210,9 @@
       const char * to = to_class->external_name();
       // print in a single call to reduce interleaving between threads
       if (source_file != NULL) {
-        log_info(classresolve)("%s %s %s:%d (%s)", from, to, source_file, line_number, trace);
+        log_debug(classresolve)("%s %s %s:%d (%s)", from, to, source_file, line_number, trace);
       } else {
-        log_info(classresolve)("%s %s (%s)", from, to, trace);
+        log_debug(classresolve)("%s %s (%s)", from, to, trace);
       }
     }
   }
@@ -518,19 +518,13 @@
 JVM_END
 
 
-JVM_ENTRY(jint, JVM_GetStackTraceDepth(JNIEnv *env, jobject throwable))
-  JVMWrapper("JVM_GetStackTraceDepth");
-  oop exception = JNIHandles::resolve(throwable);
-  return java_lang_Throwable::get_stack_trace_depth(exception, THREAD);
-JVM_END
-
-
-JVM_ENTRY(jobject, JVM_GetStackTraceElement(JNIEnv *env, jobject throwable, jint index))
-  JVMWrapper("JVM_GetStackTraceElement");
-  JvmtiVMObjectAllocEventCollector oam; // This ctor (throughout this module) may trigger a safepoint/GC
-  oop exception = JNIHandles::resolve(throwable);
-  oop element = java_lang_Throwable::get_stack_trace_element(exception, index, CHECK_NULL);
-  return JNIHandles::make_local(env, element);
+JVM_ENTRY(void, JVM_GetStackTraceElements(JNIEnv *env, jobject throwable, jobjectArray stackTrace))
+  JVMWrapper("JVM_GetStackTraceElements");
+  Handle exception(THREAD, JNIHandles::resolve(throwable));
+  objArrayOop st = objArrayOop(JNIHandles::resolve(stackTrace));
+  objArrayHandle stack_trace(THREAD, st);
+  // Fill in the allocated stack trace
+  java_lang_Throwable::get_stack_trace_elements(exception, stack_trace, CHECK);
 JVM_END
 
 
@@ -839,7 +833,7 @@
     return NULL;
   }
 
-  if (log_is_enabled(Info, classresolve)) {
+  if (log_is_enabled(Debug, classresolve)) {
     trace_class_resolution(k);
   }
   return (jclass) JNIHandles::make_local(env, k->java_mirror());
@@ -876,7 +870,7 @@
   jclass result = find_class_from_class_loader(env, h_name, init, h_loader,
                                                h_prot, false, THREAD);
 
-  if (log_is_enabled(Info, classresolve) && result != NULL) {
+  if (log_is_enabled(Debug, classresolve) && result != NULL) {
     trace_class_resolution(java_lang_Class::as_Klass(JNIHandles::resolve_non_null(result)));
   }
   return result;
@@ -906,7 +900,7 @@
   jclass result = find_class_from_class_loader(env, h_name, init, h_loader,
                                                h_prot, true, thread);
 
-  if (log_is_enabled(Info, classresolve) && result != NULL) {
+  if (log_is_enabled(Debug, classresolve) && result != NULL) {
     // this function is generally only used for class loading during verification.
     ResourceMark rm;
     oop from_mirror = JNIHandles::resolve_non_null(from);
@@ -916,7 +910,7 @@
     oop mirror = JNIHandles::resolve_non_null(result);
     Klass* to_class = java_lang_Class::as_Klass(mirror);
     const char * to = to_class->external_name();
-    log_info(classresolve)("%s %s (verification)", from_name, to);
+    log_debug(classresolve)("%s %s (verification)", from_name, to);
   }
 
   return result;
@@ -984,7 +978,7 @@
                                                    &st,
                                                    CHECK_NULL);
 
-  if (log_is_enabled(Info, classresolve) && k != NULL) {
+  if (log_is_enabled(Debug, classresolve) && k != NULL) {
     trace_class_resolution(k);
   }
 
--- a/hotspot/src/share/vm/prims/jvm.h	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/prims/jvm.h	Wed Mar 23 23:36:29 2016 +0100
@@ -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
@@ -201,11 +201,8 @@
 JNIEXPORT void JNICALL
 JVM_FillInStackTrace(JNIEnv *env, jobject throwable);
 
-JNIEXPORT jint JNICALL
-JVM_GetStackTraceDepth(JNIEnv *env, jobject throwable);
-
-JNIEXPORT jobject JNICALL
-JVM_GetStackTraceElement(JNIEnv *env, jobject throwable, jint index);
+JNIEXPORT void JNICALL
+JVM_GetStackTraceElements(JNIEnv *env, jobject throwable, jobjectArray elements);
 
 /*
  * java.lang.StackWalker
--- a/hotspot/src/share/vm/prims/jvmtiEnv.cpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/prims/jvmtiEnv.cpp	Wed Mar 23 23:36:29 2016 +0100
@@ -59,6 +59,7 @@
 #include "runtime/reflectionUtils.hpp"
 #include "runtime/signature.hpp"
 #include "runtime/thread.inline.hpp"
+#include "runtime/timerTrace.hpp"
 #include "runtime/vframe.hpp"
 #include "runtime/vmThread.hpp"
 #include "services/threadService.hpp"
--- a/hotspot/src/share/vm/prims/methodHandles.cpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/prims/methodHandles.cpp	Wed Mar 23 23:36:29 2016 +0100
@@ -40,7 +40,7 @@
 #include "prims/jvmtiRedefineClassesTrace.hpp"
 #include "runtime/compilationPolicy.hpp"
 #include "runtime/javaCalls.hpp"
-#include "runtime/logTimer.hpp"
+#include "runtime/timerTrace.hpp"
 #include "runtime/reflection.hpp"
 #include "runtime/signature.hpp"
 #include "runtime/stubRoutines.hpp"
@@ -73,7 +73,7 @@
   assert(_adapter_code == NULL, "generate only once");
 
   ResourceMark rm;
-  TraceStartupTime timer("MethodHandles adapters generation");
+  TraceTime timer("MethodHandles adapters generation", TRACETIME_LOG(Info, startuptime));
   _adapter_code = MethodHandlesAdapterBlob::create(adapter_code_size);
   CodeBuffer code(_adapter_code);
   MethodHandlesAdapterGenerator g(&code);
--- a/hotspot/src/share/vm/prims/whitebox.cpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/prims/whitebox.cpp	Wed Mar 23 23:36:29 2016 +0100
@@ -35,6 +35,7 @@
 #include "jvmtifiles/jvmtiEnv.hpp"
 #include "memory/metadataFactory.hpp"
 #include "memory/metaspaceShared.hpp"
+#include "memory/iterator.hpp"
 #include "memory/universe.hpp"
 #include "oops/constantPool.hpp"
 #include "oops/oop.inline.hpp"
@@ -717,11 +718,6 @@
   return result;
 WB_END
 
-class AlwaysFalseClosure : public BoolObjectClosure {
- public:
-  bool do_object_b(oop p) { return false; }
-};
-
 static AlwaysFalseClosure always_false;
 
 WB_ENTRY(void, WB_ClearMethodState(JNIEnv* env, jobject o, jobject method))
@@ -997,7 +993,7 @@
 
 WB_ENTRY(void, WB_FullGC(JNIEnv* env, jobject o))
   Universe::heap()->collector_policy()->set_should_clear_all_soft_refs(true);
-  Universe::heap()->collect(GCCause::_last_ditch_collection);
+  Universe::heap()->collect(GCCause::_wb_full_gc);
 #if INCLUDE_ALL_GCS
   if (UseG1GC) {
     // Needs to be cleared explicitly for G1
--- a/hotspot/src/share/vm/runtime/arguments.cpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/runtime/arguments.cpp	Wed Mar 23 23:36:29 2016 +0100
@@ -417,16 +417,34 @@
 };
 
 static AliasedLoggingFlag const aliased_logging_flags[] = {
-  { "TraceClassLoading",         LogLevel::Info,  true,  LogTag::_classload },
-  { "TraceClassPaths",           LogLevel::Info,  true,  LogTag::_classpath },
-  { "TraceClassResolution",      LogLevel::Info,  true,  LogTag::_classresolve },
-  { "TraceClassUnloading",       LogLevel::Info,  true,  LogTag::_classunload },
-  { "TraceExceptions",           LogLevel::Info,  true,  LogTag::_exceptions },
-  { "TraceMonitorInflation",     LogLevel::Debug, true,  LogTag::_monitorinflation },
-  { "TraceBiasedLocking",        LogLevel::Info,  true,  LogTag::_biasedlocking },
-  { NULL,                        LogLevel::Off,   false, LogTag::__NO_TAG }
+  { "TraceBiasedLocking",        LogLevel::Info,  true,  LOG_TAGS(biasedlocking) },
+  { "TraceClassLoading",         LogLevel::Info,  true,  LOG_TAGS(classload) },
+  { "TraceClassLoadingPreorder", LogLevel::Debug,  true,  LOG_TAGS(classload, preorder) },
+  { "TraceClassPaths",           LogLevel::Info,  true,  LOG_TAGS(classpath) },
+  { "TraceClassResolution",      LogLevel::Debug, true,  LOG_TAGS(classresolve) },
+  { "TraceClassUnloading",       LogLevel::Info,  true,  LOG_TAGS(classunload) },
+  { "TraceExceptions",           LogLevel::Info,  true,  LOG_TAGS(exceptions) },
+  { "TraceMonitorInflation",     LogLevel::Debug, true,  LOG_TAGS(monitorinflation) },
+  { "TraceSafepointCleanupTime", LogLevel::Info,  true,  LOG_TAGS(safepointcleanup) },
+  { NULL,                        LogLevel::Off,   false, LOG_TAGS(_NO_TAG) }
 };
 
+#ifndef PRODUCT
+// These options are removed in jdk9. Remove this code for jdk10.
+static AliasedFlag const removed_develop_logging_flags[] = {
+  { "TraceClassInitialization",   "-Xlog:classinit" },
+  { "TraceClassLoaderData",       "-Xlog:classloaderdata" },
+  { "TraceDefaultMethods",        "-Xlog:defaultmethods=debug" },
+  { "TraceItables",               "-Xlog:itables=debug" },
+  { "TraceSafepoint",             "-Xlog:safepoint=debug" },
+  { "TraceStartupTime",           "-Xlog:startuptime" },
+  { "TraceVMOperation",           "-Xlog:vmoperation=debug" },
+  { "PrintVtables",               "-Xlog:vtables=debug" },
+  { "VerboseVerification",        "-Xlog:verboseverification" },
+  { NULL, NULL }
+};
+#endif //PRODUCT
+
 // Return true if "v" is less than "other", where "other" may be "undefined".
 static bool version_less_than(JDK_Version v, JDK_Version other) {
   assert(!v.is_undefined(), "must be defined");
@@ -478,6 +496,18 @@
   return 0;
 }
 
+#ifndef PRODUCT
+const char* Arguments::removed_develop_logging_flag_name(const char* name){
+  for (size_t i = 0; removed_develop_logging_flags[i].alias_name != NULL; i++) {
+    const AliasedFlag& flag = removed_develop_logging_flags[i];
+    if (strcmp(flag.alias_name, name) == 0) {
+      return flag.real_name;
+    }
+  }
+  return NULL;
+}
+#endif // PRODUCT
+
 const char* Arguments::real_flag_name(const char *flag_name) {
   for (size_t i = 0; aliased_jvm_flags[i].alias_name != NULL; i++) {
     const AliasedFlag& flag_status = aliased_jvm_flags[i];
@@ -968,7 +998,7 @@
       return alf;
     }
   }
-  AliasedLoggingFlag a = {NULL, LogLevel::Off, false, LogTag::__NO_TAG};
+  AliasedLoggingFlag a = {NULL, LogLevel::Off, false, LOG_TAGS(_NO_TAG)};
   return a;
 }
 
@@ -981,12 +1011,11 @@
   char dummy;
   const char* real_name;
   bool warn_if_deprecated = true;
-  AliasedLoggingFlag alf;
 
   if (sscanf(arg, "-%" XSTR(BUFLEN) NAME_RANGE "%c", name, &dummy) == 1) {
-    alf = catch_logging_aliases(name);
+    AliasedLoggingFlag alf = catch_logging_aliases(name);
     if (alf.alias_name != NULL){
-      LogConfiguration::configure_stdout(LogLevel::Off, alf.exactMatch, alf.tag, LogTag::__NO_TAG);
+      LogConfiguration::configure_stdout(LogLevel::Off, alf.exactMatch, alf.tag0, alf.tag1, alf.tag2, alf.tag3, alf.tag4, alf.tag5);
       return true;
     }
     real_name = handle_aliases_and_deprecation(name, warn_if_deprecated);
@@ -996,9 +1025,9 @@
     return set_bool_flag(real_name, false, origin);
   }
   if (sscanf(arg, "+%" XSTR(BUFLEN) NAME_RANGE "%c", name, &dummy) == 1) {
-    alf = catch_logging_aliases(name);
+    AliasedLoggingFlag alf = catch_logging_aliases(name);
     if (alf.alias_name != NULL){
-      LogConfiguration::configure_stdout(alf.level, alf.exactMatch, alf.tag, LogTag::__NO_TAG);
+      LogConfiguration::configure_stdout(alf.level, alf.exactMatch, alf.tag0, alf.tag1, alf.tag2, alf.tag3, alf.tag4, alf.tag5);
       return true;
     }
     real_name = handle_aliases_and_deprecation(name, warn_if_deprecated);
@@ -1202,13 +1231,22 @@
     char stripped_argname[BUFLEN+1];
     strncpy(stripped_argname, argname, arg_len);
     stripped_argname[arg_len] = '\0';  // strncpy may not null terminate.
-
     if (is_obsolete_flag(stripped_argname, &since)) {
       char version[256];
       since.to_string(version, sizeof(version));
       warning("Ignoring option %s; support was removed in %s", stripped_argname, version);
       return true;
     }
+#ifndef PRODUCT
+    else {
+      const char* replacement;
+      if ((replacement = removed_develop_logging_flag_name(stripped_argname)) != NULL){
+        jio_fprintf(defaultStream::error_stream(),
+                  "%s has been removed. Please use %s instead.\n", stripped_argname, replacement);
+        return false;
+      }
+    }
+#endif //PRODUCT
   }
 
   // For locked flags, report a custom error message if available.
--- a/hotspot/src/share/vm/runtime/arguments.hpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/runtime/arguments.hpp	Wed Mar 23 23:36:29 2016 +0100
@@ -265,7 +265,12 @@
   const char* alias_name;
   LogLevelType level;
   bool exactMatch;
-  LogTagType tag;
+  LogTagType tag0;
+  LogTagType tag1;
+  LogTagType tag2;
+  LogTagType tag3;
+  LogTagType tag4;
+  LogTagType tag5;
 } AliasedLoggingFlag;
 
 class Arguments : AllStatic {
@@ -503,6 +508,10 @@
   // the version number when the flag became obsolete.
   static bool is_obsolete_flag(const char* flag_name, JDK_Version* version);
 
+#ifndef PRODUCT
+  static const char* removed_develop_logging_flag_name(const char* name);
+#endif // PRODUCT
+
   // Returns 1 if the flag is deprecated (and not yet obsolete or expired).
   //     In this case the 'version' buffer is filled in with the version number when
   //     the flag became deprecated.
--- a/hotspot/src/share/vm/runtime/commandLineFlagConstraintsGC.cpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/runtime/commandLineFlagConstraintsGC.cpp	Wed Mar 23 23:36:29 2016 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 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 "gc/shared/collectedHeap.hpp"
 #include "gc/shared/collectorPolicy.hpp"
+#include "gc/shared/genCollectedHeap.hpp"
 #include "gc/shared/threadLocalAllocBuffer.hpp"
 #include "runtime/arguments.hpp"
 #include "runtime/commandLineFlagConstraintsGC.hpp"
@@ -448,6 +449,22 @@
   return Flag::SUCCESS;
 }
 
+Flag::Error CMSSamplingGrainConstraintFunc(uintx value, bool verbose) {
+#if INCLUDE_ALL_GCS
+  if (UseConcMarkSweepGC) {
+    size_t max_capacity = GenCollectedHeap::heap()->young_gen()->max_capacity();
+    if (value > max_uintx - max_capacity) {
+    CommandLineError::print(verbose,
+                            "CMSSamplingGrain (" UINTX_FORMAT ") must be "
+                            "less than or equal to ergonomic maximum (" SIZE_FORMAT ")\n",
+                            value, max_uintx - max_capacity);
+    return Flag::VIOLATES_CONSTRAINT;
+    }
+  }
+#endif
+  return Flag::SUCCESS;
+}
+
 Flag::Error CMSWorkQueueDrainThresholdConstraintFunc(uintx value, bool verbose) {
 #if INCLUDE_ALL_GCS
   if (UseConcMarkSweepGC) {
@@ -589,9 +606,15 @@
                             "greater than or equal to reserved area in TLAB (" SIZE_FORMAT ")\n",
                             value, ThreadLocalAllocBuffer::alignment_reserve_in_bytes());
     return Flag::VIOLATES_CONSTRAINT;
-  } else {
-    return Flag::SUCCESS;
   }
+  if (value > (ThreadLocalAllocBuffer::max_size() * HeapWordSize)) {
+    CommandLineError::print(verbose,
+                            "MinTLABSize (" SIZE_FORMAT ") must be "
+                            "less than or equal to ergonomic TLAB maximum (" SIZE_FORMAT ")\n",
+                            value, ThreadLocalAllocBuffer::max_size() * HeapWordSize);
+    return Flag::VIOLATES_CONSTRAINT;
+  }
+  return Flag::SUCCESS;
 }
 
 Flag::Error TLABSizeConstraintFunc(size_t value, bool verbose) {
--- a/hotspot/src/share/vm/runtime/commandLineFlagConstraintsGC.hpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/runtime/commandLineFlagConstraintsGC.hpp	Wed Mar 23 23:36:29 2016 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 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
@@ -61,6 +61,7 @@
 Flag::Error MarkStackSizeConstraintFunc(size_t value, bool verbose);
 Flag::Error CMSPrecleanDenominatorConstraintFunc(uintx value, bool verbose);
 Flag::Error CMSPrecleanNumeratorConstraintFunc(uintx value, bool verbose);
+Flag::Error CMSSamplingGrainConstraintFunc(uintx value, bool verbose);
 Flag::Error CMSWorkQueueDrainThresholdConstraintFunc(uintx value, bool verbose);
 Flag::Error MaxGCPauseMillisConstraintFunc(uintx value, bool verbose);
 Flag::Error GCPauseIntervalMillisConstraintFunc(uintx value, bool verbose);
--- a/hotspot/src/share/vm/runtime/globals.hpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/runtime/globals.hpp	Wed Mar 23 23:36:29 2016 +0100
@@ -990,9 +990,6 @@
   develop(bool, PrintVMMessages, true,                                      \
           "Print VM messages on console")                                   \
                                                                             \
-  diagnostic(bool, VerboseVerification, false,                              \
-          "Display detailed verification details")                          \
-                                                                            \
   notproduct(uintx, ErrorHandlerTest, 0,                                    \
           "If > 0, provokes an error after VM initialization; the value "   \
           "determines which error to provoke. See test_error_handler() "    \
@@ -1052,9 +1049,6 @@
           "directory) of the dump file (defaults to java_pid<pid>.hprof "   \
           "in the working directory)")                                      \
                                                                             \
-  develop(size_t, HeapDumpSegmentSize, 1*G,                                 \
-          "Approximate segment size when generating a segmented heap dump") \
-                                                                            \
   develop(bool, BreakAtWarning, false,                                      \
           "Execute breakpoint upon encountering VM warning")                \
                                                                             \
@@ -1472,9 +1466,6 @@
   develop(bool, TraceCompiledIC, false,                                     \
           "Trace changes of compiled IC")                                   \
                                                                             \
-  develop(bool, TraceClearedExceptions, false,                              \
-          "Print when an exception is forcibly cleared")                    \
-                                                                            \
   /* gc */                                                                  \
                                                                             \
   product(bool, UseSerialGC, false,                                         \
@@ -1904,7 +1895,8 @@
                                                                             \
   product(uintx, CMSSamplingGrain, 16*K,                                    \
           "The minimum distance between eden samples for CMS (see above)")  \
-          range(1, max_uintx)                                               \
+          range(ObjectAlignmentInBytes, max_uintx)                          \
+          constraint(CMSSamplingGrainConstraintFunc,AfterMemoryInit)        \
                                                                             \
   product(bool, CMSScavengeBeforeRemark, false,                             \
           "Attempt scavenge before the CMS remark step")                    \
@@ -2067,9 +2059,6 @@
   develop(uintx, MetadataAllocationFailALotInterval, 1000,                  \
           "Metadata allocation failure a lot interval")                     \
                                                                             \
-  develop(bool, TraceMetadataChunkAllocation, false,                        \
-          "Trace chunk metadata allocations")                               \
-                                                                            \
   notproduct(bool, ExecuteInternalVMTests, false,                           \
           "Enable execution of internal VM tests")                          \
                                                                             \
@@ -2223,10 +2212,10 @@
           "Decay factor to TenuredGenerationSizeIncrement")                 \
           range(1, max_uintx)                                               \
                                                                             \
-  product(uintx, MaxGCPauseMillis, max_uintx,                               \
+  product(uintx, MaxGCPauseMillis, max_uintx - 1,                           \
           "Adaptive size policy maximum GC pause time goal in millisecond, "\
           "or (G1 Only) the maximum GC time per MMU time slice")            \
-          range(1, max_uintx)                                               \
+          range(1, max_uintx - 1)                                           \
           constraint(MaxGCPauseMillisConstraintFunc,AfterMemoryInit)        \
                                                                             \
   product(uintx, GCPauseIntervalMillis, 0,                                  \
@@ -2390,9 +2379,6 @@
   product(bool, IgnoreEmptyClassPaths, false,                               \
           "Ignore empty path elements in -classpath")                       \
                                                                             \
-  product(bool, TraceClassLoadingPreorder, false,                           \
-          "Trace all classes loaded in order referenced (not loaded)")      \
-                                                                            \
   product_rw(bool, TraceLoaderConstraints, false,                           \
           "Trace loader constraints")                                       \
                                                                             \
@@ -2545,10 +2531,6 @@
   LP64_ONLY(range(-1, max_intx/MICROUNITS))                                 \
   NOT_LP64(range(-1, max_intx))                                             \
                                                                             \
-  product(bool, TraceSafepointCleanupTime, false,                           \
-          "Print the break down of clean up tasks performed during "        \
-          "safepoint")                                                      \
-                                                                            \
   product(bool, Inline, true,                                               \
           "Enable inlining")                                                \
                                                                             \
@@ -2780,10 +2762,6 @@
           "Produce histogram of IC misses")                                 \
                                                                             \
   /* interpreter */                                                         \
-  develop(bool, ClearInterpreterLocals, false,                              \
-          "Always clear local variables of interpreter activations upon "   \
-          "entry")                                                          \
-                                                                            \
   product_pd(bool, RewriteBytecodes,                                        \
           "Allow rewriting of bytecodes (bytecodes are not immutable)")     \
                                                                             \
@@ -3267,7 +3245,8 @@
           range(0, max_uintx)                                               \
                                                                             \
   product_pd(size_t, MetaspaceSize,                                         \
-          "Initial size of Metaspaces (in bytes)")                          \
+          "Initial threshold (in bytes) at which a garbage collection "     \
+          "is done to reduce Metaspace usage")                              \
           constraint(MetaspaceSizeConstraintFunc,AfterErgo)                 \
                                                                             \
   product(size_t, MaxMetaspaceSize, max_uintx,                              \
@@ -3293,6 +3272,11 @@
           range(0, 100)                                                     \
           constraint(MaxHeapFreeRatioConstraintFunc,AfterErgo)              \
                                                                             \
+  product(bool, ShrinkHeapInSteps, true,                                    \
+          "When disabled, informs the GC to shrink the java heap directly"  \
+          " to the target size at the next full GC rather than requiring"   \
+          " smaller steps during multiple full GCs.")                       \
+                                                                            \
   product(intx, SoftRefLRUPolicyMSPerMB, 1000,                              \
           "Number of milliseconds per MB of free space in the heap")        \
           range(0, max_intx)                                                \
--- a/hotspot/src/share/vm/runtime/jniHandles.cpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/runtime/jniHandles.cpp	Wed Mar 23 23:36:29 2016 +0100
@@ -25,6 +25,7 @@
 #include "precompiled.hpp"
 #include "classfile/systemDictionary.hpp"
 #include "logging/log.hpp"
+#include "memory/iterator.hpp"
 #include "oops/oop.inline.hpp"
 #include "prims/jvmtiExport.hpp"
 #include "runtime/jniHandles.hpp"
@@ -128,6 +129,12 @@
 }
 
 
+void JNIHandles::weak_oops_do(OopClosure* f) {
+  AlwaysTrueClosure always_true;
+  weak_oops_do(&always_true, f);
+}
+
+
 void JNIHandles::initialize() {
   _global_handles      = JNIHandleBlock::allocate_block();
   _weak_global_handles = JNIHandleBlock::allocate_block();
@@ -185,11 +192,6 @@
 }
 
 
-class AlwaysAliveClosure: public BoolObjectClosure {
-public:
-  bool do_object_b(oop obj) { return true; }
-};
-
 class CountHandleClosure: public OopClosure {
 private:
   int _count;
@@ -211,9 +213,8 @@
          "JNIHandles not initialized");
 
   CountHandleClosure global_handle_count;
-  AlwaysAliveClosure always_alive;
   oops_do(&global_handle_count);
-  weak_oops_do(&always_alive, &global_handle_count);
+  weak_oops_do(&global_handle_count);
 
   st->print_cr("JNI global references: %d", global_handle_count.count());
   st->cr();
@@ -230,10 +231,9 @@
 
 void JNIHandles::verify() {
   VerifyHandleClosure verify_handle;
-  AlwaysAliveClosure always_alive;
 
   oops_do(&verify_handle);
-  weak_oops_do(&always_alive, &verify_handle);
+  weak_oops_do(&verify_handle);
 }
 
 
--- a/hotspot/src/share/vm/runtime/jniHandles.hpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/runtime/jniHandles.hpp	Wed Mar 23 23:36:29 2016 +0100
@@ -86,6 +86,8 @@
   static void oops_do(OopClosure* f);
   // Traversal of weak global handles. Unreachable oops are cleared.
   static void weak_oops_do(BoolObjectClosure* is_alive, OopClosure* f);
+  // Traversal of weak global handles.
+  static void weak_oops_do(OopClosure* f);
 };
 
 
--- a/hotspot/src/share/vm/runtime/logTimer.hpp	Tue Mar 22 18:41:09 2016 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,43 +0,0 @@
-/*
- * 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_RUNTIME_LOG_TIMER_HPP
-#define SHARE_VM_RUNTIME_LOG_TIMER_HPP
-
-#include "logging/log.hpp"
-#include "runtime/timer.hpp"
-
-// TraceStartupTime is used for tracing the execution time of a block with logging
-// Usage:
-//  { TraceStartupTime t("block time")
-//    some_code();
-//  }
-//
-
-class TraceStartupTime : public TraceTime {
-  public:
-    TraceStartupTime(const char* s) : TraceTime(s, log_is_enabled(Info, startuptime), LogTag::_startuptime) {}
-};
-
-#endif // SHARE_VM_RUNTIME_LOG_TIMER_HPP
--- a/hotspot/src/share/vm/runtime/mutexLocker.cpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/runtime/mutexLocker.cpp	Wed Mar 23 23:36:29 2016 +0100
@@ -70,7 +70,6 @@
 Monitor* Threads_lock                 = NULL;
 Monitor* CGC_lock                     = NULL;
 Monitor* STS_lock                     = NULL;
-Monitor* SLT_lock                     = NULL;
 Monitor* FullGCCount_lock             = NULL;
 Mutex*   SATB_Q_FL_lock               = NULL;
 Monitor* SATB_Q_CBL_mon               = NULL;
@@ -242,9 +241,6 @@
   def(JNIGlobalHandle_lock         , Mutex  , nonleaf,     true,  Monitor::_safepoint_check_always);     // locks JNIHandleBlockFreeList_lock
   def(JNICritical_lock             , Monitor, nonleaf,     true,  Monitor::_safepoint_check_always);     // used for JNI critical regions
   def(AdapterHandlerLibrary_lock   , Mutex  , nonleaf,     true,  Monitor::_safepoint_check_always);
-  if (UseConcMarkSweepGC) {
-    def(SLT_lock                   , Monitor, nonleaf,     false, Monitor::_safepoint_check_never);      // used in CMS GC for locking PLL lock
-  }
 
   def(Heap_lock                    , Monitor, nonleaf+1,   false, Monitor::_safepoint_check_sometimes);
   def(JfieldIdCreation_lock        , Mutex  , nonleaf+1,   true,  Monitor::_safepoint_check_always);     // jfieldID, Used in VM_Operation
--- a/hotspot/src/share/vm/runtime/mutexLocker.hpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/runtime/mutexLocker.hpp	Wed Mar 23 23:36:29 2016 +0100
@@ -65,7 +65,6 @@
 extern Monitor* CGC_lock;                        // used for coordination between
                                                  // fore- & background GC threads.
 extern Monitor* STS_lock;                        // used for joining/leaving SuspendibleThreadSet.
-extern Monitor* SLT_lock;                        // used in CMS GC for acquiring PLL
 extern Monitor* FullGCCount_lock;                // in support of "concurrent" full gc
 extern Mutex*   SATB_Q_FL_lock;                  // Protects SATB Q
                                                  // buffer free list.
--- a/hotspot/src/share/vm/runtime/objectMonitor.cpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/runtime/objectMonitor.cpp	Wed Mar 23 23:36:29 2016 +0100
@@ -44,14 +44,6 @@
 #include "utilities/macros.hpp"
 #include "utilities/preserveException.hpp"
 
-#if defined(__GNUC__) && !defined(IA64) && !defined(PPC64)
-// Need to inhibit inlining for older versions of GCC to avoid build-time failures
-  #define NOINLINE __attribute__((noinline))
-#else
-  #define NOINLINE
-#endif
-
-
 #ifdef DTRACE_ENABLED
 
 // Only bother with this argument setup if dtrace is available
@@ -254,7 +246,7 @@
 // -----------------------------------------------------------------------------
 // Enter support
 
-void NOINLINE ObjectMonitor::enter(TRAPS) {
+void ObjectMonitor::enter(TRAPS) {
   // The following code is ordered to check the most common cases first
   // and to reduce RTS->RTO cache line upgrades on SPARC and IA32 processors.
   Thread * const Self = THREAD;
@@ -431,7 +423,7 @@
 
 #define MAX_RECHECK_INTERVAL 1000
 
-void NOINLINE ObjectMonitor::EnterI(TRAPS) {
+void ObjectMonitor::EnterI(TRAPS) {
   Thread * const Self = THREAD;
   assert(Self->is_Java_thread(), "invariant");
   assert(((JavaThread *) Self)->thread_state() == _thread_blocked, "invariant");
@@ -681,7 +673,7 @@
 // Knob_Reset and Knob_SpinAfterFutile support and restructuring the
 // loop accordingly.
 
-void NOINLINE ObjectMonitor::ReenterI(Thread * Self, ObjectWaiter * SelfNode) {
+void ObjectMonitor::ReenterI(Thread * Self, ObjectWaiter * SelfNode) {
   assert(Self != NULL, "invariant");
   assert(SelfNode != NULL, "invariant");
   assert(SelfNode->_thread == Self, "invariant");
@@ -894,7 +886,7 @@
 // structured the code so the windows are short and the frequency
 // of such futile wakups is low.
 
-void NOINLINE ObjectMonitor::exit(bool not_suspended, TRAPS) {
+void ObjectMonitor::exit(bool not_suspended, TRAPS) {
   Thread * const Self = THREAD;
   if (THREAD != _owner) {
     if (THREAD->is_lock_owned((address) _owner)) {
--- a/hotspot/src/share/vm/runtime/os.cpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/runtime/os.cpp	Wed Mar 23 23:36:29 2016 +0100
@@ -61,6 +61,7 @@
 #include "utilities/events.hpp"
 
 # include <signal.h>
+# include <errno.h>
 
 OSThread*         os::_starting_thread    = NULL;
 address           os::_polling_page       = NULL;
@@ -1367,6 +1368,131 @@
   return page_size_for_region(region_size, min_pages, false);
 }
 
+static const char* errno_to_string (int e, bool short_text) {
+  #define ALL_SHARED_ENUMS(X) \
+    X(E2BIG, "Argument list too long") \
+    X(EACCES, "Permission denied") \
+    X(EADDRINUSE, "Address in use") \
+    X(EADDRNOTAVAIL, "Address not available") \
+    X(EAFNOSUPPORT, "Address family not supported") \
+    X(EAGAIN, "Resource unavailable, try again") \
+    X(EALREADY, "Connection already in progress") \
+    X(EBADF, "Bad file descriptor") \
+    X(EBADMSG, "Bad message") \
+    X(EBUSY, "Device or resource busy") \
+    X(ECANCELED, "Operation canceled") \
+    X(ECHILD, "No child processes") \
+    X(ECONNABORTED, "Connection aborted") \
+    X(ECONNREFUSED, "Connection refused") \
+    X(ECONNRESET, "Connection reset") \
+    X(EDEADLK, "Resource deadlock would occur") \
+    X(EDESTADDRREQ, "Destination address required") \
+    X(EDOM, "Mathematics argument out of domain of function") \
+    X(EEXIST, "File exists") \
+    X(EFAULT, "Bad address") \
+    X(EFBIG, "File too large") \
+    X(EHOSTUNREACH, "Host is unreachable") \
+    X(EIDRM, "Identifier removed") \
+    X(EILSEQ, "Illegal byte sequence") \
+    X(EINPROGRESS, "Operation in progress") \
+    X(EINTR, "Interrupted function") \
+    X(EINVAL, "Invalid argument") \
+    X(EIO, "I/O error") \
+    X(EISCONN, "Socket is connected") \
+    X(EISDIR, "Is a directory") \
+    X(ELOOP, "Too many levels of symbolic links") \
+    X(EMFILE, "Too many open files") \
+    X(EMLINK, "Too many links") \
+    X(EMSGSIZE, "Message too large") \
+    X(ENAMETOOLONG, "Filename too long") \
+    X(ENETDOWN, "Network is down") \
+    X(ENETRESET, "Connection aborted by network") \
+    X(ENETUNREACH, "Network unreachable") \
+    X(ENFILE, "Too many files open in system") \
+    X(ENOBUFS, "No buffer space available") \
+    X(ENODATA, "No message is available on the STREAM head read queue") \
+    X(ENODEV, "No such device") \
+    X(ENOENT, "No such file or directory") \
+    X(ENOEXEC, "Executable file format error") \
+    X(ENOLCK, "No locks available") \
+    X(ENOLINK, "Reserved") \
+    X(ENOMEM, "Not enough space") \
+    X(ENOMSG, "No message of the desired type") \
+    X(ENOPROTOOPT, "Protocol not available") \
+    X(ENOSPC, "No space left on device") \
+    X(ENOSR, "No STREAM resources") \
+    X(ENOSTR, "Not a STREAM") \
+    X(ENOSYS, "Function not supported") \
+    X(ENOTCONN, "The socket is not connected") \
+    X(ENOTDIR, "Not a directory") \
+    X(ENOTEMPTY, "Directory not empty") \
+    X(ENOTSOCK, "Not a socket") \
+    X(ENOTSUP, "Not supported") \
+    X(ENOTTY, "Inappropriate I/O control operation") \
+    X(ENXIO, "No such device or address") \
+    X(EOPNOTSUPP, "Operation not supported on socket") \
+    X(EOVERFLOW, "Value too large to be stored in data type") \
+    X(EPERM, "Operation not permitted") \
+    X(EPIPE, "Broken pipe") \
+    X(EPROTO, "Protocol error") \
+    X(EPROTONOSUPPORT, "Protocol not supported") \
+    X(EPROTOTYPE, "Protocol wrong type for socket") \
+    X(ERANGE, "Result too large") \
+    X(EROFS, "Read-only file system") \
+    X(ESPIPE, "Invalid seek") \
+    X(ESRCH, "No such process") \
+    X(ETIME, "Stream ioctl() timeout") \
+    X(ETIMEDOUT, "Connection timed out") \
+    X(ETXTBSY, "Text file busy") \
+    X(EWOULDBLOCK, "Operation would block") \
+    X(EXDEV, "Cross-device link")
+
+  #define DEFINE_ENTRY(e, text) { e, #e, text },
+
+  static const struct {
+    int v;
+    const char* short_text;
+    const char* long_text;
+  } table [] = {
+
+    ALL_SHARED_ENUMS(DEFINE_ENTRY)
+
+    // The following enums are not defined on all platforms.
+    #ifdef ESTALE
+    DEFINE_ENTRY(ESTALE, "Reserved")
+    #endif
+    #ifdef EDQUOT
+    DEFINE_ENTRY(EDQUOT, "Reserved")
+    #endif
+    #ifdef EMULTIHOP
+    DEFINE_ENTRY(EMULTIHOP, "Reserved")
+    #endif
+
+    // End marker.
+    { -1, "Unknown errno", "Unknown error" }
+
+  };
+
+  #undef DEFINE_ENTRY
+  #undef ALL_FLAGS
+
+  int i = 0;
+  while (table[i].v != -1 && table[i].v != e) {
+    i ++;
+  }
+
+  return short_text ? table[i].short_text : table[i].long_text;
+
+}
+
+const char* os::strerror(int e) {
+  return errno_to_string(e, false);
+}
+
+const char* os::errno_name(int e) {
+  return errno_to_string(e, true);
+}
+
 #ifndef PRODUCT
 void os::trace_page_sizes(const char* str, const size_t* page_sizes, int count)
 {
@@ -1540,8 +1666,8 @@
   return res;
 }
 
-void os::pretouch_memory(char* start, char* end) {
-  for (volatile char *p = start; p < end; p += os::vm_page_size()) {
+void os::pretouch_memory(void* start, void* end) {
+  for (volatile char *p = (char*)start; p < (char*)end; p += os::vm_page_size()) {
     *p = 0;
   }
 }
--- a/hotspot/src/share/vm/runtime/os.hpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/runtime/os.hpp	Wed Mar 23 23:36:29 2016 +0100
@@ -325,7 +325,7 @@
   // to make the OS back the memory range with actual memory.
   // Current implementation may not touch the last page if unaligned addresses
   // are passed.
-  static void   pretouch_memory(char* start, char* end);
+  static void   pretouch_memory(void* start, void* end);
 
   enum ProtType { MEM_PROT_NONE, MEM_PROT_READ, MEM_PROT_RW, MEM_PROT_RWX };
   static bool   protect_memory(char* addr, size_t bytes, ProtType prot,
@@ -617,6 +617,22 @@
   static size_t lasterror(char *buf, size_t len);
   static int get_last_error();
 
+  // Replacement for strerror().
+  // Will return the english description of the error (e.g. "File not found", as
+  //  suggested in the POSIX standard.
+  // Will return "Unknown error" for an unknown errno value.
+  // Will not attempt to localize the returned string.
+  // Will always return a valid string which is a static constant.
+  // Will not change the value of errno.
+  static const char* strerror(int e);
+
+  // Will return the literalized version of the given errno (e.g. "EINVAL"
+  //  for EINVAL).
+  // Will return "Unknown error" for an unknown errno value.
+  // Will always return a valid string which is a static constant.
+  // Will not change the value of errno.
+  static const char* errno_name(int e);
+
   // Determines whether the calling process is being debugged by a user-mode debugger.
   static bool is_debugger_attached();
 
--- a/hotspot/src/share/vm/runtime/reflection.cpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/runtime/reflection.cpp	Wed Mar 23 23:36:29 2016 +0100
@@ -76,9 +76,9 @@
     const char * to = to_class->external_name();
     // print in a single call to reduce interleaving between threads
     if (source_file != NULL) {
-      log_info(classresolve)("%s %s %s:%d (reflection)", from, to, source_file, line_number);
+      log_debug(classresolve)("%s %s %s:%d (reflection)", from, to, source_file, line_number);
     } else {
-      log_info(classresolve)("%s %s (reflection)", from, to);
+      log_debug(classresolve)("%s %s (reflection)", from, to);
     }
   }
 }
@@ -769,7 +769,7 @@
                                                        Handle(THREAD, protection_domain),
                                                        true,
                                                        CHECK_NULL);
-    if (log_is_enabled(Info, classresolve)) {
+    if (log_is_enabled(Debug, classresolve)) {
       trace_class_resolution(k);
     }
     return k->java_mirror();
@@ -824,7 +824,7 @@
                                       Handle(THREAD, k->protection_domain()),
                                       true, CHECK_(Handle()));
 
-  if (log_is_enabled(Info, classresolve)) {
+  if (log_is_enabled(Debug, classresolve)) {
     trace_class_resolution(result);
   }
 
--- a/hotspot/src/share/vm/runtime/safepoint.cpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/runtime/safepoint.cpp	Wed Mar 23 23:36:29 2016 +0100
@@ -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,7 +54,10 @@
 #include "runtime/sweeper.hpp"
 #include "runtime/synchronizer.hpp"
 #include "runtime/thread.inline.hpp"
+#include "runtime/timerTrace.hpp"
 #include "services/runtimeService.hpp"
+#include "trace/tracing.hpp"
+#include "trace/traceMacros.hpp"
 #include "utilities/events.hpp"
 #include "utilities/macros.hpp"
 #if INCLUDE_ALL_GCS
@@ -79,7 +82,7 @@
 
 // Roll all threads forward to a safepoint and suspend them all
 void SafepointSynchronize::begin() {
-
+  EventSafepointBegin begin_event;
   Thread* myThread = Thread::current();
   assert(myThread->is_VM_thread(), "Only VM thread may execute a safepoint");
 
@@ -169,191 +172,218 @@
   //     between states, the safepointing code will wait for the thread to
   //     block itself when it attempts transitions to a new state.
   //
-  _state            = _synchronizing;
-  OrderAccess::fence();
+  {
+    EventSafepointStateSync sync_event;
+    int initial_running = 0;
 
-  // Flush all thread states to memory
-  if (!UseMembar) {
-    os::serialize_thread_states();
-  }
+    _state            = _synchronizing;
+    OrderAccess::fence();
+
+    // Flush all thread states to memory
+    if (!UseMembar) {
+      os::serialize_thread_states();
+    }
 
-  // Make interpreter safepoint aware
-  Interpreter::notice_safepoints();
+    // Make interpreter safepoint aware
+    Interpreter::notice_safepoints();
 
-  if (DeferPollingPageLoopCount < 0) {
-    // Make polling safepoint aware
-    guarantee (PageArmed == 0, "invariant") ;
-    PageArmed = 1 ;
-    os::make_polling_page_unreadable();
-  }
+    if (DeferPollingPageLoopCount < 0) {
+      // Make polling safepoint aware
+      guarantee (PageArmed == 0, "invariant") ;
+      PageArmed = 1 ;
+      os::make_polling_page_unreadable();
+    }
 
-  // Consider using active_processor_count() ... but that call is expensive.
-  int ncpus = os::processor_count() ;
+    // Consider using active_processor_count() ... but that call is expensive.
+    int ncpus = os::processor_count() ;
 
 #ifdef ASSERT
-  for (JavaThread *cur = Threads::first(); cur != NULL; cur = cur->next()) {
-    assert(cur->safepoint_state()->is_running(), "Illegal initial state");
-    // Clear the visited flag to ensure that the critical counts are collected properly.
-    cur->set_visited_for_critical_count(false);
-  }
+    for (JavaThread *cur = Threads::first(); cur != NULL; cur = cur->next()) {
+      assert(cur->safepoint_state()->is_running(), "Illegal initial state");
+      // Clear the visited flag to ensure that the critical counts are collected properly.
+      cur->set_visited_for_critical_count(false);
+    }
 #endif // ASSERT
 
-  if (SafepointTimeout)
-    safepoint_limit_time = os::javaTimeNanos() + (jlong)SafepointTimeoutDelay * MICROUNITS;
+    if (SafepointTimeout)
+      safepoint_limit_time = os::javaTimeNanos() + (jlong)SafepointTimeoutDelay * MICROUNITS;
+
+    // Iterate through all threads until it have been determined how to stop them all at a safepoint
+    unsigned int iterations = 0;
+    int steps = 0 ;
+    while(still_running > 0) {
+      for (JavaThread *cur = Threads::first(); cur != NULL; cur = cur->next()) {
+        assert(!cur->is_ConcurrentGC_thread(), "A concurrent GC thread is unexpectly being suspended");
+        ThreadSafepointState *cur_state = cur->safepoint_state();
+        if (cur_state->is_running()) {
+          cur_state->examine_state_of_thread();
+          if (!cur_state->is_running()) {
+            still_running--;
+            // consider adjusting steps downward:
+            //   steps = 0
+            //   steps -= NNN
+            //   steps >>= 1
+            //   steps = MIN(steps, 2000-100)
+            //   if (iterations != 0) steps -= NNN
+          }
+          if (log_is_enabled(Trace, safepoint)) {
+            ResourceMark rm;
+            cur_state->print_on(LogHandle(safepoint)::trace_stream());
+          }
+        }
+      }
+
+      if (iterations == 0) {
+        initial_running = still_running;
+        if (PrintSafepointStatistics) {
+          begin_statistics(nof_threads, still_running);
+        }
+      }
+
+      if (still_running > 0) {
+        // Check for if it takes to long
+        if (SafepointTimeout && safepoint_limit_time < os::javaTimeNanos()) {
+          print_safepoint_timeout(_spinning_timeout);
+        }
 
-  // Iterate through all threads until it have been determined how to stop them all at a safepoint
-  unsigned int iterations = 0;
-  int steps = 0 ;
-  while(still_running > 0) {
-    for (JavaThread *cur = Threads::first(); cur != NULL; cur = cur->next()) {
-      assert(!cur->is_ConcurrentGC_thread(), "A concurrent GC thread is unexpectly being suspended");
-      ThreadSafepointState *cur_state = cur->safepoint_state();
-      if (cur_state->is_running()) {
-        cur_state->examine_state_of_thread();
-        if (!cur_state->is_running()) {
-           still_running--;
-           // consider adjusting steps downward:
-           //   steps = 0
-           //   steps -= NNN
-           //   steps >>= 1
-           //   steps = MIN(steps, 2000-100)
-           //   if (iterations != 0) steps -= NNN
+        // Spin to avoid context switching.
+        // There's a tension between allowing the mutators to run (and rendezvous)
+        // vs spinning.  As the VM thread spins, wasting cycles, it consumes CPU that
+        // a mutator might otherwise use profitably to reach a safepoint.  Excessive
+        // spinning by the VM thread on a saturated system can increase rendezvous latency.
+        // Blocking or yielding incur their own penalties in the form of context switching
+        // and the resultant loss of $ residency.
+        //
+        // Further complicating matters is that yield() does not work as naively expected
+        // on many platforms -- yield() does not guarantee that any other ready threads
+        // will run.   As such we revert to naked_short_sleep() after some number of iterations.
+        // nakes_short_sleep() is implemented as a short unconditional sleep.
+        // Typical operating systems round a "short" sleep period up to 10 msecs, so sleeping
+        // can actually increase the time it takes the VM thread to detect that a system-wide
+        // stop-the-world safepoint has been reached.  In a pathological scenario such as that
+        // described in CR6415670 the VMthread may sleep just before the mutator(s) become safe.
+        // In that case the mutators will be stalled waiting for the safepoint to complete and the
+        // the VMthread will be sleeping, waiting for the mutators to rendezvous.  The VMthread
+        // will eventually wake up and detect that all mutators are safe, at which point
+        // we'll again make progress.
+        //
+        // Beware too that that the VMThread typically runs at elevated priority.
+        // Its default priority is higher than the default mutator priority.
+        // Obviously, this complicates spinning.
+        //
+        // Note too that on Windows XP SwitchThreadTo() has quite different behavior than Sleep(0).
+        // Sleep(0) will _not yield to lower priority threads, while SwitchThreadTo() will.
+        //
+        // See the comments in synchronizer.cpp for additional remarks on spinning.
+        //
+        // In the future we might:
+        // 1. Modify the safepoint scheme to avoid potentially unbounded spinning.
+        //    This is tricky as the path used by a thread exiting the JVM (say on
+        //    on JNI call-out) simply stores into its state field.  The burden
+        //    is placed on the VM thread, which must poll (spin).
+        // 2. Find something useful to do while spinning.  If the safepoint is GC-related
+        //    we might aggressively scan the stacks of threads that are already safe.
+        // 3. Use Solaris schedctl to examine the state of the still-running mutators.
+        //    If all the mutators are ONPROC there's no reason to sleep or yield.
+        // 4. YieldTo() any still-running mutators that are ready but OFFPROC.
+        // 5. Check system saturation.  If the system is not fully saturated then
+        //    simply spin and avoid sleep/yield.
+        // 6. As still-running mutators rendezvous they could unpark the sleeping
+        //    VMthread.  This works well for still-running mutators that become
+        //    safe.  The VMthread must still poll for mutators that call-out.
+        // 7. Drive the policy on time-since-begin instead of iterations.
+        // 8. Consider making the spin duration a function of the # of CPUs:
+        //    Spin = (((ncpus-1) * M) + K) + F(still_running)
+        //    Alternately, instead of counting iterations of the outer loop
+        //    we could count the # of threads visited in the inner loop, above.
+        // 9. On windows consider using the return value from SwitchThreadTo()
+        //    to drive subsequent spin/SwitchThreadTo()/Sleep(N) decisions.
+
+        if (int(iterations) == DeferPollingPageLoopCount) {
+          guarantee (PageArmed == 0, "invariant") ;
+          PageArmed = 1 ;
+          os::make_polling_page_unreadable();
         }
-        if (log_is_enabled(Trace, safepoint)) {
-          ResourceMark rm;
-          cur_state->print_on(LogHandle(safepoint)::debug_stream());
+
+        // Instead of (ncpus > 1) consider either (still_running < (ncpus + EPSILON)) or
+        // ((still_running + _waiting_to_block - TryingToBlock)) < ncpus)
+        ++steps ;
+        if (ncpus > 1 && steps < SafepointSpinBeforeYield) {
+          SpinPause() ;     // MP-Polite spin
+        } else
+          if (steps < DeferThrSuspendLoopCount) {
+            os::naked_yield() ;
+          } else {
+            os::naked_short_sleep(1);
+          }
+
+        iterations ++ ;
+      }
+      assert(iterations < (uint)max_jint, "We have been iterating in the safepoint loop too long");
+    }
+    assert(still_running == 0, "sanity check");
+
+    if (PrintSafepointStatistics) {
+      update_statistics_on_spin_end();
+    }
+
+    if (sync_event.should_commit()) {
+      sync_event.set_safepointId(safepoint_counter());
+      sync_event.set_initialThreadCount(initial_running);
+      sync_event.set_runningThreadCount(_waiting_to_block);
+      sync_event.set_iterations(iterations);
+      sync_event.commit();
+    }
+  } //EventSafepointStateSync
+
+  // wait until all threads are stopped
+  {
+    EventSafepointWaitBlocked wait_blocked_event;
+    int initial_waiting_to_block = _waiting_to_block;
+
+    while (_waiting_to_block > 0) {
+      log_debug(safepoint)("Waiting for %d thread(s) to block", _waiting_to_block);
+      if (!SafepointTimeout || timeout_error_printed) {
+        Safepoint_lock->wait(true);  // true, means with no safepoint checks
+      } else {
+        // Compute remaining time
+        jlong remaining_time = safepoint_limit_time - os::javaTimeNanos();
+
+        // If there is no remaining time, then there is an error
+        if (remaining_time < 0 || Safepoint_lock->wait(true, remaining_time / MICROUNITS)) {
+          print_safepoint_timeout(_blocking_timeout);
         }
       }
     }
-
-    if (PrintSafepointStatistics && iterations == 0) {
-      begin_statistics(nof_threads, still_running);
-    }
-
-    if (still_running > 0) {
-      // Check for if it takes to long
-      if (SafepointTimeout && safepoint_limit_time < os::javaTimeNanos()) {
-        print_safepoint_timeout(_spinning_timeout);
-      }
+    assert(_waiting_to_block == 0, "sanity check");
 
-      // Spin to avoid context switching.
-      // There's a tension between allowing the mutators to run (and rendezvous)
-      // vs spinning.  As the VM thread spins, wasting cycles, it consumes CPU that
-      // a mutator might otherwise use profitably to reach a safepoint.  Excessive
-      // spinning by the VM thread on a saturated system can increase rendezvous latency.
-      // Blocking or yielding incur their own penalties in the form of context switching
-      // and the resultant loss of $ residency.
-      //
-      // Further complicating matters is that yield() does not work as naively expected
-      // on many platforms -- yield() does not guarantee that any other ready threads
-      // will run.   As such we revert to naked_short_sleep() after some number of iterations.
-      // nakes_short_sleep() is implemented as a short unconditional sleep.
-      // Typical operating systems round a "short" sleep period up to 10 msecs, so sleeping
-      // can actually increase the time it takes the VM thread to detect that a system-wide
-      // stop-the-world safepoint has been reached.  In a pathological scenario such as that
-      // described in CR6415670 the VMthread may sleep just before the mutator(s) become safe.
-      // In that case the mutators will be stalled waiting for the safepoint to complete and the
-      // the VMthread will be sleeping, waiting for the mutators to rendezvous.  The VMthread
-      // will eventually wake up and detect that all mutators are safe, at which point
-      // we'll again make progress.
-      //
-      // Beware too that that the VMThread typically runs at elevated priority.
-      // Its default priority is higher than the default mutator priority.
-      // Obviously, this complicates spinning.
-      //
-      // Note too that on Windows XP SwitchThreadTo() has quite different behavior than Sleep(0).
-      // Sleep(0) will _not yield to lower priority threads, while SwitchThreadTo() will.
-      //
-      // See the comments in synchronizer.cpp for additional remarks on spinning.
-      //
-      // In the future we might:
-      // 1. Modify the safepoint scheme to avoid potentially unbounded spinning.
-      //    This is tricky as the path used by a thread exiting the JVM (say on
-      //    on JNI call-out) simply stores into its state field.  The burden
-      //    is placed on the VM thread, which must poll (spin).
-      // 2. Find something useful to do while spinning.  If the safepoint is GC-related
-      //    we might aggressively scan the stacks of threads that are already safe.
-      // 3. Use Solaris schedctl to examine the state of the still-running mutators.
-      //    If all the mutators are ONPROC there's no reason to sleep or yield.
-      // 4. YieldTo() any still-running mutators that are ready but OFFPROC.
-      // 5. Check system saturation.  If the system is not fully saturated then
-      //    simply spin and avoid sleep/yield.
-      // 6. As still-running mutators rendezvous they could unpark the sleeping
-      //    VMthread.  This works well for still-running mutators that become
-      //    safe.  The VMthread must still poll for mutators that call-out.
-      // 7. Drive the policy on time-since-begin instead of iterations.
-      // 8. Consider making the spin duration a function of the # of CPUs:
-      //    Spin = (((ncpus-1) * M) + K) + F(still_running)
-      //    Alternately, instead of counting iterations of the outer loop
-      //    we could count the # of threads visited in the inner loop, above.
-      // 9. On windows consider using the return value from SwitchThreadTo()
-      //    to drive subsequent spin/SwitchThreadTo()/Sleep(N) decisions.
-
-      if (int(iterations) == DeferPollingPageLoopCount) {
-         guarantee (PageArmed == 0, "invariant") ;
-         PageArmed = 1 ;
-         os::make_polling_page_unreadable();
-      }
-
-      // Instead of (ncpus > 1) consider either (still_running < (ncpus + EPSILON)) or
-      // ((still_running + _waiting_to_block - TryingToBlock)) < ncpus)
-      ++steps ;
-      if (ncpus > 1 && steps < SafepointSpinBeforeYield) {
-        SpinPause() ;     // MP-Polite spin
-      } else
-      if (steps < DeferThrSuspendLoopCount) {
-        os::naked_yield() ;
-      } else {
-        os::naked_short_sleep(1);
-      }
-
-      iterations ++ ;
-    }
-    assert(iterations < (uint)max_jint, "We have been iterating in the safepoint loop too long");
-  }
-  assert(still_running == 0, "sanity check");
-
-  if (PrintSafepointStatistics) {
-    update_statistics_on_spin_end();
-  }
-
-  // wait until all threads are stopped
-  while (_waiting_to_block > 0) {
-    log_debug(safepoint)("Waiting for %d thread(s) to block", _waiting_to_block);
-    if (!SafepointTimeout || timeout_error_printed) {
-      Safepoint_lock->wait(true);  // true, means with no safepoint checks
-    } else {
-      // Compute remaining time
-      jlong remaining_time = safepoint_limit_time - os::javaTimeNanos();
-
-      // If there is no remaining time, then there is an error
-      if (remaining_time < 0 || Safepoint_lock->wait(true, remaining_time / MICROUNITS)) {
-        print_safepoint_timeout(_blocking_timeout);
+#ifndef PRODUCT
+    if (SafepointTimeout) {
+      jlong current_time = os::javaTimeNanos();
+      if (safepoint_limit_time < current_time) {
+        tty->print_cr("# SafepointSynchronize: Finished after "
+                      INT64_FORMAT_W(6) " ms",
+                      ((current_time - safepoint_limit_time) / MICROUNITS +
+                       (jlong)SafepointTimeoutDelay));
       }
     }
-  }
-  assert(_waiting_to_block == 0, "sanity check");
-
-#ifndef PRODUCT
-  if (SafepointTimeout) {
-    jlong current_time = os::javaTimeNanos();
-    if (safepoint_limit_time < current_time) {
-      tty->print_cr("# SafepointSynchronize: Finished after "
-                    INT64_FORMAT_W(6) " ms",
-                    ((current_time - safepoint_limit_time) / MICROUNITS +
-                     (jlong)SafepointTimeoutDelay));
-    }
-  }
 #endif
 
-  assert((_safepoint_counter & 0x1) == 0, "must be even");
-  assert(Threads_lock->owned_by_self(), "must hold Threads_lock");
-  _safepoint_counter ++;
+    assert((_safepoint_counter & 0x1) == 0, "must be even");
+    assert(Threads_lock->owned_by_self(), "must hold Threads_lock");
+    _safepoint_counter ++;
+
+    // Record state
+    _state = _synchronized;
 
-  // Record state
-  _state = _synchronized;
+    OrderAccess::fence();
 
-  OrderAccess::fence();
+    if (wait_blocked_event.should_commit()) {
+      wait_blocked_event.set_safepointId(safepoint_counter());
+      wait_blocked_event.set_runningThreadCount(initial_waiting_to_block);
+      wait_blocked_event.commit();
+    }
+  } // EventSafepointWaitBlocked
 
 #ifdef ASSERT
   for (JavaThread *cur = Threads::first(); cur != NULL; cur = cur->next()) {
@@ -377,17 +407,32 @@
   }
 
   // Call stuff that needs to be run when a safepoint is just about to be completed
-  do_cleanup_tasks();
+  {
+    EventSafepointCleanup cleanup_event;
+    do_cleanup_tasks();
+    if (cleanup_event.should_commit()) {
+      cleanup_event.set_safepointId(safepoint_counter());
+      cleanup_event.commit();
+    }
+  }
 
   if (PrintSafepointStatistics) {
     // Record how much time spend on the above cleanup tasks
     update_statistics_on_cleanup_end(os::javaTimeNanos());
   }
+  if (begin_event.should_commit()) {
+    begin_event.set_safepointId(safepoint_counter());
+    begin_event.set_totalThreadCount(nof_threads);
+    begin_event.set_jniCriticalThreadCount(_current_jni_active_count);
+    begin_event.commit();
+  }
 }
 
 // Wake up all threads, so they are ready to resume execution after the safepoint
 // operation has been carried out
 void SafepointSynchronize::end() {
+  EventSafepointEnd event;
+  int safepoint_id = safepoint_counter(); // Keep the odd counter as "id"
 
   assert(Threads_lock->owned_by_self(), "must hold Threads_lock");
   assert((_safepoint_counter & 0x1) == 1, "must be odd");
@@ -474,6 +519,11 @@
   // record this time so VMThread can keep track how much time has elapsed
   // since last safepoint.
   _end_of_last_safepoint = os::javaTimeMillis();
+
+  if (event.should_commit()) {
+    event.set_safepointId(safepoint_id);
+    event.commit();
+  }
 }
 
 bool SafepointSynchronize::is_cleanup_needed() {
@@ -482,44 +532,71 @@
   return false;
 }
 
-
+static void event_safepoint_cleanup_task_commit(EventSafepointCleanupTask& event, const char* name) {
+  if (event.should_commit()) {
+    event.set_safepointId(SafepointSynchronize::safepoint_counter());
+    event.set_name(name);
+    event.commit();
+  }
+}
 
 // Various cleaning tasks that should be done periodically at safepoints
 void SafepointSynchronize::do_cleanup_tasks() {
   {
-    TraceTime t1("deflating idle monitors", TraceSafepointCleanupTime);
+    const char* name = "deflating idle monitors";
+    EventSafepointCleanupTask event;
+    TraceTime timer(name, TRACETIME_LOG(Info, safepointcleanup));
     ObjectSynchronizer::deflate_idle_monitors();
+    event_safepoint_cleanup_task_commit(event, name);
   }
 
   {
-    TraceTime t2("updating inline caches", TraceSafepointCleanupTime);
+    const char* name = "updating inline caches";
+    EventSafepointCleanupTask event;
+    TraceTime timer(name, TRACETIME_LOG(Info, safepointcleanup));
     InlineCacheBuffer::update_inline_caches();
+    event_safepoint_cleanup_task_commit(event, name);
   }
   {
-    TraceTime t3("compilation policy safepoint handler", TraceSafepointCleanupTime);
+    const char* name = "compilation policy safepoint handler";
+    EventSafepointCleanupTask event;
+    TraceTime timer("compilation policy safepoint handler", TRACETIME_LOG(Info, safepointcleanup));
     CompilationPolicy::policy()->do_safepoint_work();
+    event_safepoint_cleanup_task_commit(event, name);
   }
 
   {
-    TraceTime t4("mark nmethods", TraceSafepointCleanupTime);
+    const char* name = "mark nmethods";
+    EventSafepointCleanupTask event;
+    TraceTime timer(name, TRACETIME_LOG(Info, safepointcleanup));
     NMethodSweeper::mark_active_nmethods();
+    event_safepoint_cleanup_task_commit(event, name);
   }
 
   if (SymbolTable::needs_rehashing()) {
-    TraceTime t5("rehashing symbol table", TraceSafepointCleanupTime);
+    const char* name = "rehashing symbol table";
+    EventSafepointCleanupTask event;
+    TraceTime timer(name, TRACETIME_LOG(Info, safepointcleanup));
     SymbolTable::rehash_table();
+    event_safepoint_cleanup_task_commit(event, name);
   }
 
   if (StringTable::needs_rehashing()) {
-    TraceTime t6("rehashing string table", TraceSafepointCleanupTime);
+    const char* name = "rehashing string table";
+    EventSafepointCleanupTask event;
+    TraceTime timer(name, TRACETIME_LOG(Info, safepointcleanup));
     StringTable::rehash_table();
+    event_safepoint_cleanup_task_commit(event, name);
   }
 
   {
     // CMS delays purging the CLDG until the beginning of the next safepoint and to
     // make sure concurrent sweep is done
-    TraceTime t7("purging class loader data graph", TraceSafepointCleanupTime);
+    const char* name = "purging class loader data graph";
+    EventSafepointCleanupTask event;
+    TraceTime timer(name, TRACETIME_LOG(Info, safepointcleanup));
     ClassLoaderDataGraph::purge_if_needed();
+    event_safepoint_cleanup_task_commit(event, name);
   }
 }
 
--- a/hotspot/src/share/vm/runtime/safepoint.hpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/runtime/safepoint.hpp	Wed Mar 23 23:36:29 2016 +0100
@@ -145,6 +145,7 @@
   // Query
   inline static bool is_at_safepoint()   { return _state == _synchronized;  }
   inline static bool is_synchronizing()  { return _state == _synchronizing;  }
+  inline static int safepoint_counter()  { return _safepoint_counter; }
 
   inline static bool do_call_back() {
     return (_state != _not_synchronized);
--- a/hotspot/src/share/vm/runtime/sharedRuntime.cpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/runtime/sharedRuntime.cpp	Wed Mar 23 23:36:29 2016 +0100
@@ -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
@@ -993,19 +993,6 @@
   return CAST_FROM_FN_PTR(address, &throw_unsatisfied_link_error);
 }
 
-
-#ifndef PRODUCT
-JRT_ENTRY(intptr_t, SharedRuntime::trace_bytecode(JavaThread* thread, intptr_t preserve_this_value, intptr_t tos, intptr_t tos2))
-  const frame f = thread->last_frame();
-  assert(f.is_interpreted_frame(), "must be an interpreted frame");
-#ifndef PRODUCT
-  methodHandle mh(THREAD, f.interpreter_frame_method());
-  BytecodeTracer::trace(mh, f.interpreter_frame_bcp(), tos, tos2);
-#endif // !PRODUCT
-  return preserve_this_value;
-JRT_END
-#endif // !PRODUCT
-
 JRT_ENTRY_NO_ASYNC(void, SharedRuntime::register_finalizer(JavaThread* thread, oopDesc* obj))
   assert(obj->is_oop(), "must be a valid oop");
 #if INCLUDE_JVMCI
--- a/hotspot/src/share/vm/runtime/sharedRuntime.hpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/runtime/sharedRuntime.hpp	Wed Mar 23 23:36:29 2016 +0100
@@ -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
@@ -269,9 +269,6 @@
   static address native_method_throw_unsatisfied_link_error_entry();
   static address native_method_throw_unsupported_operation_exception_entry();
 
-  // bytecode tracing is only used by the TraceBytecodes
-  static intptr_t trace_bytecode(JavaThread* thread, intptr_t preserve_this_value, intptr_t tos, intptr_t tos2) PRODUCT_RETURN0;
-
   static oop retrieve_receiver(Symbol* sig, frame caller);
 
   static void register_finalizer(JavaThread* thread, oopDesc* obj);
--- a/hotspot/src/share/vm/runtime/stubRoutines.cpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/runtime/stubRoutines.cpp	Wed Mar 23 23:36:29 2016 +0100
@@ -28,7 +28,7 @@
 #include "memory/resourceArea.hpp"
 #include "oops/oop.inline.hpp"
 #include "runtime/interfaceSupport.hpp"
-#include "runtime/logTimer.hpp"
+#include "runtime/timerTrace.hpp"
 #include "runtime/sharedRuntime.hpp"
 #include "runtime/stubRoutines.hpp"
 #include "utilities/copy.hpp"
@@ -183,7 +183,7 @@
 void StubRoutines::initialize1() {
   if (_code1 == NULL) {
     ResourceMark rm;
-    TraceStartupTime timer("StubRoutines generation 1");
+    TraceTime timer("StubRoutines generation 1", TRACETIME_LOG(Info, startuptime));
     _code1 = BufferBlob::create("StubRoutines (1)", code_size1);
     if (_code1 == NULL) {
       vm_exit_out_of_memory(code_size1, OOM_MALLOC_ERROR, "CodeCache: no room for StubRoutines (1)");
@@ -276,7 +276,7 @@
 void StubRoutines::initialize2() {
   if (_code2 == NULL) {
     ResourceMark rm;
-    TraceStartupTime timer("StubRoutines generation 2");
+    TraceTime timer("StubRoutines generation 2", TRACETIME_LOG(Info, startuptime));
     _code2 = BufferBlob::create("StubRoutines (2)", code_size2);
     if (_code2 == NULL) {
       vm_exit_out_of_memory(code_size2, OOM_MALLOC_ERROR, "CodeCache: no room for StubRoutines (2)");
--- a/hotspot/src/share/vm/runtime/synchronizer.cpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/runtime/synchronizer.cpp	Wed Mar 23 23:36:29 2016 +0100
@@ -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
@@ -48,13 +48,6 @@
 #include "utilities/events.hpp"
 #include "utilities/preserveException.hpp"
 
-#if defined(__GNUC__) && !defined(PPC64)
-// Need to inhibit inlining for older versions of GCC to avoid build-time failures
-  #define NOINLINE __attribute__((noinline))
-#else
-  #define NOINLINE
-#endif
-
 // The "core" versions of monitor enter and exit reside in this file.
 // The interpreter and compilers contain specialized transliterated
 // variants of the enter-exit fast-path operations.  See i486.ad fast_lock(),
@@ -1038,7 +1031,7 @@
   assert(free_tally == Self->omFreeCount, "free count off");
 }
 
-ObjectMonitor * NOINLINE ObjectSynchronizer::omAlloc(Thread * Self) {
+ObjectMonitor* ObjectSynchronizer::omAlloc(Thread * Self) {
   // A large MAXPRIVATE value reduces both list lock contention
   // and list coherency traffic, but also tends to increase the
   // number of objectMonitors in circulation as well as the STW
@@ -1313,7 +1306,7 @@
                                      inflate_cause_vm_internal);
 }
 
-ObjectMonitor * NOINLINE ObjectSynchronizer::inflate(Thread * Self,
+ObjectMonitor* ObjectSynchronizer::inflate(Thread * Self,
                                                      oop object,
                                                      const InflateCause cause) {
 
--- a/hotspot/src/share/vm/runtime/thread.cpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/runtime/thread.cpp	Wed Mar 23 23:36:29 2016 +0100
@@ -35,6 +35,7 @@
 #include "compiler/compileTask.hpp"
 #include "gc/shared/gcId.hpp"
 #include "gc/shared/gcLocker.inline.hpp"
+#include "gc/shared/referencePendingListLocker.hpp"
 #include "gc/shared/workgroup.hpp"
 #include "interpreter/interpreter.hpp"
 #include "interpreter/linkResolver.hpp"
@@ -68,7 +69,7 @@
 #include "runtime/java.hpp"
 #include "runtime/javaCalls.hpp"
 #include "runtime/jniPeriodicChecker.hpp"
-#include "runtime/logTimer.hpp"
+#include "runtime/timerTrace.hpp"
 #include "runtime/memprofiler.hpp"
 #include "runtime/mutexLocker.hpp"
 #include "runtime/objectMonitor.hpp"
@@ -3416,7 +3417,7 @@
 }
 
 void Threads::initialize_java_lang_classes(JavaThread* main_thread, TRAPS) {
-  TraceStartupTime timer("Initialize java.lang classes");
+  TraceTime timer("Initialize java.lang classes", TRACETIME_LOG(Info, startuptime));
 
   if (EagerXrunInit && Arguments::init_libraries_at_startup()) {
     create_vm_init_libraries();
@@ -3468,7 +3469,7 @@
 }
 
 void Threads::initialize_jsr292_core_classes(TRAPS) {
-  TraceStartupTime timer("Initialize java.lang.invoke classes");
+  TraceTime timer("Initialize java.lang.invoke classes", TRACETIME_LOG(Info, startuptime));
 
   initialize_class(vmSymbols::java_lang_invoke_MethodHandle(), CHECK);
   initialize_class(vmSymbols::java_lang_invoke_MemberName(), CHECK);
@@ -3539,7 +3540,7 @@
   HOTSPOT_VM_INIT_BEGIN();
 
   // Timing (must come after argument parsing)
-  TraceStartupTime timer("Create VM");
+  TraceTime timer("Create VM", TRACETIME_LOG(Info, startuptime));
 
   // Initialize the os module after parsing the args
   jint os_init_2_result = os::init_2();
@@ -3628,7 +3629,7 @@
   JvmtiExport::transition_pending_onload_raw_monitors();
 
   // Create the VMThread
-  { TraceStartupTime timer("Start VMThread");
+  { TraceTime timer("Start VMThread", TRACETIME_LOG(Info, startuptime));
 
   VMThread::create();
     Thread* vmthread = VMThread::vm_thread();
@@ -3703,18 +3704,9 @@
   // set_init_completed has just been called, causing exceptions not to be shortcut
   // anymore. We call vm_exit_during_initialization directly instead.
 
-#if INCLUDE_ALL_GCS
-  // Support for ConcurrentMarkSweep. This should be cleaned up
-  // and better encapsulated. The ugly nested if test would go away
-  // once things are properly refactored. XXX YSR
-  if (UseConcMarkSweepGC || UseG1GC) {
-    if (UseConcMarkSweepGC) {
-      ConcurrentMarkSweepThread::makeSurrogateLockerThread(CHECK_JNI_ERR);
-    } else {
-      ConcurrentMarkThread::makeSurrogateLockerThread(CHECK_JNI_ERR);
-    }
-  }
-#endif // INCLUDE_ALL_GCS
+  // Initialize reference pending list locker
+  bool needs_locker_thread = Universe::heap()->needs_reference_pending_list_locker_thread();
+  ReferencePendingListLocker::initialize(needs_locker_thread, CHECK_JNI_ERR);
 
   // Signal Dispatcher needs to be started before VMInit event is posted
   os::signal_init();
--- a/hotspot/src/share/vm/runtime/timer.cpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/runtime/timer.cpp	Wed Mar 23 23:36:29 2016 +0100
@@ -114,54 +114,6 @@
   return os::elapsed_counter() - _counter;
 }
 
-TraceTime::TraceTime(const char* title,
-                     bool doit,
-                     LogTagType tag) {
-  _active   = doit;
-  _verbose  = true;
-  _tag      = tag;
-  _title    = title;
-
-  if (_active) {
-    _accum = NULL;
-    _t.start();
-  }
-}
-
-TraceTime::TraceTime(const char* title,
-                     elapsedTimer* accumulator,
-                     bool doit,
-                     bool verbose,
-                     LogTagType tag) {
-  _active   = doit;
-  _verbose  = verbose;
-  _tag      = tag;
-  _title    = title;
-
-  if (_active) {
-    _accum = accumulator;
-    _t.start();
-  }
-}
-
-TraceTime::~TraceTime() {
-  if (_active) {
-    _t.stop();
-    if (_accum!=NULL) _accum->add(_t);
-    if (_verbose) {
-      switch (_tag) {
-        case LogTag::_startuptime :
-          log_info(startuptime)("%s, %3.7f secs", _title, _t.seconds());
-          break;
-        case LogTag::__NO_TAG :
-       default :
-          tty->print_cr("[%s, %3.7f secs]", _title, _t.seconds());
-          tty->flush();
-      }
-    }
-  }
-}
-
 TraceCPUTime::TraceCPUTime(bool doit,
                bool print_cr,
                outputStream *logfile) :
@@ -216,3 +168,4 @@
     _logfile->flush();
   }
 }
+
--- a/hotspot/src/share/vm/runtime/timer.hpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/runtime/timer.hpp	Wed Mar 23 23:36:29 2016 +0100
@@ -25,7 +25,6 @@
 #ifndef SHARE_VM_RUNTIME_TIMER_HPP
 #define SHARE_VM_RUNTIME_TIMER_HPP
 
-#include "logging/logTag.hpp"
 #include "utilities/globalDefinitions.hpp"
 
 // Timers for simple measurement.
@@ -73,43 +72,6 @@
   jlong ticks_since_update() const;
 };
 
-// TraceTime is used for tracing the execution time of a block
-// Usage:
-//  { TraceTime t("block time")
-//    some_code();
-//  }
-//
-
-class TraceTime: public StackObj {
- private:
-  bool          _active;    // do timing
-  bool          _verbose;   // report every timing
-  elapsedTimer  _t;         // timer
-  elapsedTimer* _accum;     // accumulator
-  const char*   _title;     // name of timer
-  LogTagType    _tag;       // stream to print to
-
- public:
-  // Constructors
-  TraceTime(const char* title,
-            bool doit = true,
-            LogTagType tag = LogTag::__NO_TAG);
-  TraceTime(const char* title,
-            elapsedTimer* accumulator,
-            bool doit = true,
-            bool verbose = false,
-            LogTagType tag = LogTag::__NO_TAG);
-  ~TraceTime();
-
-  // Accessors
-  void set_verbose(bool verbose)  { _verbose = verbose; }
-  bool verbose() const            { return _verbose;    }
-
-  // Activation
-  void suspend()  { if (_active) _t.stop();  }
-  void resume()   { if (_active) _t.start(); }
-};
-
 class TraceCPUTime: public StackObj {
  private:
   bool _active;                 // true if times will be measured and printed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/runtime/timerTrace.cpp	Wed Mar 23 23:36:29 2016 +0100
@@ -0,0 +1,87 @@
+/*
+ * 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 "runtime/timerTrace.hpp"
+
+TraceTime::TraceTime(const char* title,
+                     bool doit) {
+  _active   = doit;
+  _verbose  = true;
+  _title    = title;
+  _print    = NULL;
+
+  if (_active) {
+    _accum = NULL;
+    _t.start();
+  }
+}
+
+TraceTime::TraceTime(const char* title,
+                     elapsedTimer* accumulator,
+                     bool doit,
+                     bool verbose) {
+  _active   = doit;
+  _verbose  = verbose;
+  _title    = title;
+  _print    = NULL;
+
+  if (_active) {
+    _accum = accumulator;
+    _t.start();
+  }
+}
+
+TraceTime::TraceTime(const char* title,
+                     TraceTimerLogPrintFunc ttlpf) {
+  _active   = ttlpf!= NULL;
+  _verbose  = true;
+  _title    = title;
+  _print    = ttlpf;
+
+  if (_active) {
+    _accum = NULL;
+    _t.start();
+  }
+}
+
+TraceTime::~TraceTime() {
+  if (!_active) {
+    return;
+  }
+  _t.stop();
+  if (_accum != NULL) {
+    _accum->add(_t);
+  }
+  if (!_verbose) {
+    return;
+  }
+  if (_print) {
+    _print("%s, %3.7f secs", _title, _t.seconds());
+  } else {
+    tty->print_cr("[%s, %3.7f secs]", _title, _t.seconds());
+    tty->flush();
+  }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/runtime/timerTrace.hpp	Wed Mar 23 23:36:29 2016 +0100
@@ -0,0 +1,80 @@
+/*
+ * 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_RUNTIME_TIMERTRACE_HPP
+#define SHARE_VM_RUNTIME_TIMERTRACE_HPP
+
+#include "logging/log.hpp"
+#include "utilities/globalDefinitions.hpp"
+
+// TraceTime is used for tracing the execution time of a block
+// Usage:
+//  {
+//    TraceTime t("some timer", TIMERTRACE_LOG(Info, startuptime, tagX...));
+//    some_code();
+//  }
+//
+
+typedef void (*TraceTimerLogPrintFunc)(const char*, ...);
+
+// We need to explicit take address of Log<>write<> and static cast
+// due to MSVC is not compliant with templates two-phase lookup
+#define TRACETIME_LOG(TT_LEVEL, ...) \
+    log_is_enabled(TT_LEVEL, __VA_ARGS__) ? static_cast<TraceTimerLogPrintFunc>(&Log<LOG_TAGS(__VA_ARGS__)>::write<LogLevel::TT_LEVEL>) : (TraceTimerLogPrintFunc)NULL
+
+class TraceTime: public StackObj {
+ private:
+  bool          _active;    // do timing
+  bool          _verbose;   // report every timing
+  elapsedTimer  _t;         // timer
+  elapsedTimer* _accum;     // accumulator
+  const char*   _title;     // name of timer
+  TraceTimerLogPrintFunc _print;
+
+ public:
+  // Constructors
+  TraceTime(const char* title,
+            bool doit = true);
+
+  TraceTime(const char* title,
+            elapsedTimer* accumulator,
+            bool doit = true,
+            bool verbose = false);
+
+  TraceTime(const char* title,
+            TraceTimerLogPrintFunc ttlpf);
+
+  ~TraceTime();
+
+  // Accessors
+  void set_verbose(bool verbose)  { _verbose = verbose; }
+  bool verbose() const            { return _verbose;    }
+
+  // Activation
+  void suspend()  { if (_active) _t.stop();  }
+  void resume()   { if (_active) _t.start(); }
+};
+
+
+#endif // SHARE_VM_RUNTIME_TIMERTRACE_HPP
--- a/hotspot/src/share/vm/runtime/vmStructs.cpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/runtime/vmStructs.cpp	Wed Mar 23 23:36:29 2016 +0100
@@ -54,6 +54,7 @@
 #include "gc/shared/genCollectedHeap.hpp"
 #include "gc/shared/generation.hpp"
 #include "gc/shared/generationSpec.hpp"
+#include "gc/shared/referencePendingListLocker.hpp"
 #include "gc/shared/space.hpp"
 #include "interpreter/bytecodeInterpreter.hpp"
 #include "interpreter/bytecodes.hpp"
@@ -1692,6 +1693,7 @@
            declare_type(JavaThread, Thread)                               \
            declare_type(JvmtiAgentThread, JavaThread)                     \
            declare_type(ServiceThread, JavaThread)                        \
+           declare_type(ReferencePendingListLockerThread, JavaThread)     \
   declare_type(CompilerThread, JavaThread)                                \
   declare_type(CodeCacheSweeperThread, JavaThread)                        \
   declare_toplevel_type(OSThread)                                         \
--- a/hotspot/src/share/vm/runtime/vmThread.cpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/runtime/vmThread.cpp	Wed Mar 23 23:36:29 2016 +0100
@@ -32,6 +32,7 @@
 #include "runtime/interfaceSupport.hpp"
 #include "runtime/mutexLocker.hpp"
 #include "runtime/os.hpp"
+#include "runtime/safepoint.hpp"
 #include "runtime/thread.inline.hpp"
 #include "runtime/vmThread.hpp"
 #include "runtime/vm_operations.hpp"
@@ -352,14 +353,16 @@
     op->evaluate();
 
     if (event.should_commit()) {
-      bool is_concurrent = op->evaluate_concurrently();
+      const bool is_concurrent = op->evaluate_concurrently();
+      const bool evaluate_at_safepoint = op->evaluate_at_safepoint();
       event.set_operation(op->type());
-      event.set_safepoint(op->evaluate_at_safepoint());
+      event.set_safepoint(evaluate_at_safepoint);
       event.set_blocking(!is_concurrent);
       // Only write caller thread information for non-concurrent vm operations.
       // For concurrent vm operations, the thread id is set to 0 indicating thread is unknown.
       // This is because the caller thread could have exited already.
       event.set_caller(is_concurrent ? 0 : THREAD_TRACE_ID(op->calling_thread()));
+      event.set_safepointId(evaluate_at_safepoint ? SafepointSynchronize::safepoint_counter() : 0);
       event.commit();
     }
 
--- a/hotspot/src/share/vm/services/heapDumper.cpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/services/heapDumper.cpp	Wed Mar 23 23:36:29 2016 +0100
@@ -459,7 +459,7 @@
 
   // if the open failed we record the error
   if (_fd < 0) {
-    _error = (char*)os::strdup(strerror(errno));
+    _error = (char*)os::strdup(os::strerror(errno));
   }
 }
 
@@ -509,7 +509,7 @@
 
       if (n < 0) {
         // EINTR cannot happen here, os::write will take care of that
-        set_error(strerror(errno));
+        set_error(os::strerror(errno));
         os::close(file_descriptor());
         set_file_descriptor(-1);
         return;
--- a/hotspot/src/share/vm/trace/trace.dtd	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/trace/trace.dtd	Wed Mar 23 23:36:29 2016 +0100
@@ -23,7 +23,7 @@
   
 -->
 
-<!ELEMENT trace (xi:include, relation_decls, events*, xi:include, xi:include)>
+<!ELEMENT trace (xi:include*)>
 <!ELEMENT types (content_types, primary_types)>
 <!ELEMENT content_types (content_type|struct_type)*>
 <!ELEMENT content_type (value|structvalue|structarray|array)*>
--- a/hotspot/src/share/vm/trace/trace.xml	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/trace/trace.xml	Wed Mar 23 23:36:29 2016 +0100
@@ -30,573 +30,10 @@
 ]>
 
 <trace>
-  <xi:include href="tracetypes.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/>
-
-  <relation_decls>
-    <relation_decl id="GC_ID" uri="vm/gc/id"/>
-    <relation_decl id="COMP_ID" uri="vm/compiler/id"/>
-    <relation_decl id="SWEEP_ID" uri="vm/code_sweeper/id"/>
-    <relation_decl id="JAVA_MONITOR_ADDRESS" uri="java/monitor/address"/>
-  </relation_decls>
-
-<!--
-
-Events in the JVM are by default timed (it's more common)
-Perhaps a little strange. Might change.
-
-EVENTS
-
-Declard with the 'event' tag.
-
-<value fields> can be one or more of
-   value            - a simple primitive or constant type value
-   structvalue      - value is a sub-struct. This type must be previously defined
-                      with 'struct'
-All these require you to declare type, field and label of the field. They also accept
-an optional description of the field. If the meaning of the field is not obvious
-from the label you should provide a description. If an event however is not actually
-meant for end-users, you should probably _not_ write descriptions at all, since you
-might just add more concepts the user has no notion of/interest in.
-
-Events should be modeled after what conceptual process you are expressing, _NOT_
-from whatever data structures you might use inside the JVM for expressing a process.
-
-
-STRUCT
-
-Declared with the 'struct' tag.
-
-Declares a structure type that can be used in other events.
-
--->
-
-  <events>
-    <event id="ThreadStart" path="java/thread_start" label="Java Thread Start"
-           has_thread="true" is_instant="true">
-      <value type="THREAD" field="thread" label="Java Thread"/>
-    </event>
-
-    <event id="ThreadEnd" path="java/thread_end" label="Java Thread End"
-           has_thread="true" is_instant="true">
-      <value type="THREAD" field="thread" label="Java Thread"/>
-    </event>
-
-    <event id="ThreadSleep" path="java/thread_sleep" label="Java Thread Sleep"
-            has_thread="true" has_stacktrace="true" is_instant="false">
-      <value type="MILLIS" field="time" label="Sleep Time"/>
-    </event>
-
-    <event id="ThreadPark" path="java/thread_park" label="Java Thread Park"
-            has_thread="true" has_stacktrace="true" is_instant="false">
-      <value type="CLASS" field="klass" label="Class Parked On"/>
-      <value type="MILLIS" field="timeout" label="Park Timeout"/>
-      <value type="ADDRESS" field="address" label="Address of Object Parked" relation="JAVA_MONITOR_ADDRESS"/>
-    </event>
-
-    <event id="JavaMonitorEnter" path="java/monitor_enter" label="Java Monitor Blocked"
-            has_thread="true" has_stacktrace="true" is_instant="false">
-      <value type="CLASS" field="klass" label="Monitor Class"/>
-      <value type="THREAD" field="previousOwner" label="Previous Monitor Owner"/>
-      <value type="ADDRESS" field="address" label="Monitor Address" relation="JAVA_MONITOR_ADDRESS"/>
-    </event>
-
-    <event id="JavaMonitorWait" path="java/monitor_wait" label="Java Monitor Wait" description="Waiting on a Java monitor"
-            has_thread="true" has_stacktrace="true" is_instant="false">
-      <value type="CLASS" field="klass" label="Monitor Class" description="Class of object waited on"/>
-      <value type="THREAD" field="notifier" label="Notifier Thread" description="Notifying Thread"/>
-      <value type="MILLIS" field="timeout" label="Timeout" description="Maximum wait time"/>
-      <value type="BOOLEAN" field="timedOut" label="Timed Out" description="Wait has been timed out"/>
-      <value type="ADDRESS" field="address" label="Monitor Address" description="Address of object waited on" relation="JAVA_MONITOR_ADDRESS"/>
-    </event>
-
-    <event id="JavaMonitorInflate" path="java/monitor_inflate" label="Java Monitor Inflated"
-           has_thread="true" has_stacktrace="true" is_instant="false">
-      <value type="CLASS" field="klass" label="Monitor Class"/>
-      <value type="ADDRESS" field="address" label="Monitor Address" relation="JAVA_MONITOR_ADDRESS"/>
-      <value type="INFLATECAUSE" field="cause" label="Cause" description="Cause of inflation"/>
-    </event>
-
-    <event id="ReservedStackActivation" path="java/reserved_stack_activation" label="Reserved Stack Activation" description="Activation of Reserved Stack Area caused by stack overflow with ReservedStackAccess annotated method in call stack"
-            has_thread="true" has_stacktrace="true" is_instant="true">
-        <value type="METHOD" field="method" label="Java Method"/>
-    </event>
-
-    <event id="ClassLoad" path="vm/class/load" label="Class Load"
-            has_thread="true" has_stacktrace="true" is_instant="false">
-      <value type="CLASS" field="loadedClass" label="Loaded Class"/>
-      <value type="CLASS" field="definingClassLoader" label="Defining Class Loader"/>
-      <value type="CLASS" field="initiatingClassLoader" label="Initiating Class Loader"/>
-    </event>
-
-    <event id="ClassUnload" path="vm/class/unload" label="Class Unload"
-        has_thread="true" is_instant="true">
-      <value type="CLASS" field="unloadedClass" label="Unloaded Class"/>
-      <value type="CLASS" field="definingClassLoader" label="Defining Class Loader"/>
-    </event>
-
-    <event id="IntFlagChanged" path="vm/flag/int_changed" label="Int Flag Changed"
-          is_instant="true">
-      <value type="UTF8" field="name" label="Name" />
-      <value type="INTEGER" field="old_value" label="Old Value" />
-      <value type="INTEGER" field="new_value" label="New Value" />
-      <value type="FLAGVALUEORIGIN" field="origin" label="Origin" />
-    </event>
-
-    <event id="UnsignedIntFlagChanged" path="vm/flag/uint_changed" label="Unsigned Int Flag Changed"
-          is_instant="true">
-      <value type="UTF8" field="name" label="Name" />
-      <value type="UINT" field="old_value" label="Old Value" />
-      <value type="UINT" field="new_value" label="New Value" />
-      <value type="FLAGVALUEORIGIN" field="origin" label="Origin" />
-    </event>
-
-    <event id="LongFlagChanged" path="vm/flag/long_changed" label="Long Flag Changed"
-          is_instant="true">
-      <value type="UTF8" field="name" label="Name" />
-      <value type="LONG" field="old_value" label="Old Value" />
-      <value type="LONG" field="new_value" label="New Value" />
-      <value type="FLAGVALUEORIGIN" field="origin" label="Origin" />
-    </event>
-
-    <event id="UnsignedLongFlagChanged" path="vm/flag/ulong_changed" label="Unsigned Long Flag Changed"
-          is_instant="true">
-      <value type="UTF8" field="name" label="Name" />
-      <value type="ULONG" field="old_value" label="Old Value" />
-      <value type="ULONG" field="new_value" label="New Value" />
-      <value type="FLAGVALUEORIGIN" field="origin" label="Origin" />
-    </event>
-
-    <event id="DoubleFlagChanged" path="vm/flag/double_changed" label="Double Flag Changed"
-         is_instant="true">
-      <value type="UTF8" field="name" label="Name" />
-      <value type="DOUBLE" field="old_value" label="Old Value" />
-      <value type="DOUBLE" field="new_value" label="New Value" />
-      <value type="FLAGVALUEORIGIN" field="origin" label="Origin" />
-    </event>
-
-    <event id="BooleanFlagChanged" path="vm/flag/boolean_changed" label="Boolean Flag Changed"
-         is_instant="true">
-      <value type="UTF8" field="name" label="Name" />
-      <value type="BOOLEAN" field="old_value" label="Old Value" />
-      <value type="BOOLEAN" field="new_value" label="New Value" />
-      <value type="FLAGVALUEORIGIN" field="origin" label="Origin" />
-    </event>
-
-    <event id="StringFlagChanged" path="vm/flag/string_changed" label="String Flag Changed"
-         is_instant="true">
-      <value type="UTF8" field="name" label="Name" />
-      <value type="UTF8" field="old_value" label="Old Value" />
-      <value type="UTF8" field="new_value" label="New Value" />
-      <value type="FLAGVALUEORIGIN" field="origin" label="Origin" />
-    </event>
-
-    <struct id="VirtualSpace">
-      <value type="ADDRESS" field="start" label="Start Address" description="Start address of the virtual space" />
-      <value type="ADDRESS" field="committedEnd" label="Committed End Address" description="End address of the committed memory for the virtual space" />
-      <value type="BYTES64" field="committedSize" label="Committed Size" description="Size of the committed memory for the virtual space" />
-      <value type="ADDRESS" field="reservedEnd" label="Reserved End Address" description="End address of the reserved memory for the virtual space" />
-      <value type="BYTES64" field="reservedSize" label="Reserved Size" description="Size of the reserved memory for the virtual space" />
-    </struct>
-
-    <struct id="ObjectSpace">
-      <value type="ADDRESS" field="start" label="Start Address" description="Start address of the space" />
-      <value type="ADDRESS" field="end" label="End Address" description="End address of the space" />
-      <value type="BYTES64" field="used" label="Used" description="Bytes allocated by objects in the space" />
-      <value type="BYTES64" field="size" label="Size" description="Size of the space" />
-    </struct>
-
-    <event id="GCHeapSummary" path="vm/gc/heap/summary" label="Heap Summary" is_instant="true">
-      <value type="UINT" field="gcId" label="GC ID" relation="GC_ID"/>
-      <value type="GCWHEN" field="when" label="When" />
-      <structvalue type="VirtualSpace" field="heapSpace" label="Heap Space"/>
-      <value type="BYTES64" field="heapUsed" label="Heap Used" description="Bytes allocated by objects in the heap"/>
-    </event>
-
-    <struct id="MetaspaceSizes">
-      <value type="BYTES64" field="committed" label="Committed" description="Committed memory for this space" />
-      <value type="BYTES64" field="used" label="Used" description="Bytes allocated by objects in the space" />
-      <value type="BYTES64" field="reserved" label="Reserved" description="Reserved memory for this space" />
-    </struct>
-
-    <event id="MetaspaceSummary" path="vm/gc/heap/metaspace_summary" label="Metaspace Summary" is_instant="true">
-      <value type="UINT" field="gcId" label="GC ID" relation="GC_ID"/>
-      <value type="GCWHEN" field="when" label="When" />
-      <value type="BYTES64" field="gcThreshold" label="GC Threshold" />
-      <structvalue type="MetaspaceSizes" field="metaspace" label="Total"/>
-      <structvalue type="MetaspaceSizes" field="dataSpace" label="Data"/>
-      <structvalue type="MetaspaceSizes" field="classSpace" label="Class"/>
-    </event>
-
-    <event id="MetaspaceGCThreshold" path="vm/gc/metaspace/gc_threshold" label="Metaspace GC Threshold" is_instant="true">
-      <value type="BYTES64" field="oldValue" label="Old Value" />
-      <value type="BYTES64" field="newValue" label="New Value" />
-      <value type="GCTHRESHOLDUPDATER" field="updater" label="Updater" />
-    </event>
-
-    <event id="MetaspaceAllocationFailure" path="vm/gc/metaspace/allocation_failure" label="Metaspace Allocation Failure" is_instant="true" has_stacktrace="true">
-      <value type="CLASS" field="classLoader" label="Class Loader" />
-      <value type="BOOLEAN" field="anonymousClassLoader" label="Anonymous Class Loader" />
-      <value type="BYTES64" field="size" label="Size" />
-      <value type="METADATATYPE" field="metadataType" label="Metadata Type" />
-      <value type="METASPACEOBJTYPE" field="metaspaceObjectType" label="Metaspace Object Type" />
-    </event>
-
-    <event id="MetaspaceOOM" path="vm/gc/metaspace/out_of_memory" label="Metaspace Out of Memory" is_instant="true" has_stacktrace="true">
-      <value type="CLASS" field="classLoader" label="Class Loader" />
-      <value type="BOOLEAN" field="anonymousClassLoader" label="Anonymous Class Loader" />
-      <value type="BYTES64" field="size" label="Size" />
-      <value type="METADATATYPE" field="metadataType" label="Metadata Type" />
-      <value type="METASPACEOBJTYPE" field="metaspaceObjectType" label="Metaspace Object Type" />
-    </event>
-
-    <event id="MetaspaceChunkFreeListSummary" path="vm/gc/metaspace/chunk_free_list_summary" label="Metaspace Chunk Free List Summary" is_instant="true">
-      <value type="UINT" field="gcId" label="GC ID" relation="GC_ID"/>
-      <value type="GCWHEN" field="when" label="When" />
-      <value type="METADATATYPE" field="metadataType" label="Metadata Type" />
-      <value type="ULONG" field="specializedChunks" label="Specialized Chunks" />
-      <value type="BYTES64" field="specializedChunksTotalSize" label="Specialized Chunks Total Size" />
-      <value type="ULONG" field="smallChunks" label="Small Chunks" />
-      <value type="BYTES64" field="smallChunksTotalSize" label="Small Chunks Total Size" />
-      <value type="ULONG" field="mediumChunks" label="Medium Chunks" />
-      <value type="BYTES64" field="mediumChunksTotalSize" label="Medium Chunks Total Size" />
-      <value type="ULONG" field="humongousChunks" label="Humongous Chunks" />
-      <value type="BYTES64" field="humongousChunksTotalSize" label="Humongous Chunks Total Size" />
-    </event>
-
-    <event id="PSHeapSummary" path="vm/gc/heap/ps_summary" label="Parallel Scavenge Heap Summary" is_instant="true">
-      <value type="UINT" field="gcId" label="GC ID" relation="GC_ID"/>
-      <value type="GCWHEN" field="when" label="When" />
-
-      <structvalue type="VirtualSpace" field="oldSpace" label="Old Space"/>
-      <structvalue type="ObjectSpace" field="oldObjectSpace" label="Old Object Space"/>
-
-      <structvalue type="VirtualSpace" field="youngSpace" label="Young Space"/>
-      <structvalue type="ObjectSpace" field="edenSpace" label="Eden Space"/>
-      <structvalue type="ObjectSpace" field="fromSpace" label="From Space"/>
-      <structvalue type="ObjectSpace" field="toSpace" label="To Space"/>
-    </event>
-
-    <event id="G1HeapSummary" path="vm/gc/heap/g1_summary" label="G1 Heap Summary" is_instant="true">
-      <value type="UINT" field="gcId" label="GC ID" relation="GC_ID"/>
-      <value type="GCWHEN" field="when" label="When" />
-
-      <value type="BYTES64" field="edenUsedSize" label="Eden Used Size" />
-      <value type="BYTES64" field="edenTotalSize" label="Eden Total Size" />
-      <value type="BYTES64" field="survivorUsedSize" label="Survivor Used Size" />
-      <value type="UINT" field="numberOfRegions" label="Number of Regions" />
-    </event>
-
-    <event id="GCGarbageCollection" path="vm/gc/collector/garbage_collection" label="Garbage Collection"
-           description="Garbage collection performed by the JVM">
-      <value type="UINT" field="gcId"  label="GC ID" relation="GC_ID" />
-      <value type="GCNAME" field="name" label="Name" description="The name of the Garbage Collector" />
-      <value type="GCCAUSE" field="cause" label="Cause" description="The reason for triggering this Garbage Collection" />
-      <value type="TICKSPAN" field="sumOfPauses" label="Sum of Pauses" description="Sum of all the times in which Java execution was paused during the garbage collection" />
-      <value type="TICKSPAN" field="longestPause" label="Longest Pause" description="Longest individual pause during the garbage collection" />
-    </event>
-
-    <event id="GCParallelOld" path="vm/gc/collector/parold_garbage_collection" label="Parallel Old Garbage Collection"
-           description="Extra information specific to Parallel Old Garbage Collections">
-      <value type="UINT" field="gcId"  label="GC ID" relation="GC_ID" />
-      <value type="ADDRESS" field="densePrefix" label="Dense Prefix" description="The address of the dense prefix, used when compacting" />
-    </event>
-
-    <event id="GCYoungGarbageCollection" path="vm/gc/collector/young_garbage_collection" label="Young Garbage Collection"
-           description="Extra information specific to Young Garbage Collections">
-      <value type="UINT" field="gcId"  label="GC ID" relation="GC_ID" />
-      <value type="UINT" field="tenuringThreshold" label="Tenuring Threshold" />
-    </event>
-
-    <event id="GCOldGarbageCollection" path="vm/gc/collector/old_garbage_collection" label="Old Garbage Collection"
-           description="Extra information specific to Old Garbage Collections">
-      <value type="UINT" field="gcId" label="GC ID" relation="GC_ID"/>
-    </event>
-
-    <event id="GCG1GarbageCollection" path="vm/gc/collector/g1_garbage_collection" label="G1 Garbage Collection"
-           description="Extra information specific to G1 Garbage Collections">
-      <value type="UINT" field="gcId" label="GC ID" relation="GC_ID"/>
-      <value type="G1YCTYPE" field="type" label="Type" />
-    </event>
-
-    <event id="GCG1MMU" path="vm/gc/detailed/g1_mmu_info" label="G1 MMU Information" is_instant="true">
-      <value type="UINT" field="gcId" label="GC ID" relation="GC_ID"/>
-      <value type="DOUBLE" field="timeSlice" label="Time slice used to calculate MMU"/>
-      <value type="DOUBLE" field="gcTime" label="Time spent on GC during last time slice"/>
-      <value type="DOUBLE" field="maxGcTime" label="Max time allowed to be spent on GC during last time slice"/>
-    </event>
-
-    <event id="EvacuationInfo" path="vm/gc/detailed/evacuation_info" label="Evacuation Information" is_instant="true">
-      <value type="UINT" field="gcId" label="GC ID" relation="GC_ID"/>
-      <value type="UINT" field="cSetRegions" label="Collection Set Regions"/>
-      <value type="BYTES64" field="cSetUsedBefore" label="Collection Set Before" description="Memory usage before GC in the collection set regions"/>
-      <value type="BYTES64" field="cSetUsedAfter" label="Collection Set After" description="Memory usage after GC in the collection set regions"/>
-      <value type="UINT" field="allocationRegions" label="Allocation Regions" description="Regions chosen as allocation regions during evacuation (includes survivors and old space regions)"/>
-      <value type="BYTES64" field="allocRegionsUsedBefore" label="Alloc Regions Before" description="Memory usage before GC in allocation regions"/>
-      <value type="BYTES64" field="allocRegionsUsedAfter" label="Alloc Regions After" description="Memory usage after GC in allocation regions"/>
-      <value type="BYTES64" field="bytesCopied" label="Bytes Copied"/>
-      <value type="UINT" field="regionsFreed" label="Regions Freed"/>
-    </event>
-
-    <event id="GCReferenceStatistics" path="vm/gc/reference/statistics"
-           label="GC Reference Statistics" is_instant="true"
-           description="Total count of processed references during GC">
-      <value type="UINT" field="gcId" label="GC ID" relation="GC_ID"/>
-      <value type="REFERENCETYPE" field="type" label="Type" />
-      <value type="ULONG" field="count" label="Total Count" />
-    </event>
-
-    <struct id="CopyFailed">
-      <value type="ULONG" field="objectCount" label="Object Count"/>
-      <value type="BYTES64" field="firstSize" label="First Failed Object Size"/>
-      <value type="BYTES64" field="smallestSize" label="Smallest Failed Object Size"/>
-      <value type="BYTES64" field="totalSize" label="Total Object Size"/>
-    </struct>
-
-    <event id="ObjectCountAfterGC" path="vm/gc/detailed/object_count_after_gc" is_instant="true" label="Object Count after GC">
-      <value type="UINT" field="gcId"  label="GC ID" relation="GC_ID" />
-      <value type="CLASS" field="class" label="Class" />
-      <value type="LONG" field="count" label="Count" />
-      <value type="BYTES64" field="totalSize" label="Total Size" />
-    </event>
-
-    <struct id="G1EvacStats">
-      <value type="UINT" field="gcId" label="GC ID" relation="GC_ID"/>
-      <value type="BYTES64" field="allocated" label="Allocated" description="Total memory allocated by PLABs"/>
-      <value type="BYTES64" field="wasted" label="Wasted" description="Total memory wasted within PLABs due to alignment or refill"/>
-      <value type="BYTES64" field="used" label="Used" description="Total memory occupied by objects within PLABs"/>
-      <value type="BYTES64" field="undoWaste" label="Undo Wasted" description="Total memory wasted due to allocation undo within PLABs"/>
-      <value type="BYTES64" field="regionEndWaste" label="Region End Wasted" description="Total memory wasted at the end of regions due to refill"/>
-      <value type="UINT" field="regionsRefilled" label="Region Refills" description="Total memory wasted at the end of regions due to refill"/>
-      <value type="BYTES64" field="directAllocated" label="Allocated (direct)" description="Total memory allocated using direct allocation outside of PLABs"/>
-      <value type="BYTES64" field="failureUsed" label="Used (failure)" description="Total memory occupied by objects in regions where evacuation failed"/>
-      <value type="BYTES64" field="failureWaste" label="Wasted (failure)" description="Total memory left unused in regions where evacuation failed"/>
-    </struct>
-
-    <event id="GCG1EvacuationYoungStatistics" path="vm/gc/detailed/g1_evac_young_stats" label="G1 Evacuation Statistics for Young" is_instant="true"
-           description="Memory related evacuation statistics during GC for the young generation">
-      <structvalue type="G1EvacStats" field="stats" label="Evacuation statistics"/>
-    </event>
-
-    <event id="GCG1EvacuationOldStatistics" path="vm/gc/detailed/g1_evac_old_stats" label="G1 Evacuation Memory Statistics for Old" is_instant="true"
-           description="Memory related evacuation statistics during GC for the old generation">
-      <structvalue type="G1EvacStats" field="stats" label="Evacuation statistics"/>
-    </event>
-
-    <event id="GCG1BasicIHOP" path="vm/gc/detailed/g1_basic_ihop_status" label="G1 Basic IHOP statistics" is_instant="true"
-           description="Basic statistics related to current IHOP calculation">
-      <value type="UINT" field="gcId" label="GC ID" relation="GC_ID"/>
-      <value type="BYTES64" field="threshold" label="Current IHOP threshold" description="Current IHOP threshold in bytes"/>
-      <value type="BYTES64" field="thresholdPercentage" label="Current IHOP threshold in percent" description="Current IHOP threshold in percent of old gen"/>
-      <value type="BYTES64" field="targetOccupancy" label="Target occupancy" description="Target old gen occupancy to reach at the start of mixed GC in bytes"/>
-      <value type="BYTES64" field="currentOccupancy" label="Current occupancy" description="Current old gen occupancy in bytes"/>
-      <value type="BYTES64" field="lastAllocationSize" label="Last mutator allocation size" description="Mutator allocation during mutator operation since last GC in bytes"/>
-      <value type="DOUBLE" field="lastAllocationDuration" label="Last mutator operation duration" description="Time the mutator ran since last GC in seconds"/>
-      <value type="DOUBLE" field="lastAllocationRate" label="Last mutator allocation rate" description="Allocation rate of the mutator since last GC in bytes/second"/>
-      <value type="DOUBLE" field="lastMarkingLength" label="Last mutator time from initial mark to first mixed GC" description="Last time from the end of the last initial mark to the first mixed GC in seconds"/>
-    </event>
-
-    <event id="GCG1AdaptiveIHOP" path="vm/gc/detailed/g1_adaptive_ihop_status" label="G1 Adaptive IHOP statistics" is_instant="true"
-           description="Statistics related to current adaptive IHOP calculation">
-      <value type="UINT" field="gcId" label="GC ID" relation="GC_ID"/>
-      <value type="BYTES64" field="threshold" label="Current IHOP threshold" description="Current IHOP threshold in bytes"/>
-      <value type="BYTES64" field="thresholdPercentage" label="Current IHOP threshold in percent" description="Current IHOP threshold in percent of the internal target occupancy"/>
-      <value type="BYTES64" field="internalTargetOccupancy" label="Target occupancy" description="Internal target old gen occupancy to reach at the start of mixed GC in bytes"/>
-      <value type="BYTES64" field="currentOccupancy" label="Current occupancy" description="Current old gen occupancy in bytes"/>
-      <value type="BYTES64" field="additionalBufferSize" label="Additional buffer size" description="Additional buffer size in bytes"/>
-      <value type="DOUBLE" field="predictedAllocationRate" label="Predicted mutator allocation rate" description="Current predicted allocation rate for the mutator in bytes/second"/>
-      <value type="DOUBLE" field="predictedMarkingLength" label="Predicted time from initial mark to first mixed GC" description="Current predicted time from the end of the last initial mark to the first mixed GC in seconds"/>
-      <value type="BOOLEAN" field="predictionActive" label="Prediction active" description="Indicates whether the adaptive IHOP prediction is active"/>
-    </event>
-
-    <!-- Promotion events, Supported GCs are Parallel Scavange, G1 and CMS with Parallel New. -->
-    <event id="PromoteObjectInNewPLAB" path="vm/gc/detailed/object_promotion_in_new_PLAB" label="Promotion in new PLAB"
-        description="Object survived scavenge and was copied to a new Promotion Local Allocation Buffer (PLAB). Supported GCs are Parallel Scavange, G1 and CMS with Parallel New. Due to promotion being done in parallel an object might be reported multiple times as the GC threads race to copy all objects." 
-           has_thread="true" has_stacktrace="false" is_instant="true">
-      <value type="UINT" field="gcId" label="GC ID" relation="GC_ID" description="ID of GC during which the object was promoted"/>
-      <value type="CLASS" field="class" label="Class" description="Class of promoted object"/>
-      <value type="BYTES64" field="objectSize" label="Object Size" description="Size of promoted object"/>
-      <value type="UINT" field="tenuringAge" label="Object Tenuring Age" description="Tenuring age of a surviving object before being copied. The tenuring age of an object is a value between 0-15 and is incremented each scavange the object survives. Newly allocated objects have tenuring age 0."/>
-      <value type="BOOLEAN" field="tenured" label="Tenured" description="True if object was promoted to Old space, otherwise the object was aged and copied to a Survivor space"/>
-      <value type="BYTES64" field="plabSize" label="PLAB Size" description="Size of the allocated PLAB to which the object was copied"/>
-    </event>
-    
-    <event id="PromoteObjectOutsidePLAB" path="vm/gc/detailed/object_promotion_outside_PLAB" label="Promotion outside PLAB"
-        description="Object survived scavenge and was copied directly to the heap. Supported GCs are Parallel Scavange, G1 and CMS with Parallel New. Due to promotion being done in parallel an object might be reported multiple times as the GC threads race to copy all objects." 
-           has_thread="true" has_stacktrace="false" is_instant="true">
-      <value type="UINT" field="gcId" label="GC ID" relation="GC_ID" description="ID of GC during which the object was promoted"/>
-      <value type="CLASS" field="class" label="Class" description="Class of promoted object"/>
-      <value type="BYTES64" field="objectSize" label="Object Size" description="Size of promoted object"/>
-      <value type="UINT" field="tenuringAge" label="Object Tenuring Age" description="Tenuring age of a surviving object before being copied. The tenuring age of an object is a value between 0-15 and is incremented each scavange the object survives. Newly allocated objects have tenuring age 0."/>
-      <value type="BOOLEAN" field="tenured" label="Tenured" description="True if object was promoted to Old space, otherwise the object was aged and copied to a Survivor space"/>
-    </event>
-
-    <event id="PromotionFailed" path="vm/gc/detailed/promotion_failed" label="Promotion Failed" is_instant="true"
-           description="Promotion of an object failed">
-      <value type="UINT" field="gcId" label="GC ID" relation="GC_ID"/>
-      <structvalue type="CopyFailed" field="data" label="Data"/>
-      <value type="THREAD" field="thread" label="Running thread"/>
-    </event>
-
-    <event id="EvacuationFailed" path="vm/gc/detailed/evacuation_failed" label="Evacuation Failed" is_instant="true"
-           description="Evacuation of an object failed">
-      <value type="UINT" field="gcId" label="GC ID" relation="GC_ID"/>
-      <structvalue type="CopyFailed" field="data" label="Data"/>
-    </event>
-
-    <event id="ConcurrentModeFailure" path="vm/gc/detailed/concurrent_mode_failure" label="Concurrent Mode Failure"
-           is_instant="true" description="Concurrent Mode failed">
-      <value type="UINT" field="gcId" label="GC ID" relation="GC_ID"/>
-    </event>
-
-    <event id="GCPhasePause" path="vm/gc/phases/pause" label="GC Phase Pause">
-      <value type="UINT" field="gcId" label="GC ID" relation="GC_ID"/>
-      <value type="UTF8" field="name" label="Name" />
-    </event>
-
-    <event id="GCPhasePauseLevel1" path="vm/gc/phases/pause_level_1" label="GC Phase Pause Level 1">
-      <value type="UINT" field="gcId" label="GC ID" relation="GC_ID"/>
-      <value type="UTF8" field="name" label="Name" />
-    </event>
-
-    <event id="GCPhasePauseLevel2" path="vm/gc/phases/pause_level_2" label="GC Phase Pause Level 2">
-      <value type="UINT" field="gcId" label="GC ID" relation="GC_ID"/>
-      <value type="UTF8" field="name" label="Name" />
-    </event>
-
-    <event id="GCPhasePauseLevel3" path="vm/gc/phases/pause_level_3" label="GC Phase Pause Level 3">
-      <value type="UINT" field="gcId" label="GC ID" relation="GC_ID"/>
-      <value type="UTF8" field="name" label="Name" />
-    </event>
-
-    <event id="GCPhaseConcurrent" path="vm/gc/phases/concurrent" label="GC Phase Concurrent">
-      <value type="UINT" field="gcId" label="GC ID" relation="GC_ID"/>
-      <value type="UTF8" field="name" label="Name" />
-    </event>
-
-    <event id="AllocationRequiringGC" path="vm/gc/detailed/allocation_requiring_gc" label="Allocation Requiring GC"
-           has_thread="true" has_stacktrace="true"  is_instant="true">
-      <value type="UINT" field="gcId"  label="Pending GC ID" relation="GC_ID" />
-      <value type="BYTES64" field="size" label="Allocation Size" />
-    </event>
-
-    <event id="TenuringDistribution" path="vm/gc/detailed/tenuring_distribution" label="Tenuring Distribution"
-           is_instant="true">
-      <value type="UINT" field="gcId" label="GC ID" relation="GC_ID"/>
-      <value type="UINT" field="age" label="Age" />
-      <value type="BYTES64" field="size" label="Size" />
-    </event>
-
-    <event id="G1HeapRegionTypeChange" path="vm/gc/detailed/g1_heap_region_type_change" label="G1 Heap Region Type Change"
-           description="Information about a G1 heap region type change." is_instant="true">
-      <value type="UINT" field="index" label="Index" />
-      <value type="G1HEAPREGIONTYPE" field="from" label="From Type" />
-      <value type="G1HEAPREGIONTYPE" field="to" label="To Type" />
-      <value type="ADDRESS" field="start" label="Start" />
-      <value type="BYTES64" field="used" label="Used" />
-      <value type="UINT" field="allocContext" label="Allocation Context" />
-    </event>
-
-    <event id="VMError" path="vm/runtime/vm_error" label="VM Error"
-           description="VM shutdown due to an error" has_stacktrace="true" has_thread="true">
-      <value type="BOOLEAN" field="out_of_java_memory" label="Java Out Of Memory"/>
-    </event>
-
-    <!-- Compiler events -->
-
-    <event id="Compilation" path="vm/compiler/compilation" label="Compilation"
-         has_thread="true" is_requestable="false" is_constant="false">
-      <value type="METHOD" field="method" label="Java Method"/>
-      <value type="UINT" field="compileID" label="Compilation ID" relation="COMP_ID"/>
-      <value type="USHORT" field="compileLevel" label="Compilation Level"/>
-      <value type="BOOLEAN" field="succeded" label="Succeeded"/>
-      <value type="BOOLEAN" field="isOsr" label="On Stack Replacement"/>
-      <value type="BYTES" field="codeSize" label="Compiled Code Size"/>
-      <value type="BYTES" field="inlinedBytes" label="Inlined Code Size"/>
-    </event>
-
-    <event id="CompilerPhase" path="vm/compiler/phase" label="Compiler Phase"
-            has_thread="true" is_requestable="false" is_constant="false">
-      <value type="COMPILERPHASETYPE" field="phase" label="Compile Phase"/>
-      <value type="UINT" field="compileID" label="Compilation ID" relation="COMP_ID"/>
-      <value type="USHORT" field="phaseLevel" label="Phase Level"/>
-    </event>
-
-    <event id="CompilerFailure" path="vm/compiler/failure" label="Compilation Failure"
-            has_thread="true" is_requestable="false" is_constant="false" is_instant="true">
-      <value type="UTF8" field="failure" label="Message"/>
-      <value type="UINT" field="compileID" label="Compilation ID" relation="COMP_ID"/>
-    </event>
-
-    <struct id="CiMethod">
-      <value type="UTF8" field="class" label="Class name"/>
-      <value type="UTF8" field="name" label="Method name"/>
-      <value type="UTF8" field="signature" label="Method signature"/>
-    </struct>
-
-    <event id="CompilerInlining" path="vm/compiler/optimization/inlining" label="Method Inlining"
-         has_thread="true" is_instant="true">
-      <value type="UINT" field="compileID" label="Compilation ID" relation="COMP_ID"/>
-      <value type="METHOD" field="caller" label="Caller Method"/>
-      <structvalue type="CiMethod" field="callee" label="Callee Method"/>
-      <value type="BOOLEAN" field="succeeded" label="Succeeded"/>
-      <value type="UTF8" field="message" label="Message"/>
-      <value type="INTEGER" field="bci" label="Byte Code Index"/>
-    </event>
-
-    <!-- Code sweeper events -->
-
-    <event id="SweepCodeCache" path="vm/code_sweeper/sweep" label="Sweep Code Cache"
-       has_thread="true" is_requestable="false" is_constant="false">
-      <value type="INTEGER" field="sweepIndex" label="Sweep Index" relation="SWEEP_ID"/>
-      <value type="UINT" field="sweptCount" label="Methods Swept"/>
-      <value type="UINT" field="flushedCount" label="Methods Flushed"/>
-      <value type="UINT" field="markedCount" label="Methods Reclaimed"/>
-      <value type="UINT" field="zombifiedCount" label="Methods Zombified"/>
-    </event>
-
-    <!-- Code cache events -->
-
-    <event id="CodeCacheFull" path="vm/code_cache/full" label="Code Cache Full"
-         has_thread="true" is_requestable="false" is_constant="false" is_instant="true">
-      <value type="CODEBLOBTYPE" field="codeBlobType" label="Code Heap"/>
-      <value type="ADDRESS" field="startAddress" label="Start Address"/>
-      <value type="ADDRESS" field="commitedTopAddress" label="Commited Top"/>
-      <value type="ADDRESS" field="reservedTopAddress" label="Reserved Top"/>
-      <value type="INTEGER" field="entryCount" label="Entries"/>
-      <value type="INTEGER" field="methodCount" label="Methods"/>
-      <value type="INTEGER" field="adaptorCount" label="Adaptors"/>
-      <value type="BYTES64" field="unallocatedCapacity" label="Unallocated"/>
-      <value type="INTEGER" field="fullCount" label="Full Count"/>
-    </event>
-
-    <event id="ExecuteVMOperation" path="vm/runtime/execute_vm_operation" label="VM Operation"
-        description="Execution of a VM Operation" has_thread="true">
-      <value type="VMOPERATIONTYPE" field="operation" label="Operation" />
-      <value type="BOOLEAN" field="safepoint" label="At Safepoint" description="If the operation occured at a safepoint."/>
-      <value type="BOOLEAN" field="blocking" label="Caller Blocked" description="If the calling thread was blocked until the operation was complete."/>
-      <value type="THREAD" field="caller" label="Caller" transition="FROM" description="Thread requesting operation. If non-blocking, will be set to 0 indicating thread is unknown."/>
-    </event>
-
-    <!-- Allocation events -->
-    <event id="AllocObjectInNewTLAB" path="java/object_alloc_in_new_TLAB" label="Allocation in new TLAB"
-        description="Allocation in new Thread Local Allocation Buffer" has_thread="true" has_stacktrace="true" is_instant="true">
-      <value type="CLASS" field="class" label="Class" description="Class of allocated object"/>
-      <value type="BYTES64" field="allocationSize" label="Allocation Size"/>
-      <value type="BYTES64" field="tlabSize" label="TLAB Size"/>
-    </event>
-
-    <event id="AllocObjectOutsideTLAB" path="java/object_alloc_outside_TLAB" label="Allocation outside TLAB"
-        description="Allocation outside Thread Local Allocation Buffers" has_thread="true" has_stacktrace="true" is_instant="true">
-      <value type="CLASS" field="class" label="Class" description="Class of allocated object"/>
-      <value type="BYTES64" field="allocationSize" label="Allocation Size"/>
-    </event>
-  </events>
-
-  <xi:include href="../../../closed/share/vm/trace/traceeventtypes.xml" xmlns:xi="http://www.w3.org/2001/XInclude">
-    <xi:fallback/>
-  </xi:include>
-
-  <xi:include href="../../../closed/share/vm/trace/traceevents.xml" xmlns:xi="http://www.w3.org/2001/XInclude">
-    <xi:fallback/>
-  </xi:include>
+  <xi:include href="tracetypes.xml"
+              xmlns:xi="http://www.w3.org/2001/XInclude"/>
+  <xi:include href="tracerelationdecls.xml"
+              xmlns:xi="http://www.w3.org/2001/XInclude"/>
+  <xi:include href="traceevents.xml"
+              xmlns:xi="http://www.w3.org/2001/XInclude"/>
 </trace>
--- a/hotspot/src/share/vm/trace/traceMacros.hpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/trace/traceMacros.hpp	Wed Mar 23 23:36:29 2016 +0100
@@ -30,6 +30,7 @@
 #define EVENT_THREAD_EXIT(thread)
 #define EVENT_THREAD_DESTRUCT(thread)
 #define TRACE_KLASS_CREATION(k, p, t)
+#define TRACE_KLASS_DEFINITION(k, t)
 
 #define TRACE_INIT_KLASS_ID(k)
 #define TRACE_INIT_MODULE_ID(m)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/trace/traceevents.xml	Wed Mar 23 23:36:29 2016 +0100
@@ -0,0 +1,619 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (c) 2012, 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.
+
+-->
+
+
+<!DOCTYPE events SYSTEM "trace.dtd">
+
+<events>
+
+<!--
+
+Events in the JVM are by default timed (it's more common)
+Perhaps a little strange. Might change.
+
+EVENTS
+
+Declard with the 'event' tag.
+
+<value fields> can be one or more of
+   value            - a simple primitive or constant type value
+   structvalue      - value is a sub-struct. This type must be previously defined
+                      with 'struct'
+All these require you to declare type, field and label of the field. They also accept
+an optional description of the field. If the meaning of the field is not obvious
+from the label you should provide a description. If an event however is not actually
+meant for end-users, you should probably _not_ write descriptions at all, since you
+might just add more concepts the user has no notion of/interest in.
+
+Events should be modeled after what conceptual process you are expressing, _NOT_
+from whatever data structures you might use inside the JVM for expressing a process.
+
+
+STRUCT
+
+Declared with the 'struct' tag.
+
+Declares a structure type that can be used in other events.
+
+-->
+
+  <event id="ThreadStart" path="java/thread_start" label="Java Thread Start"
+         has_thread="true" is_instant="true">
+    <value type="THREAD" field="thread" label="Java Thread"/>
+  </event>
+
+  <event id="ThreadEnd" path="java/thread_end" label="Java Thread End"
+         has_thread="true" is_instant="true">
+    <value type="THREAD" field="thread" label="Java Thread"/>
+  </event>
+
+  <event id="ThreadSleep" path="java/thread_sleep" label="Java Thread Sleep"
+          has_thread="true" has_stacktrace="true" is_instant="false">
+    <value type="MILLIS" field="time" label="Sleep Time"/>
+  </event>
+
+  <event id="ThreadPark" path="java/thread_park" label="Java Thread Park"
+          has_thread="true" has_stacktrace="true" is_instant="false">
+    <value type="CLASS" field="klass" label="Class Parked On"/>
+    <value type="MILLIS" field="timeout" label="Park Timeout"/>
+    <value type="ADDRESS" field="address" label="Address of Object Parked" relation="JAVA_MONITOR_ADDRESS"/>
+  </event>
+
+  <event id="JavaMonitorEnter" path="java/monitor_enter" label="Java Monitor Blocked"
+          has_thread="true" has_stacktrace="true" is_instant="false">
+    <value type="CLASS" field="klass" label="Monitor Class"/>
+    <value type="THREAD" field="previousOwner" label="Previous Monitor Owner"/>
+    <value type="ADDRESS" field="address" label="Monitor Address" relation="JAVA_MONITOR_ADDRESS"/>
+  </event>
+
+  <event id="JavaMonitorWait" path="java/monitor_wait" label="Java Monitor Wait" description="Waiting on a Java monitor"
+          has_thread="true" has_stacktrace="true" is_instant="false">
+    <value type="CLASS" field="klass" label="Monitor Class" description="Class of object waited on"/>
+    <value type="THREAD" field="notifier" label="Notifier Thread" description="Notifying Thread"/>
+    <value type="MILLIS" field="timeout" label="Timeout" description="Maximum wait time"/>
+    <value type="BOOLEAN" field="timedOut" label="Timed Out" description="Wait has been timed out"/>
+    <value type="ADDRESS" field="address" label="Monitor Address" description="Address of object waited on" relation="JAVA_MONITOR_ADDRESS"/>
+  </event>
+
+  <event id="JavaMonitorInflate" path="java/monitor_inflate" label="Java Monitor Inflated"
+         has_thread="true" has_stacktrace="true" is_instant="false">
+    <value type="CLASS" field="klass" label="Monitor Class"/>
+    <value type="ADDRESS" field="address" label="Monitor Address" relation="JAVA_MONITOR_ADDRESS"/>
+    <value type="INFLATECAUSE" field="cause" label="Cause" description="Cause of inflation"/>
+  </event>
+
+  <event id="ReservedStackActivation" path="java/reserved_stack_activation" label="Reserved Stack Activation" description="Activation of Reserved Stack Area caused by stack overflow with ReservedStackAccess annotated method in call stack"
+          has_thread="true" has_stacktrace="true" is_instant="true">
+      <value type="METHOD" field="method" label="Java Method"/>
+  </event>
+
+  <event id="ClassLoad" path="vm/class/load" label="Class Load"
+          has_thread="true" has_stacktrace="true" is_instant="false">
+    <value type="CLASS" field="loadedClass" label="Loaded Class"/>
+    <value type="CLASS" field="definingClassLoader" label="Defining Class Loader"/>
+    <value type="CLASS" field="initiatingClassLoader" label="Initiating Class Loader"/>
+  </event>
+
+  <event id="ClassUnload" path="vm/class/unload" label="Class Unload"
+      has_thread="true" is_instant="true">
+    <value type="CLASS" field="unloadedClass" label="Unloaded Class"/>
+    <value type="CLASS" field="definingClassLoader" label="Defining Class Loader"/>
+  </event>
+
+  <event id="IntFlagChanged" path="vm/flag/int_changed" label="Int Flag Changed"
+        is_instant="true">
+    <value type="UTF8" field="name" label="Name" />
+    <value type="INTEGER" field="old_value" label="Old Value" />
+    <value type="INTEGER" field="new_value" label="New Value" />
+    <value type="FLAGVALUEORIGIN" field="origin" label="Origin" />
+  </event>
+
+  <event id="UnsignedIntFlagChanged" path="vm/flag/uint_changed" label="Unsigned Int Flag Changed"
+        is_instant="true">
+    <value type="UTF8" field="name" label="Name" />
+    <value type="UINT" field="old_value" label="Old Value" />
+    <value type="UINT" field="new_value" label="New Value" />
+    <value type="FLAGVALUEORIGIN" field="origin" label="Origin" />
+  </event>
+
+  <event id="LongFlagChanged" path="vm/flag/long_changed" label="Long Flag Changed"
+        is_instant="true">
+    <value type="UTF8" field="name" label="Name" />
+    <value type="LONG" field="old_value" label="Old Value" />
+    <value type="LONG" field="new_value" label="New Value" />
+    <value type="FLAGVALUEORIGIN" field="origin" label="Origin" />
+  </event>
+
+  <event id="UnsignedLongFlagChanged" path="vm/flag/ulong_changed" label="Unsigned Long Flag Changed"
+        is_instant="true">
+    <value type="UTF8" field="name" label="Name" />
+    <value type="ULONG" field="old_value" label="Old Value" />
+    <value type="ULONG" field="new_value" label="New Value" />
+    <value type="FLAGVALUEORIGIN" field="origin" label="Origin" />
+  </event>
+
+  <event id="DoubleFlagChanged" path="vm/flag/double_changed" label="Double Flag Changed"
+       is_instant="true">
+    <value type="UTF8" field="name" label="Name" />
+    <value type="DOUBLE" field="old_value" label="Old Value" />
+    <value type="DOUBLE" field="new_value" label="New Value" />
+    <value type="FLAGVALUEORIGIN" field="origin" label="Origin" />
+  </event>
+
+  <event id="BooleanFlagChanged" path="vm/flag/boolean_changed" label="Boolean Flag Changed"
+       is_instant="true">
+    <value type="UTF8" field="name" label="Name" />
+    <value type="BOOLEAN" field="old_value" label="Old Value" />
+    <value type="BOOLEAN" field="new_value" label="New Value" />
+    <value type="FLAGVALUEORIGIN" field="origin" label="Origin" />
+  </event>
+
+  <event id="StringFlagChanged" path="vm/flag/string_changed" label="String Flag Changed"
+       is_instant="true">
+    <value type="UTF8" field="name" label="Name" />
+    <value type="UTF8" field="old_value" label="Old Value" />
+    <value type="UTF8" field="new_value" label="New Value" />
+    <value type="FLAGVALUEORIGIN" field="origin" label="Origin" />
+  </event>
+
+  <struct id="VirtualSpace">
+    <value type="ADDRESS" field="start" label="Start Address" description="Start address of the virtual space" />
+    <value type="ADDRESS" field="committedEnd" label="Committed End Address" description="End address of the committed memory for the virtual space" />
+    <value type="BYTES64" field="committedSize" label="Committed Size" description="Size of the committed memory for the virtual space" />
+    <value type="ADDRESS" field="reservedEnd" label="Reserved End Address" description="End address of the reserved memory for the virtual space" />
+    <value type="BYTES64" field="reservedSize" label="Reserved Size" description="Size of the reserved memory for the virtual space" />
+  </struct>
+
+  <struct id="ObjectSpace">
+    <value type="ADDRESS" field="start" label="Start Address" description="Start address of the space" />
+    <value type="ADDRESS" field="end" label="End Address" description="End address of the space" />
+    <value type="BYTES64" field="used" label="Used" description="Bytes allocated by objects in the space" />
+    <value type="BYTES64" field="size" label="Size" description="Size of the space" />
+  </struct>
+
+  <event id="GCHeapSummary" path="vm/gc/heap/summary" label="Heap Summary" is_instant="true">
+    <value type="UINT" field="gcId" label="GC ID" relation="GC_ID"/>
+    <value type="GCWHEN" field="when" label="When" />
+    <structvalue type="VirtualSpace" field="heapSpace" label="Heap Space"/>
+    <value type="BYTES64" field="heapUsed" label="Heap Used" description="Bytes allocated by objects in the heap"/>
+  </event>
+
+  <struct id="MetaspaceSizes">
+    <value type="BYTES64" field="committed" label="Committed" description="Committed memory for this space" />
+    <value type="BYTES64" field="used" label="Used" description="Bytes allocated by objects in the space" />
+    <value type="BYTES64" field="reserved" label="Reserved" description="Reserved memory for this space" />
+  </struct>
+
+  <event id="MetaspaceSummary" path="vm/gc/heap/metaspace_summary" label="Metaspace Summary" is_instant="true">
+    <value type="UINT" field="gcId" label="GC ID" relation="GC_ID"/>
+    <value type="GCWHEN" field="when" label="When" />
+    <value type="BYTES64" field="gcThreshold" label="GC Threshold" />
+    <structvalue type="MetaspaceSizes" field="metaspace" label="Total"/>
+    <structvalue type="MetaspaceSizes" field="dataSpace" label="Data"/>
+    <structvalue type="MetaspaceSizes" field="classSpace" label="Class"/>
+  </event>
+
+  <event id="MetaspaceGCThreshold" path="vm/gc/metaspace/gc_threshold" label="Metaspace GC Threshold" is_instant="true">
+    <value type="BYTES64" field="oldValue" label="Old Value" />
+    <value type="BYTES64" field="newValue" label="New Value" />
+    <value type="GCTHRESHOLDUPDATER" field="updater" label="Updater" />
+  </event>
+
+  <event id="MetaspaceAllocationFailure" path="vm/gc/metaspace/allocation_failure" label="Metaspace Allocation Failure" is_instant="true" has_stacktrace="true">
+    <value type="CLASS" field="classLoader" label="Class Loader" />
+    <value type="BOOLEAN" field="anonymousClassLoader" label="Anonymous Class Loader" />
+    <value type="BYTES64" field="size" label="Size" />
+    <value type="METADATATYPE" field="metadataType" label="Metadata Type" />
+    <value type="METASPACEOBJTYPE" field="metaspaceObjectType" label="Metaspace Object Type" />
+  </event>
+
+  <event id="MetaspaceOOM" path="vm/gc/metaspace/out_of_memory" label="Metaspace Out of Memory" is_instant="true" has_stacktrace="true">
+    <value type="CLASS" field="classLoader" label="Class Loader" />
+    <value type="BOOLEAN" field="anonymousClassLoader" label="Anonymous Class Loader" />
+    <value type="BYTES64" field="size" label="Size" />
+    <value type="METADATATYPE" field="metadataType" label="Metadata Type" />
+    <value type="METASPACEOBJTYPE" field="metaspaceObjectType" label="Metaspace Object Type" />
+  </event>
+
+  <event id="MetaspaceChunkFreeListSummary" path="vm/gc/metaspace/chunk_free_list_summary" label="Metaspace Chunk Free List Summary" is_instant="true">
+    <value type="UINT" field="gcId" label="GC ID" relation="GC_ID"/>
+    <value type="GCWHEN" field="when" label="When" />
+    <value type="METADATATYPE" field="metadataType" label="Metadata Type" />
+    <value type="ULONG" field="specializedChunks" label="Specialized Chunks" />
+    <value type="BYTES64" field="specializedChunksTotalSize" label="Specialized Chunks Total Size" />
+    <value type="ULONG" field="smallChunks" label="Small Chunks" />
+    <value type="BYTES64" field="smallChunksTotalSize" label="Small Chunks Total Size" />
+    <value type="ULONG" field="mediumChunks" label="Medium Chunks" />
+    <value type="BYTES64" field="mediumChunksTotalSize" label="Medium Chunks Total Size" />
+    <value type="ULONG" field="humongousChunks" label="Humongous Chunks" />
+    <value type="BYTES64" field="humongousChunksTotalSize" label="Humongous Chunks Total Size" />
+  </event>
+
+  <event id="PSHeapSummary" path="vm/gc/heap/ps_summary" label="Parallel Scavenge Heap Summary" is_instant="true">
+    <value type="UINT" field="gcId" label="GC ID" relation="GC_ID"/>
+    <value type="GCWHEN" field="when" label="When" />
+
+    <structvalue type="VirtualSpace" field="oldSpace" label="Old Space"/>
+    <structvalue type="ObjectSpace" field="oldObjectSpace" label="Old Object Space"/>
+
+    <structvalue type="VirtualSpace" field="youngSpace" label="Young Space"/>
+    <structvalue type="ObjectSpace" field="edenSpace" label="Eden Space"/>
+    <structvalue type="ObjectSpace" field="fromSpace" label="From Space"/>
+    <structvalue type="ObjectSpace" field="toSpace" label="To Space"/>
+  </event>
+
+  <event id="G1HeapSummary" path="vm/gc/heap/g1_summary" label="G1 Heap Summary" is_instant="true">
+    <value type="UINT" field="gcId" label="GC ID" relation="GC_ID"/>
+    <value type="GCWHEN" field="when" label="When" />
+
+    <value type="BYTES64" field="edenUsedSize" label="Eden Used Size" />
+    <value type="BYTES64" field="edenTotalSize" label="Eden Total Size" />
+    <value type="BYTES64" field="survivorUsedSize" label="Survivor Used Size" />
+    <value type="UINT" field="numberOfRegions" label="Number of Regions" />
+  </event>
+
+  <event id="GCGarbageCollection" path="vm/gc/collector/garbage_collection" label="Garbage Collection"
+         description="Garbage collection performed by the JVM">
+    <value type="UINT" field="gcId"  label="GC ID" relation="GC_ID" />
+    <value type="GCNAME" field="name" label="Name" description="The name of the Garbage Collector" />
+    <value type="GCCAUSE" field="cause" label="Cause" description="The reason for triggering this Garbage Collection" />
+    <value type="TICKSPAN" field="sumOfPauses" label="Sum of Pauses" description="Sum of all the times in which Java execution was paused during the garbage collection" />
+    <value type="TICKSPAN" field="longestPause" label="Longest Pause" description="Longest individual pause during the garbage collection" />
+  </event>
+
+  <event id="GCParallelOld" path="vm/gc/collector/parold_garbage_collection" label="Parallel Old Garbage Collection"
+         description="Extra information specific to Parallel Old Garbage Collections">
+    <value type="UINT" field="gcId"  label="GC ID" relation="GC_ID" />
+    <value type="ADDRESS" field="densePrefix" label="Dense Prefix" description="The address of the dense prefix, used when compacting" />
+  </event>
+
+  <event id="GCYoungGarbageCollection" path="vm/gc/collector/young_garbage_collection" label="Young Garbage Collection"
+         description="Extra information specific to Young Garbage Collections">
+    <value type="UINT" field="gcId"  label="GC ID" relation="GC_ID" />
+    <value type="UINT" field="tenuringThreshold" label="Tenuring Threshold" />
+  </event>
+
+  <event id="GCOldGarbageCollection" path="vm/gc/collector/old_garbage_collection" label="Old Garbage Collection"
+         description="Extra information specific to Old Garbage Collections">
+    <value type="UINT" field="gcId" label="GC ID" relation="GC_ID"/>
+  </event>
+
+  <event id="GCG1GarbageCollection" path="vm/gc/collector/g1_garbage_collection" label="G1 Garbage Collection"
+         description="Extra information specific to G1 Garbage Collections">
+    <value type="UINT" field="gcId" label="GC ID" relation="GC_ID"/>
+    <value type="G1YCTYPE" field="type" label="Type" />
+  </event>
+
+  <event id="GCG1MMU" path="vm/gc/detailed/g1_mmu_info" label="G1 MMU Information" is_instant="true">
+    <value type="UINT" field="gcId" label="GC ID" relation="GC_ID"/>
+    <value type="DOUBLE" field="timeSlice" label="Time slice used to calculate MMU"/>
+    <value type="DOUBLE" field="gcTime" label="Time spent on GC during last time slice"/>
+    <value type="DOUBLE" field="maxGcTime" label="Max time allowed to be spent on GC during last time slice"/>
+  </event>
+
+  <event id="EvacuationInfo" path="vm/gc/detailed/evacuation_info" label="Evacuation Information" is_instant="true">
+    <value type="UINT" field="gcId" label="GC ID" relation="GC_ID"/>
+    <value type="UINT" field="cSetRegions" label="Collection Set Regions"/>
+    <value type="BYTES64" field="cSetUsedBefore" label="Collection Set Before" description="Memory usage before GC in the collection set regions"/>
+    <value type="BYTES64" field="cSetUsedAfter" label="Collection Set After" description="Memory usage after GC in the collection set regions"/>
+    <value type="UINT" field="allocationRegions" label="Allocation Regions" description="Regions chosen as allocation regions during evacuation (includes survivors and old space regions)"/>
+    <value type="BYTES64" field="allocRegionsUsedBefore" label="Alloc Regions Before" description="Memory usage before GC in allocation regions"/>
+    <value type="BYTES64" field="allocRegionsUsedAfter" label="Alloc Regions After" description="Memory usage after GC in allocation regions"/>
+    <value type="BYTES64" field="bytesCopied" label="Bytes Copied"/>
+    <value type="UINT" field="regionsFreed" label="Regions Freed"/>
+  </event>
+
+  <event id="GCReferenceStatistics" path="vm/gc/reference/statistics"
+         label="GC Reference Statistics" is_instant="true"
+         description="Total count of processed references during GC">
+    <value type="UINT" field="gcId" label="GC ID" relation="GC_ID"/>
+    <value type="REFERENCETYPE" field="type" label="Type" />
+    <value type="ULONG" field="count" label="Total Count" />
+  </event>
+
+  <struct id="CopyFailed">
+    <value type="ULONG" field="objectCount" label="Object Count"/>
+    <value type="BYTES64" field="firstSize" label="First Failed Object Size"/>
+    <value type="BYTES64" field="smallestSize" label="Smallest Failed Object Size"/>
+    <value type="BYTES64" field="totalSize" label="Total Object Size"/>
+  </struct>
+
+  <event id="ObjectCountAfterGC" path="vm/gc/detailed/object_count_after_gc" is_instant="true" label="Object Count after GC">
+    <value type="UINT" field="gcId"  label="GC ID" relation="GC_ID" />
+    <value type="CLASS" field="class" label="Class" />
+    <value type="LONG" field="count" label="Count" />
+    <value type="BYTES64" field="totalSize" label="Total Size" />
+  </event>
+
+  <struct id="G1EvacStats">
+    <value type="UINT" field="gcId" label="GC ID" relation="GC_ID"/>
+    <value type="BYTES64" field="allocated" label="Allocated" description="Total memory allocated by PLABs"/>
+    <value type="BYTES64" field="wasted" label="Wasted" description="Total memory wasted within PLABs due to alignment or refill"/>
+    <value type="BYTES64" field="used" label="Used" description="Total memory occupied by objects within PLABs"/>
+    <value type="BYTES64" field="undoWaste" label="Undo Wasted" description="Total memory wasted due to allocation undo within PLABs"/>
+    <value type="BYTES64" field="regionEndWaste" label="Region End Wasted" description="Total memory wasted at the end of regions due to refill"/>
+    <value type="UINT" field="regionsRefilled" label="Region Refills" description="Total memory wasted at the end of regions due to refill"/>
+    <value type="BYTES64" field="directAllocated" label="Allocated (direct)" description="Total memory allocated using direct allocation outside of PLABs"/>
+    <value type="BYTES64" field="failureUsed" label="Used (failure)" description="Total memory occupied by objects in regions where evacuation failed"/>
+    <value type="BYTES64" field="failureWaste" label="Wasted (failure)" description="Total memory left unused in regions where evacuation failed"/>
+  </struct>
+
+  <event id="GCG1EvacuationYoungStatistics" path="vm/gc/detailed/g1_evac_young_stats" label="G1 Evacuation Statistics for Young" is_instant="true"
+         description="Memory related evacuation statistics during GC for the young generation">
+    <structvalue type="G1EvacStats" field="stats" label="Evacuation statistics"/>
+  </event>
+
+  <event id="GCG1EvacuationOldStatistics" path="vm/gc/detailed/g1_evac_old_stats" label="G1 Evacuation Memory Statistics for Old" is_instant="true"
+         description="Memory related evacuation statistics during GC for the old generation">
+    <structvalue type="G1EvacStats" field="stats" label="Evacuation statistics"/>
+  </event>
+
+  <event id="GCG1BasicIHOP" path="vm/gc/detailed/g1_basic_ihop_status" label="G1 Basic IHOP statistics" is_instant="true"
+         description="Basic statistics related to current IHOP calculation">
+    <value type="UINT" field="gcId" label="GC ID" relation="GC_ID"/>
+    <value type="BYTES64" field="threshold" label="Current IHOP threshold" description="Current IHOP threshold in bytes"/>
+    <value type="BYTES64" field="thresholdPercentage" label="Current IHOP threshold in percent" description="Current IHOP threshold in percent of old gen"/>
+    <value type="BYTES64" field="targetOccupancy" label="Target occupancy" description="Target old gen occupancy to reach at the start of mixed GC in bytes"/>
+    <value type="BYTES64" field="currentOccupancy" label="Current occupancy" description="Current old gen occupancy in bytes"/>
+    <value type="BYTES64" field="lastAllocationSize" label="Last mutator allocation size" description="Mutator allocation during mutator operation since last GC in bytes"/>
+    <value type="DOUBLE" field="lastAllocationDuration" label="Last mutator operation duration" description="Time the mutator ran since last GC in seconds"/>
+    <value type="DOUBLE" field="lastAllocationRate" label="Last mutator allocation rate" description="Allocation rate of the mutator since last GC in bytes/second"/>
+    <value type="DOUBLE" field="lastMarkingLength" label="Last mutator time from initial mark to first mixed GC" description="Last time from the end of the last initial mark to the first mixed GC in seconds"/>
+  </event>
+
+  <event id="GCG1AdaptiveIHOP" path="vm/gc/detailed/g1_adaptive_ihop_status" label="G1 Adaptive IHOP statistics" is_instant="true"
+         description="Statistics related to current adaptive IHOP calculation">
+    <value type="UINT" field="gcId" label="GC ID" relation="GC_ID"/>
+    <value type="BYTES64" field="threshold" label="Current IHOP threshold" description="Current IHOP threshold in bytes"/>
+    <value type="BYTES64" field="thresholdPercentage" label="Current IHOP threshold in percent" description="Current IHOP threshold in percent of the internal target occupancy"/>
+    <value type="BYTES64" field="internalTargetOccupancy" label="Target occupancy" description="Internal target old gen occupancy to reach at the start of mixed GC in bytes"/>
+    <value type="BYTES64" field="currentOccupancy" label="Current occupancy" description="Current old gen occupancy in bytes"/>
+    <value type="BYTES64" field="additionalBufferSize" label="Additional buffer size" description="Additional buffer size in bytes"/>
+    <value type="DOUBLE" field="predictedAllocationRate" label="Predicted mutator allocation rate" description="Current predicted allocation rate for the mutator in bytes/second"/>
+    <value type="DOUBLE" field="predictedMarkingLength" label="Predicted time from initial mark to first mixed GC" description="Current predicted time from the end of the last initial mark to the first mixed GC in seconds"/>
+    <value type="BOOLEAN" field="predictionActive" label="Prediction active" description="Indicates whether the adaptive IHOP prediction is active"/>
+  </event>
+
+  <!-- Promotion events, Supported GCs are Parallel Scavange, G1 and CMS with Parallel New. -->
+  <event id="PromoteObjectInNewPLAB" path="vm/gc/detailed/object_promotion_in_new_PLAB" label="Promotion in new PLAB"
+      description="Object survived scavenge and was copied to a new Promotion Local Allocation Buffer (PLAB). Supported GCs are Parallel Scavange, G1 and CMS with Parallel New. Due to promotion being done in parallel an object might be reported multiple times as the GC threads race to copy all objects." 
+         has_thread="true" has_stacktrace="false" is_instant="true">
+    <value type="UINT" field="gcId" label="GC ID" relation="GC_ID" description="ID of GC during which the object was promoted"/>
+    <value type="CLASS" field="class" label="Class" description="Class of promoted object"/>
+    <value type="BYTES64" field="objectSize" label="Object Size" description="Size of promoted object"/>
+    <value type="UINT" field="tenuringAge" label="Object Tenuring Age" description="Tenuring age of a surviving object before being copied. The tenuring age of an object is a value between 0-15 and is incremented each scavange the object survives. Newly allocated objects have tenuring age 0."/>
+    <value type="BOOLEAN" field="tenured" label="Tenured" description="True if object was promoted to Old space, otherwise the object was aged and copied to a Survivor space"/>
+    <value type="BYTES64" field="plabSize" label="PLAB Size" description="Size of the allocated PLAB to which the object was copied"/>
+  </event>
+  
+  <event id="PromoteObjectOutsidePLAB" path="vm/gc/detailed/object_promotion_outside_PLAB" label="Promotion outside PLAB"
+      description="Object survived scavenge and was copied directly to the heap. Supported GCs are Parallel Scavange, G1 and CMS with Parallel New. Due to promotion being done in parallel an object might be reported multiple times as the GC threads race to copy all objects." 
+         has_thread="true" has_stacktrace="false" is_instant="true">
+    <value type="UINT" field="gcId" label="GC ID" relation="GC_ID" description="ID of GC during which the object was promoted"/>
+    <value type="CLASS" field="class" label="Class" description="Class of promoted object"/>
+    <value type="BYTES64" field="objectSize" label="Object Size" description="Size of promoted object"/>
+    <value type="UINT" field="tenuringAge" label="Object Tenuring Age" description="Tenuring age of a surviving object before being copied. The tenuring age of an object is a value between 0-15 and is incremented each scavange the object survives. Newly allocated objects have tenuring age 0."/>
+    <value type="BOOLEAN" field="tenured" label="Tenured" description="True if object was promoted to Old space, otherwise the object was aged and copied to a Survivor space"/>
+  </event>
+
+  <event id="PromotionFailed" path="vm/gc/detailed/promotion_failed" label="Promotion Failed" is_instant="true"
+         description="Promotion of an object failed">
+    <value type="UINT" field="gcId" label="GC ID" relation="GC_ID"/>
+    <structvalue type="CopyFailed" field="data" label="Data"/>
+    <value type="THREAD" field="thread" label="Running thread"/>
+  </event>
+
+  <event id="EvacuationFailed" path="vm/gc/detailed/evacuation_failed" label="Evacuation Failed" is_instant="true"
+         description="Evacuation of an object failed">
+    <value type="UINT" field="gcId" label="GC ID" relation="GC_ID"/>
+    <structvalue type="CopyFailed" field="data" label="Data"/>
+  </event>
+
+  <event id="ConcurrentModeFailure" path="vm/gc/detailed/concurrent_mode_failure" label="Concurrent Mode Failure"
+         is_instant="true" description="Concurrent Mode failed">
+    <value type="UINT" field="gcId" label="GC ID" relation="GC_ID"/>
+  </event>
+
+  <event id="GCPhasePause" path="vm/gc/phases/pause" label="GC Phase Pause" has_thread="true">
+    <value type="UINT" field="gcId" label="GC ID" relation="GC_ID"/>
+    <value type="UTF8" field="name" label="Name" />
+  </event>
+
+  <event id="GCPhasePauseLevel1" path="vm/gc/phases/pause_level_1" label="GC Phase Pause Level 1" has_thread="true">
+    <value type="UINT" field="gcId" label="GC ID" relation="GC_ID"/>
+    <value type="UTF8" field="name" label="Name" />
+  </event>
+
+  <event id="GCPhasePauseLevel2" path="vm/gc/phases/pause_level_2" label="GC Phase Pause Level 2" has_thread="true">
+    <value type="UINT" field="gcId" label="GC ID" relation="GC_ID"/>
+    <value type="UTF8" field="name" label="Name" />
+  </event>
+
+  <event id="GCPhasePauseLevel3" path="vm/gc/phases/pause_level_3" label="GC Phase Pause Level 3" has_thread="true">
+    <value type="UINT" field="gcId" label="GC ID" relation="GC_ID"/>
+    <value type="UTF8" field="name" label="Name" />
+  </event>
+
+  <event id="GCPhaseConcurrent" path="vm/gc/phases/concurrent" label="GC Phase Concurrent" has_thread="true">
+    <value type="UINT" field="gcId" label="GC ID" relation="GC_ID"/>
+    <value type="UTF8" field="name" label="Name" />
+  </event>
+
+  <event id="AllocationRequiringGC" path="vm/gc/detailed/allocation_requiring_gc" label="Allocation Requiring GC"
+         has_thread="true" has_stacktrace="true"  is_instant="true">
+    <value type="UINT" field="gcId"  label="Pending GC ID" relation="GC_ID" />
+    <value type="BYTES64" field="size" label="Allocation Size" />
+  </event>
+
+  <event id="TenuringDistribution" path="vm/gc/detailed/tenuring_distribution" label="Tenuring Distribution"
+         is_instant="true">
+    <value type="UINT" field="gcId" label="GC ID" relation="GC_ID"/>
+    <value type="UINT" field="age" label="Age" />
+    <value type="BYTES64" field="size" label="Size" />
+  </event>
+
+  <event id="G1HeapRegionTypeChange" path="vm/gc/detailed/g1_heap_region_type_change" label="G1 Heap Region Type Change"
+         description="Information about a G1 heap region type change." is_instant="true">
+    <value type="UINT" field="index" label="Index" />
+    <value type="G1HEAPREGIONTYPE" field="from" label="From Type" />
+    <value type="G1HEAPREGIONTYPE" field="to" label="To Type" />
+    <value type="ADDRESS" field="start" label="Start" />
+    <value type="BYTES64" field="used" label="Used" />
+    <value type="UINT" field="allocContext" label="Allocation Context" />
+  </event>
+
+  <event id="VMError" path="vm/runtime/vm_error" label="VM Error"
+         description="VM shutdown due to an error" has_stacktrace="true" has_thread="true">
+    <value type="BOOLEAN" field="out_of_java_memory" label="Java Out Of Memory"/>
+  </event>
+
+  <!-- Compiler events -->
+
+  <event id="Compilation" path="vm/compiler/compilation" label="Compilation"
+       has_thread="true" is_requestable="false" is_constant="false">
+    <value type="METHOD" field="method" label="Java Method"/>
+    <value type="UINT" field="compileID" label="Compilation ID" relation="COMP_ID"/>
+    <value type="USHORT" field="compileLevel" label="Compilation Level"/>
+    <value type="BOOLEAN" field="succeded" label="Succeeded"/>
+    <value type="BOOLEAN" field="isOsr" label="On Stack Replacement"/>
+    <value type="BYTES" field="codeSize" label="Compiled Code Size"/>
+    <value type="BYTES" field="inlinedBytes" label="Inlined Code Size"/>
+  </event>
+
+  <event id="CompilerPhase" path="vm/compiler/phase" label="Compiler Phase"
+          has_thread="true" is_requestable="false" is_constant="false">
+    <value type="COMPILERPHASETYPE" field="phase" label="Compile Phase"/>
+    <value type="UINT" field="compileID" label="Compilation ID" relation="COMP_ID"/>
+    <value type="USHORT" field="phaseLevel" label="Phase Level"/>
+  </event>
+
+  <event id="CompilerFailure" path="vm/compiler/failure" label="Compilation Failure"
+          has_thread="true" is_requestable="false" is_constant="false" is_instant="true">
+    <value type="UTF8" field="failure" label="Message"/>
+    <value type="UINT" field="compileID" label="Compilation ID" relation="COMP_ID"/>
+  </event>
+
+  <struct id="CiMethod">
+    <value type="UTF8" field="class" label="Class name"/>
+    <value type="UTF8" field="name" label="Method name"/>
+    <value type="UTF8" field="signature" label="Method signature"/>
+  </struct>
+
+  <event id="CompilerInlining" path="vm/compiler/optimization/inlining" label="Method Inlining"
+       has_thread="true" is_instant="true">
+    <value type="UINT" field="compileID" label="Compilation ID" relation="COMP_ID"/>
+    <value type="METHOD" field="caller" label="Caller Method"/>
+    <structvalue type="CiMethod" field="callee" label="Callee Method"/>
+    <value type="BOOLEAN" field="succeeded" label="Succeeded"/>
+    <value type="UTF8" field="message" label="Message"/>
+    <value type="INTEGER" field="bci" label="Byte Code Index"/>
+  </event>
+
+  <!-- Code sweeper events -->
+
+  <event id="SweepCodeCache" path="vm/code_sweeper/sweep" label="Sweep Code Cache"
+     has_thread="true" is_requestable="false" is_constant="false">
+    <value type="INTEGER" field="sweepIndex" label="Sweep Index" relation="SWEEP_ID"/>
+    <value type="UINT" field="sweptCount" label="Methods Swept"/>
+    <value type="UINT" field="flushedCount" label="Methods Flushed"/>
+    <value type="UINT" field="markedCount" label="Methods Reclaimed"/>
+    <value type="UINT" field="zombifiedCount" label="Methods Zombified"/>
+  </event>
+
+  <!-- Code cache events -->
+
+  <event id="CodeCacheFull" path="vm/code_cache/full" label="Code Cache Full"
+       has_thread="true" is_requestable="false" is_constant="false" is_instant="true">
+    <value type="CODEBLOBTYPE" field="codeBlobType" label="Code Heap"/>
+    <value type="ADDRESS" field="startAddress" label="Start Address"/>
+    <value type="ADDRESS" field="commitedTopAddress" label="Commited Top"/>
+    <value type="ADDRESS" field="reservedTopAddress" label="Reserved Top"/>
+    <value type="INTEGER" field="entryCount" label="Entries"/>
+    <value type="INTEGER" field="methodCount" label="Methods"/>
+    <value type="INTEGER" field="adaptorCount" label="Adaptors"/>
+    <value type="BYTES64" field="unallocatedCapacity" label="Unallocated"/>
+    <value type="INTEGER" field="fullCount" label="Full Count"/>
+  </event>
+
+  <event id="SafepointBegin" path="vm/runtime/safepoint/begin" label="Safepoint Begin"
+         description="Safepointing begin" has_thread="true">
+    <value type="INTEGER" field="safepointId" label="Safepoint ID" relation="SAFEPOINT_ID"/>
+    <value type="INTEGER" field="totalThreadCount" label="Total Threads" description="The total number of threads at the start of safe point"/>
+    <value type="INTEGER" field="jniCriticalThreadCount" label="JNI Critical Threads" description="The number of threads in JNI critical sections"/>
+  </event>
+
+  <event id="SafepointStateSync" path="vm/runtime/safepoint/statesync" label="Safepoint State Sync"
+         description="Synchronize run state of threads" has_thread="true">
+    <value type="INTEGER" field="safepointId" label="Safepoint ID" relation="SAFEPOINT_ID"/>
+    <value type="INTEGER" field="initialThreadCount" label="Initial Threads" description="The number of threads running at the beginning of state check"/>
+    <value type="INTEGER" field="runningThreadCount" label="Running Threads" description="The number of threads still running"/>
+    <value type="INTEGER" field="iterations" label="Iterations" description="Number of state check iterations"/>
+  </event>
+
+  <event id="SafepointWaitBlocked" path="vm/runtime/safepoint/waitblocked" label="Safepoint Wait Blocked"
+         description="Safepointing begin waiting on running threads to block" has_thread="true">
+    <value type="INTEGER" field="safepointId" label="Safepoint ID" relation="SAFEPOINT_ID"/>
+    <value type="INTEGER" field="runningThreadCount" label="Running Threads" description="The number running of threads wait for safe point"/>
+  </event>
+
+  <event id="SafepointCleanup" path="vm/runtime/safepoint/cleanup" label="Safepoint Cleanup"
+         description="Safepointing begin running cleanup tasks" has_thread="true">
+    <value type="INTEGER" field="safepointId" label="Safepoint ID" relation="SAFEPOINT_ID"/>
+  </event>
+
+  <event id="SafepointCleanupTask" path="vm/runtime/safepoint/cleanuptask" label="Safepoint Cleanup Task"
+         description="Safepointing begin running cleanup tasks" has_thread="true">
+    <value type="INTEGER" field="safepointId" label="Safepoint ID" relation="SAFEPOINT_ID"/>
+    <value type="UTF8" field="name" label="Task Name" description="The task name"/>
+  </event>
+
+  <event id="SafepointEnd" path="vm/runtime/safepoint/end" label="Safepoint End"
+         description="Safepointing end" has_thread="true">
+    <value type="INTEGER" field="safepointId" label="Safepoint ID" relation="SAFEPOINT_ID"/>
+  </event>
+
+  <event id="ExecuteVMOperation" path="vm/runtime/execute_vm_operation" label="VM Operation"
+      description="Execution of a VM Operation" has_thread="true">
+    <value type="VMOPERATIONTYPE" field="operation" label="Operation" />
+    <value type="BOOLEAN" field="safepoint" label="At Safepoint" description="If the operation occured at a safepoint."/>
+    <value type="BOOLEAN" field="blocking" label="Caller Blocked" description="If the calling thread was blocked until the operation was complete."/>
+    <value type="THREAD" field="caller" label="Caller" transition="FROM" description="Thread requesting operation. If non-blocking, will be set to 0 indicating thread is unknown."/>
+    <value type="INTEGER" field="safepointId" label="Safepoint ID" description="The safepoint (if any) under which this operation was completed." relation="SAFEPOINT_ID"/>
+  </event>
+
+  <!-- Allocation events -->
+  <event id="AllocObjectInNewTLAB" path="java/object_alloc_in_new_TLAB" label="Allocation in new TLAB"
+      description="Allocation in new Thread Local Allocation Buffer" has_thread="true" has_stacktrace="true" is_instant="true">
+    <value type="CLASS" field="class" label="Class" description="Class of allocated object"/>
+    <value type="BYTES64" field="allocationSize" label="Allocation Size"/>
+    <value type="BYTES64" field="tlabSize" label="TLAB Size"/>
+  </event>
+
+  <event id="AllocObjectOutsideTLAB" path="java/object_alloc_outside_TLAB" label="Allocation outside TLAB"
+      description="Allocation outside Thread Local Allocation Buffers" has_thread="true" has_stacktrace="true" is_instant="true">
+    <value type="CLASS" field="class" label="Class" description="Class of allocated object"/>
+    <value type="BYTES64" field="allocationSize" label="Allocation Size"/>
+  </event>
+</events>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/trace/tracerelationdecls.xml	Wed Mar 23 23:36:29 2016 +0100
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (c) 2012, 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.
+
+-->
+
+
+<!DOCTYPE relation_decls SYSTEM "trace.dtd">
+
+<relation_decls>
+  <relation_decl id="GC_ID" uri="vm/gc/id"/>
+  <relation_decl id="COMP_ID" uri="vm/compiler/id"/>
+  <relation_decl id="SWEEP_ID" uri="vm/code_sweeper/id"/>
+  <relation_decl id="JAVA_MONITOR_ADDRESS" uri="java/monitor/address"/>
+  <relation_decl id="SAFEPOINT_ID" uri="vm/runtime/safepoint/id"/>
+</relation_decls>
--- a/hotspot/src/share/vm/utilities/bitMap.cpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/utilities/bitMap.cpp	Wed Mar 23 23:36:29 2016 +0100
@@ -29,19 +29,25 @@
 #include "utilities/bitMap.inline.hpp"
 #include "utilities/copy.hpp"
 
-BitMap::BitMap(bm_word_t* map, idx_t size_in_bits) :
-  _map(map), _size(size_in_bits), _map_allocator(false)
+STATIC_ASSERT(sizeof(BitMap::bm_word_t) == BytesPerWord); // "Implementation assumption."
+
+BitMap::BitMap(idx_t size_in_bits, bool in_resource_area) :
+  _map(NULL), _size(0)
 {
-  assert(sizeof(bm_word_t) == BytesPerWord, "Implementation assumption.");
+  resize(size_in_bits, in_resource_area);
 }
 
+#ifdef ASSERT
+void BitMap::verify_index(idx_t index) const {
+  assert(index < _size, "BitMap index out of bounds");
+}
 
-BitMap::BitMap(idx_t size_in_bits, bool in_resource_area) :
-  _map(NULL), _size(0), _map_allocator(false)
-{
-  assert(sizeof(bm_word_t) == BytesPerWord, "Implementation assumption.");
-  resize(size_in_bits, in_resource_area);
+void BitMap::verify_range(idx_t beg_index, idx_t end_index) const {
+  assert(beg_index <= end_index, "BitMap range error");
+  // Note that [0,0) and [size,size) are both valid ranges.
+  if (end_index != _size) verify_index(end_index);
 }
+#endif // #ifdef ASSERT
 
 void BitMap::resize(idx_t size_in_bits, bool in_resource_area) {
   idx_t old_size_in_words = size_in_words();
@@ -54,7 +60,7 @@
     Copy::disjoint_words((HeapWord*)old_map, (HeapWord*) _map,
                          MIN2(old_size_in_words, new_size_in_words));
   } else {
-    _map = _map_allocator.reallocate(new_size_in_words);
+    _map = ArrayAllocator<bm_word_t, mtInternal>::reallocate(old_map, old_size_in_words, new_size_in_words);
   }
 
   if (new_size_in_words > old_size_in_words) {
--- a/hotspot/src/share/vm/utilities/bitMap.hpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/utilities/bitMap.hpp	Wed Mar 23 23:36:29 2016 +0100
@@ -48,7 +48,6 @@
   } RangeSizeHint;
 
  private:
-  ArrayAllocator<bm_word_t, mtInternal> _map_allocator;
   bm_word_t* _map;     // First word in bitmap
   idx_t      _size;    // Size of bitmap (in bits)
 
@@ -101,9 +100,8 @@
   idx_t word_index_round_up(idx_t bit) const;
 
   // Verification.
-  inline void verify_index(idx_t index) const NOT_DEBUG_RETURN;
-  inline void verify_range(idx_t beg_index, idx_t end_index) const
-    NOT_DEBUG_RETURN;
+  void verify_index(idx_t index) const NOT_DEBUG_RETURN;
+  void verify_range(idx_t beg_index, idx_t end_index) const NOT_DEBUG_RETURN;
 
   // Statistics.
   static idx_t* _pop_count_table;
@@ -114,10 +112,10 @@
  public:
 
   // Constructs a bitmap with no map, and size 0.
-  BitMap() : _map(NULL), _size(0), _map_allocator(false) {}
+  BitMap() : _map(NULL), _size(0) {}
 
   // Constructs a bitmap with the given map and size.
-  BitMap(bm_word_t* map, idx_t size_in_bits);
+  BitMap(bm_word_t* map, idx_t size_in_bits) :_map(map), _size(size_in_bits) {}
 
   // Constructs an empty bitmap of the given size (that is, this clears the
   // new bitmap).  Allocates the map array in resource area if
@@ -307,36 +305,12 @@
     return _map.size() / _bits_per_slot;
   }
 
-  bool is_valid_index(idx_t slot_index, idx_t bit_within_slot_index) {
-    verify_bit_within_slot_index(bit_within_slot_index);
-    return (bit_index(slot_index, bit_within_slot_index) < size_in_bits());
-  }
-
-  bool at(idx_t slot_index, idx_t bit_within_slot_index) const {
-    verify_bit_within_slot_index(bit_within_slot_index);
-    return _map.at(bit_index(slot_index, bit_within_slot_index));
-  }
-
-  void set_bit(idx_t slot_index, idx_t bit_within_slot_index) {
-    verify_bit_within_slot_index(bit_within_slot_index);
-    _map.set_bit(bit_index(slot_index, bit_within_slot_index));
-  }
-
-  void clear_bit(idx_t slot_index, idx_t bit_within_slot_index) {
-    verify_bit_within_slot_index(bit_within_slot_index);
-    _map.clear_bit(bit_index(slot_index, bit_within_slot_index));
-  }
-
-  void at_put(idx_t slot_index, idx_t bit_within_slot_index, bool value) {
-    verify_bit_within_slot_index(bit_within_slot_index);
-    _map.at_put(bit_index(slot_index, bit_within_slot_index), value);
-  }
-
-  void at_put_grow(idx_t slot_index, idx_t bit_within_slot_index, bool value) {
-    verify_bit_within_slot_index(bit_within_slot_index);
-    _map.at_put_grow(bit_index(slot_index, bit_within_slot_index), value);
-  }
-
+  bool is_valid_index(idx_t slot_index, idx_t bit_within_slot_index);
+  bool at(idx_t slot_index, idx_t bit_within_slot_index) const;
+  void set_bit(idx_t slot_index, idx_t bit_within_slot_index);
+  void clear_bit(idx_t slot_index, idx_t bit_within_slot_index);
+  void at_put(idx_t slot_index, idx_t bit_within_slot_index, bool value);
+  void at_put_grow(idx_t slot_index, idx_t bit_within_slot_index, bool value);
   void clear();
 };
 
--- a/hotspot/src/share/vm/utilities/bitMap.inline.hpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/utilities/bitMap.inline.hpp	Wed Mar 23 23:36:29 2016 +0100
@@ -28,18 +28,6 @@
 #include "runtime/atomic.inline.hpp"
 #include "utilities/bitMap.hpp"
 
-#ifdef ASSERT
-inline void BitMap::verify_index(idx_t index) const {
-  assert(index < _size, "BitMap index out of bounds");
-}
-
-inline void BitMap::verify_range(idx_t beg_index, idx_t end_index) const {
-  assert(beg_index <= end_index, "BitMap range error");
-  // Note that [0,0) and [size,size) are both valid ranges.
-  if (end_index != _size) verify_index(end_index);
-}
-#endif // #ifdef ASSERT
-
 inline void BitMap::set_bit(idx_t bit) {
   verify_index(bit);
   *word_addr(bit) |= bit_mask(bit);
@@ -344,6 +332,36 @@
   return get_next_zero_offset_inline(l_offset, r_offset);
 }
 
+inline bool BitMap2D::is_valid_index(idx_t slot_index, idx_t bit_within_slot_index) {
+  verify_bit_within_slot_index(bit_within_slot_index);
+  return (bit_index(slot_index, bit_within_slot_index) < size_in_bits());
+}
+
+inline bool BitMap2D::at(idx_t slot_index, idx_t bit_within_slot_index) const {
+  verify_bit_within_slot_index(bit_within_slot_index);
+  return _map.at(bit_index(slot_index, bit_within_slot_index));
+}
+
+inline void BitMap2D::set_bit(idx_t slot_index, idx_t bit_within_slot_index) {
+  verify_bit_within_slot_index(bit_within_slot_index);
+  _map.set_bit(bit_index(slot_index, bit_within_slot_index));
+}
+
+inline void BitMap2D::clear_bit(idx_t slot_index, idx_t bit_within_slot_index) {
+  verify_bit_within_slot_index(bit_within_slot_index);
+  _map.clear_bit(bit_index(slot_index, bit_within_slot_index));
+}
+
+inline void BitMap2D::at_put(idx_t slot_index, idx_t bit_within_slot_index, bool value) {
+  verify_bit_within_slot_index(bit_within_slot_index);
+  _map.at_put(bit_index(slot_index, bit_within_slot_index), value);
+}
+
+inline void BitMap2D::at_put_grow(idx_t slot_index, idx_t bit_within_slot_index, bool value) {
+  verify_bit_within_slot_index(bit_within_slot_index);
+  _map.at_put_grow(bit_index(slot_index, bit_within_slot_index), value);
+}
+
 inline void BitMap2D::clear() {
   _map.clear();
 }
--- a/hotspot/src/share/vm/utilities/debug.cpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/utilities/debug.cpp	Wed Mar 23 23:36:29 2016 +0100
@@ -224,6 +224,11 @@
   va_end(detail_args);
 }
 
+void report_vm_status_error(const char* file, int line, const char* error_msg,
+                            int status, const char* detail) {
+  report_vm_error(file, line, error_msg, "error %s(%d), %s", os::errno_name(status), status, detail);
+}
+
 void report_fatal(const char* file, int line, const char* detail_fmt, ...)
 {
   if (Debugging || error_is_suppressed(file, line)) return;
--- a/hotspot/src/share/vm/utilities/debug.hpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/utilities/debug.hpp	Wed Mar 23 23:36:29 2016 +0100
@@ -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
@@ -137,7 +137,13 @@
 // an extra arg and use strerror to convert it to a meaningful string
 // like "Invalid argument", "out of memory" etc
 #define vmassert_status(p, status, msg) \
-  vmassert(p, "error %s(%d), %s", strerror(status), status, msg)
+do {                                                                           \
+  if (!(p)) {                                                                  \
+    report_vm_status_error(__FILE__, __LINE__, "assert(" #p ") failed",        \
+                           status, msg);                                       \
+    BREAKPOINT;                                                                \
+  }                                                                            \
+} while (0)
 
 // For backward compatibility.
 #define assert_status(p, status, msg) vmassert_status(p, status, msg)
@@ -209,6 +215,8 @@
 void report_vm_error(const char* file, int line, const char* error_msg,
                      const char* detail_fmt, ...);
 #endif
+void report_vm_status_error(const char* file, int line, const char* error_msg,
+                            int status, const char* detail);
 void report_fatal(const char* file, int line, const char* detail_fmt, ...) ATTRIBUTE_PRINTF(3, 4);
 void report_vm_out_of_memory(const char* file, int line, size_t size, VMErrorType vm_err_type,
                              const char* detail_fmt, ...) ATTRIBUTE_PRINTF(5, 6);
--- a/hotspot/src/share/vm/utilities/exceptions.cpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/utilities/exceptions.cpp	Wed Mar 23 23:36:29 2016 +0100
@@ -52,11 +52,11 @@
 }
 
 void ThreadShadow::clear_pending_exception() {
-  if (TraceClearedExceptions) {
-    if (_pending_exception != NULL) {
-      tty->print_cr("Thread::clear_pending_exception: cleared exception:");
-      _pending_exception->print();
-    }
+  if (_pending_exception != NULL && log_is_enabled(Debug, exceptions)) {
+    ResourceMark rm;
+    outputStream* logst = LogHandle(exceptions)::debug_stream();
+    logst->print("Thread::clear_pending_exception: cleared exception:");
+    _pending_exception->print_on(logst);
   }
   _pending_exception = NULL;
   _exception_file    = NULL;
--- a/hotspot/src/share/vm/utilities/globalDefinitions.cpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/utilities/globalDefinitions.cpp	Wed Mar 23 23:36:29 2016 +0100
@@ -358,6 +358,20 @@
     return size_t(result);
 }
 
+
+// Test that nth_bit macro and friends behave as
+// expected, even with low-precedence operators.
+
+STATIC_ASSERT(nth_bit(3)   == 0x8);
+STATIC_ASSERT(nth_bit(1|2) == 0x8);
+
+STATIC_ASSERT(right_n_bits(3)   == 0x7);
+STATIC_ASSERT(right_n_bits(1|2) == 0x7);
+
+STATIC_ASSERT(left_n_bits(3)   == (intptr_t) LP64_ONLY(0xE000000000000000) NOT_LP64(0xE0000000));
+STATIC_ASSERT(left_n_bits(1|2) == (intptr_t) LP64_ONLY(0xE000000000000000) NOT_LP64(0xE0000000));
+
+
 #ifndef PRODUCT
 // For unit testing only
 class GlobalDefinitions {
--- a/hotspot/src/share/vm/utilities/globalDefinitions.hpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/utilities/globalDefinitions.hpp	Wed Mar 23 23:36:29 2016 +0100
@@ -42,6 +42,12 @@
 # include "utilities/globalDefinitions_xlc.hpp"
 #endif
 
+#ifndef NOINLINE
+#define NOINLINE
+#endif
+#ifndef ALWAYSINLINE
+#define ALWAYSINLINE inline
+#endif
 #ifndef PRAGMA_DIAG_PUSH
 #define PRAGMA_DIAG_PUSH
 #endif
@@ -1083,9 +1089,9 @@
 
 // get a word with the n.th or the right-most or left-most n bits set
 // (note: #define used only so that they can be used in enum constant definitions)
-#define nth_bit(n)        (n >= BitsPerWord ? 0 : OneBit << (n))
+#define nth_bit(n)        (((n) >= BitsPerWord) ? 0 : (OneBit << (n)))
 #define right_n_bits(n)   (nth_bit(n) - 1)
-#define left_n_bits(n)    (right_n_bits(n) << (n >= BitsPerWord ? 0 : (BitsPerWord - n)))
+#define left_n_bits(n)    (right_n_bits(n) << (((n) >= BitsPerWord) ? 0 : (BitsPerWord - (n))))
 
 // bit-operations using a mask m
 inline void   set_bits    (intptr_t& x, intptr_t m) { x |= m; }
--- a/hotspot/src/share/vm/utilities/globalDefinitions_gcc.hpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/utilities/globalDefinitions_gcc.hpp	Wed Mar 23 23:36:29 2016 +0100
@@ -322,4 +322,8 @@
 #define THREAD_LOCAL_DECL __thread
 #endif
 
+// Inlining support
+#define NOINLINE     __attribute__ ((noinline))
+#define ALWAYSINLINE __attribute__ ((always_inline))
+
 #endif // SHARE_VM_UTILITIES_GLOBALDEFINITIONS_GCC_HPP
--- a/hotspot/src/share/vm/utilities/globalDefinitions_sparcWorks.hpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/utilities/globalDefinitions_sparcWorks.hpp	Wed Mar 23 23:36:29 2016 +0100
@@ -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
@@ -277,4 +277,8 @@
 #define THREAD_LOCAL_DECL __thread
 #endif
 
+// Inlining support
+#define NOINLINE
+#define ALWAYSINLINE __attribute__((always_inline))
+
 #endif // SHARE_VM_UTILITIES_GLOBALDEFINITIONS_SPARCWORKS_HPP
--- a/hotspot/src/share/vm/utilities/globalDefinitions_visCPP.hpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/utilities/globalDefinitions_visCPP.hpp	Wed Mar 23 23:36:29 2016 +0100
@@ -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
@@ -240,4 +240,11 @@
 #define THREAD_LOCAL_DECL __declspec( thread )
 #endif
 
+// Inlining support
+// MSVC has '__declspec(noinline)' but according to the official documentation
+// it only applies to member functions. There are reports though which pretend
+// that it also works for freestanding functions.
+#define NOINLINE     __declspec(noinline)
+#define ALWAYSINLINE __forceinline
+
 #endif // SHARE_VM_UTILITIES_GLOBALDEFINITIONS_VISCPP_HPP
--- a/hotspot/src/share/vm/utilities/globalDefinitions_xlc.hpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/utilities/globalDefinitions_xlc.hpp	Wed Mar 23 23:36:29 2016 +0100
@@ -1,6 +1,6 @@
 /*
- * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2012, 2013 SAP SE. All rights reserved.
+ * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2016 SAP SE. 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
@@ -184,4 +184,8 @@
 #define THREAD_LOCAL_DECL __thread
 #endif
 
+// Inlining support
+#define NOINLINE
+#define ALWAYSINLINE __attribute__((always_inline))
+
 #endif // SHARE_VM_UTILITIES_GLOBALDEFINITIONS_XLC_HPP
--- a/hotspot/src/share/vm/utilities/internalVMTests.cpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/utilities/internalVMTests.cpp	Wed Mar 23 23:36:29 2016 +0100
@@ -69,6 +69,7 @@
   run_unit_test(JSON_test);
   run_unit_test(Test_log_length);
   run_unit_test(Test_configure_stdout);
+  run_unit_test(Test_logconfiguration_subscribe);
   run_unit_test(DirectivesParser_test);
   run_unit_test(Test_TempNewSymbol);
 #if INCLUDE_VM_STRUCTS
--- a/hotspot/src/share/vm/utilities/ostream.cpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/utilities/ostream.cpp	Wed Mar 23 23:36:29 2016 +0100
@@ -504,7 +504,7 @@
   if (_file != NULL) {
     _need_close = true;
   } else {
-    warning("Cannot open file %s due to %s\n", file_name, strerror(errno));
+    warning("Cannot open file %s due to %s\n", file_name, os::strerror(errno));
     _need_close = false;
   }
 }
@@ -514,7 +514,7 @@
   if (_file != NULL) {
     _need_close = true;
   } else {
-    warning("Cannot open file %s due to %s\n", file_name, strerror(errno));
+    warning("Cannot open file %s due to %s\n", file_name, os::strerror(errno));
     _need_close = false;
   }
 }
--- a/hotspot/src/share/vm/utilities/stack.inline.hpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/utilities/stack.inline.hpp	Wed Mar 23 23:36:29 2016 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 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,17 +27,6 @@
 
 #include "utilities/stack.hpp"
 
-// Stack is used by the GC code and in some hot paths a lot of the Stack
-// code gets inlined. This is generally good, but when too much code has
-// been inlined, no further inlining is allowed by GCC. Therefore we need
-// to prevent parts of the slow path in Stack to be inlined to allow other
-// code to be.
-#if defined(TARGET_COMPILER_gcc)
-#define NOINLINE __attribute__((noinline))
-#else
-#define NOINLINE
-#endif
-
 template <MEMFLAGS F> StackBase<F>::StackBase(size_t segment_size, size_t max_cache_size,
                      size_t max_size):
   _seg_size(segment_size),
@@ -151,6 +140,11 @@
   FREE_C_HEAP_ARRAY(char, (char*) addr);
 }
 
+// Stack is used by the GC code and in some hot paths a lot of the Stack
+// code gets inlined. This is generally good, but when too much code has
+// been inlined, no further inlining is allowed by GCC. Therefore we need
+// to prevent parts of the slow path in Stack to be inlined to allow other
+// code to be.
 template <class E, MEMFLAGS F>
 NOINLINE void Stack<E, F>::push_segment()
 {
@@ -280,6 +274,4 @@
   return _cur_seg + --_cur_seg_size;
 }
 
-#undef NOINLINE
-
 #endif // SHARE_VM_UTILITIES_STACK_INLINE_HPP
--- a/hotspot/src/share/vm/utilities/vmError.cpp	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/src/share/vm/utilities/vmError.cpp	Wed Mar 23 23:36:29 2016 +0100
@@ -1260,8 +1260,9 @@
           out.print_raw("#\n# Compiler replay data is saved as:\n# ");
           out.print_raw_cr(buffer);
         } else {
+          int e = errno;
           out.print_raw("#\n# Can't open file to dump replay data. Error: ");
-          out.print_raw_cr(strerror(os::get_last_error()));
+          out.print_raw_cr(os::strerror(e));
         }
       }
     }
@@ -1301,7 +1302,8 @@
       out.print_raw_cr("\" ...");
 
       if (os::fork_and_exec(cmd) < 0) {
-        out.print_cr("os::fork_and_exec failed: %s (%d)", strerror(errno), errno);
+        out.print_cr("os::fork_and_exec failed: %s (%s=%d)",
+                     os::strerror(errno), os::errno_name(errno), errno);
       }
     }
 
@@ -1359,7 +1361,8 @@
     tty->print_cr("\"%s\"...", cmd);
 
     if (os::fork_and_exec(cmd) < 0) {
-      tty->print_cr("os::fork_and_exec failed: %s (%d)", strerror(errno), errno);
+      tty->print_cr("os::fork_and_exec failed: %s (%s=%d)",
+                     os::strerror(errno), os::errno_name(errno), errno);
     }
   }
 }
--- a/hotspot/test/gc/arguments/TestMaxHeapSizeTools.java	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/test/gc/arguments/TestMaxHeapSizeTools.java	Wed Mar 23 23:36:29 2016 +0100
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2013, 2015, 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
@@ -112,10 +112,12 @@
   }
 
   private static void checkInvalidMinInitialHeapCombinations(String gcflag) throws Exception {
+    expectError(new String[] { gcflag, "-XX:InitialHeapSize=1023K", "-version" });
     expectError(new String[] { gcflag, "-Xms64M", "-XX:InitialHeapSize=32M", "-version" });
   }
 
   private static void checkValidMinInitialHeapCombinations(String gcflag) throws Exception {
+    expectValid(new String[] { gcflag, "-XX:InitialHeapSize=1024K", "-version" });
     expectValid(new String[] { gcflag, "-XX:InitialHeapSize=8M", "-Xms4M", "-version" });
     expectValid(new String[] { gcflag, "-Xms4M", "-XX:InitialHeapSize=8M", "-version" });
     expectValid(new String[] { gcflag, "-XX:InitialHeapSize=8M", "-Xms8M", "-version" });
@@ -124,11 +126,13 @@
   }
 
   private static void checkInvalidInitialMaxHeapCombinations(String gcflag) throws Exception {
+    expectError(new String[] { gcflag, "-XX:MaxHeapSize=2047K", "-version" });
     expectError(new String[] { gcflag, "-XX:MaxHeapSize=4M", "-XX:InitialHeapSize=8M", "-version" });
     expectError(new String[] { gcflag, "-XX:InitialHeapSize=8M", "-XX:MaxHeapSize=4M", "-version" });
   }
 
   private static void checkValidInitialMaxHeapCombinations(String gcflag) throws Exception {
+    expectValid(new String[] { gcflag, "-XX:MaxHeapSize=2048K", "-version" });
     expectValid(new String[] { gcflag, "-XX:InitialHeapSize=4M", "-XX:MaxHeapSize=8M", "-version" });
     expectValid(new String[] { gcflag, "-XX:MaxHeapSize=8M", "-XX:InitialHeapSize=4M", "-version" });
     expectValid(new String[] { gcflag, "-XX:MaxHeapSize=4M", "-XX:InitialHeapSize=4M", "-version" });
--- a/hotspot/test/gc/arguments/TestMaxMinHeapFreeRatioFlags.java	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/test/gc/arguments/TestMaxMinHeapFreeRatioFlags.java	Wed Mar 23 23:36:29 2016 +0100
@@ -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
@@ -61,11 +61,11 @@
         negativeTest(-1, false, 50, false, options);
         negativeTest(50, true, -1, true, options);
 
-        positiveTest(10, false, 90, false, options);
-        positiveTest(10, true, 80, false, options);
-        positiveTest(20, false, 70, true, options);
-        positiveTest(25, true, 65, true, options);
-        positiveTest(40, false, 50, false, options);
+        positiveTest(10, false, 90, false, true, options);
+        positiveTest(10, true, 80, false, true, options);
+        positiveTest(20, false, 70, true, true, options);
+        positiveTest(25, true, 65, true, true, options);
+        positiveTest(40, false, 50, false, true, options);
     }
 
     /**
@@ -79,7 +79,7 @@
      * @param options additional options for JVM
      */
     public static void positiveTest(int minRatio, boolean useXminf,
-            int maxRatio, boolean useXmaxf,
+            int maxRatio, boolean useXmaxf, boolean shrinkHeapInSteps,
             LinkedList<String> options) throws Exception {
 
         LinkedList<String> vmOptions = new LinkedList<>(options);
@@ -90,9 +90,11 @@
                 "-Xms" + HEAP_SIZE,
                 "-XX:NewSize=" + NEW_SIZE,
                 "-XX:MaxNewSize=" + MAX_NEW_SIZE,
+                "-XX:" + (shrinkHeapInSteps ? '+' : '-') + "ShrinkHeapInSteps",
                 RatioVerifier.class.getName(),
                 Integer.toString(minRatio),
-                Integer.toString(maxRatio)
+                Integer.toString(maxRatio),
+                Boolean.toString(shrinkHeapInSteps)
         );
 
         ProcessBuilder procBuilder = ProcessTools.createJavaProcessBuilder(vmOptions.toArray(new String[vmOptions.size()]));
@@ -151,8 +153,8 @@
         public static LinkedList<Object> garbage = new LinkedList<>();
 
         public static void main(String args[]) throws Exception {
-            if (args.length != 2) {
-                throw new IllegalArgumentException("Expected 2 args: <minRatio> <maxRatio>");
+            if (args.length != 3) {
+                throw new IllegalArgumentException("Expected 3 args: <minRatio> <maxRatio> <shrinkHeapInSteps>");
             }
             if (GCTypes.OldGCType.getOldGCType() == GCTypes.OldGCType.PSOld) {
                 System.out.println("Test is not applicable to parallel GC");
@@ -161,8 +163,10 @@
 
             double minRatio = Integer.valueOf(args[0]) / 100.0;
             double maxRatio = Integer.valueOf(args[1]) / 100.0;
+            boolean shrinkHeapInSteps = Boolean.valueOf(args[2]);
 
             long maxHeapSize = getMax();
+            int gcTries = (shrinkHeapInSteps ? GC_TRIES : 1);
 
             // commit 0.5 of total heap size to have enough space
             // to both shink and expand
@@ -170,7 +174,7 @@
                 garbage.add(new byte[ARRAY_LENGTH]);
             }
 
-            forceGC();
+            forceGC(gcTries);
             // Verify that current heap free ratio lies between specified limits
             verifyRatio(minRatio, maxRatio);
 
@@ -185,7 +189,7 @@
                 memoryToFill -= CHUNK_SIZE;
             }
 
-            forceGC();
+            forceGC(gcTries);
             // Verify that after memory allocation heap free ratio is still conforming specified limits
             verifyRatio(minRatio, maxRatio);
             // Verify that heap was actually expanded
@@ -204,7 +208,7 @@
                 memoryToFree -= CHUNK_SIZE;
             }
 
-            forceGC();
+            forceGC(gcTries);
             // Verify that heap free ratio is still conforming specified limits
             verifyRatio(minRatio, maxRatio);
             // Verify that heap was actually shrinked
@@ -214,8 +218,8 @@
 
         }
 
-        public static void forceGC() {
-            for (int i = 0; i < GC_TRIES; i++) {
+        public static void forceGC(int gcTries) {
+            for (int i = 0; i < gcTries; i++) {
                 System.gc();
                 try {
                     Thread.sleep(10);
--- a/hotspot/test/gc/arguments/TestSelectDefaultGC.java	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/test/gc/arguments/TestSelectDefaultGC.java	Wed Mar 23 23:36:29 2016 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 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,9 +27,9 @@
  * @bug 8068582
  * @key gc
  * @library /testlibrary
+ * @requires vm.gc=="null"
  * @modules java.base/sun.misc
  *          java.management
- * @ignore 8148239
  * @run driver TestSelectDefaultGC
  */
 
@@ -41,24 +41,40 @@
         output.shouldMatch(" " + option + " .*=.* " + value + " ");
     }
 
-    public static void main(String[] args) throws Exception {
+    public static void testDefaultGC(boolean actAsServer) throws Exception {
+        String[] args = new String[] {
+          "-XX:" + (actAsServer ? "+" : "-") + "AlwaysActAsServerClassMachine",
+          "-XX:" + (actAsServer ? "-" : "+") + "NeverActAsServerClassMachine",
+          "-XX:+PrintFlagsFinal",
+          "-version"
+        };
+
         // Start VM without specifying GC
-        ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-XX:+PrintFlagsFinal", "-version");
+        ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(args);
         OutputAnalyzer output = new OutputAnalyzer(pb.start());
         output.shouldHaveExitValue(0);
 
-        boolean isServerVM = Platform.isServer();
-        boolean isEmbeddedVM = Platform.isEmbedded();
+        final boolean isServer = actAsServer;
+        final boolean isEmbedded = Platform.isEmbedded();
 
         // Verify GC selection
-        // G1 is default for non-embedded server VMs
-        assertVMOption(output, "UseG1GC",            isServerVM && !isEmbeddedVM);
-        // Parallel is default for embedded server VMs
-        assertVMOption(output, "UseParallelGC",      isServerVM && isEmbeddedVM);
-        assertVMOption(output, "UseParallelOldGC",   isServerVM && isEmbeddedVM);
-        // Serial is default for non-server VMs
-        assertVMOption(output, "UseSerialGC",        !isServerVM);
+        // G1 is default for non-embedded server class machines
+        assertVMOption(output, "UseG1GC",            isServer && !isEmbedded);
+        // Parallel is default for embedded server class machines
+        assertVMOption(output, "UseParallelGC",      isServer && isEmbedded);
+        assertVMOption(output, "UseParallelOldGC",   isServer && isEmbedded);
+        // Serial is default for non-server class machines
+        assertVMOption(output, "UseSerialGC",        !isServer);
+        // CMS is never default
         assertVMOption(output, "UseConcMarkSweepGC", false);
         assertVMOption(output, "UseParNewGC",        false);
     }
+
+    public static void main(String[] args) throws Exception {
+        // Test server class machine
+        testDefaultGC(false);
+
+        // Test non-server class machine
+        testDefaultGC(true);
+    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/gc/arguments/TestShrinkHeapInSteps.java	Wed Mar 23 23:36:29 2016 +0100
@@ -0,0 +1,55 @@
+/*
+* 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.
+*/
+
+/*
+ * @test TestShrinkHeapInSteps
+ * @key gc
+ * @summary Verify that -XX:-ShrinkHeapInSteps works properly.
+ * @library /testlibrary
+ * @modules java.base/sun.misc
+ *          java.management
+ * @build TestMaxMinHeapFreeRatioFlags TestShrinkHeapInSteps
+ * @run driver/timeout=240 TestShrinkHeapInSteps
+ */
+
+import java.util.LinkedList;
+import java.util.Arrays;
+import java.util.Collections;
+import jdk.test.lib.Utils;
+
+public class TestShrinkHeapInSteps {
+    public static void main(String args[]) throws Exception {
+        LinkedList<String> options = new LinkedList<>(
+                Arrays.asList(Utils.getFilteredTestJavaOpts("-XX:[^ ]*HeapFreeRatio","-XX:\\+ExplicitGCInvokesConcurrent"))
+        );
+
+        // Leverage the existing TestMaxMinHeapFreeRatioFlags test, but pass
+        // "false" for the shrinkHeapInSteps argument. This will cause it to
+        // run with -XX:-ShrinkHeapInSteps, and only do 1 full GC instead of 10.
+        TestMaxMinHeapFreeRatioFlags.positiveTest(10, false, 90, false, false, options);
+        TestMaxMinHeapFreeRatioFlags.positiveTest(10, true, 80, false, false, options);
+        TestMaxMinHeapFreeRatioFlags.positiveTest(20, false, 70, true, false, options);
+        TestMaxMinHeapFreeRatioFlags.positiveTest(25, true, 65, true, false, options);
+        TestMaxMinHeapFreeRatioFlags.positiveTest(40, false, 50, false, false, options);
+    }
+}
--- a/hotspot/test/gc/ergonomics/TestDynamicNumberOfGCThreads.java	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/test/gc/ergonomics/TestDynamicNumberOfGCThreads.java	Wed Mar 23 23:36:29 2016 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 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
@@ -63,6 +63,14 @@
     System.arraycopy(baseArgs,  0, finalArgs, extraArgs.length, baseArgs.length);
     pb_enabled = ProcessTools.createJavaProcessBuilder(finalArgs);
     verifyDynamicNumberOfGCThreads(new OutputAnalyzer(pb_enabled.start()));
+
+    // Turn on parallel reference processing
+    String[] parRefProcArg = {"-XX:+ParallelRefProcEnabled", "-XX:-ShowMessageBoxOnError"};
+    String[] parRefArgs = new String[baseArgs.length + parRefProcArg.length];
+    System.arraycopy(parRefProcArg, 0, parRefArgs, 0,                parRefProcArg.length);
+    System.arraycopy(baseArgs,  0, parRefArgs, parRefProcArg.length, baseArgs.length);
+    pb_enabled = ProcessTools.createJavaProcessBuilder(parRefArgs);
+    verifyDynamicNumberOfGCThreads(new OutputAnalyzer(pb_enabled.start()));
   }
 
   static class GCTest {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/gc/g1/TestRegionLivenessPrint.java	Wed Mar 23 23:36:29 2016 +0100
@@ -0,0 +1,53 @@
+/*
+ * 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.
+ */
+
+/*
+ * @test TestRegionLivenessPrint.java
+ * @bug 8151920
+ * @requires vm.gc=="G1" | vm.gc=="null"
+ * @summary Make sure that G1 does not assert when printing region liveness data on a humongous continues region.
+ * @key gc
+ * @library /testlibrary /test/lib
+ * @modules java.base/sun.misc
+ * @build TestRegionLivenessPrint
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ *                              sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/othervm -Xbootclasspath/a:. -XX:+WhiteBoxAPI -XX:+UseG1GC -Xmx128M -XX:G1HeapRegionSize=1m -Xlog:gc+liveness=trace TestRegionLivenessPrint
+ */
+
+import sun.hotspot.WhiteBox;
+
+public class TestRegionLivenessPrint {
+
+  static byte[] bigobj = new byte[1024* 1024 * 2];
+
+  public static void main(String[] args) throws InterruptedException {
+      WhiteBox wb = WhiteBox.getWhiteBox();
+      // Run a concurrent mark cycle to trigger the liveness accounting log messages.
+      wb.g1StartConcMarkCycle();
+      while (wb.g1InConcurrentMark()) {
+          Thread.sleep(100);
+      }
+  }
+
+}
--- a/hotspot/test/gc/g1/TestStringSymbolTableStats.java	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/test/gc/g1/TestStringSymbolTableStats.java	Wed Mar 23 23:36:29 2016 +0100
@@ -39,7 +39,7 @@
 
     ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-XX:+UseG1GC",
                                                               "-XX:+UnlockExperimentalVMOptions",
-                                                              "-Xlog:gc+stringdedup=trace",
+                                                              "-Xlog:gc+stringtable=trace",
                                                               SystemGCTest.class.getName());
 
     OutputAnalyzer output = new OutputAnalyzer(pb.start());
--- a/hotspot/test/gc/g1/plab/TestPLABResize.java	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/test/gc/g1/plab/TestPLABResize.java	Wed Mar 23 23:36:29 2016 +0100
@@ -35,7 +35,6 @@
  *        gc.g1.plab.lib.MemoryConsumer
  *        gc.g1.plab.lib.PLABUtils
  *        gc.g1.plab.lib.AppPLABResize
- * @ignore 8150183
  * @run main ClassFileInstaller sun.hotspot.WhiteBox
  *                              sun.hotspot.WhiteBox$WhiteBoxPermission
  * @run main gc.g1.plab.TestPLABResize
@@ -122,29 +121,23 @@
                 .collect(Collectors.toCollection(ArrayList::new));
 
         // Check that desired plab size was changed during iterations.
-        // It should decrease during first half of iterations
-        // and increase after.
-        List<Long> decreasedPlabs = plabSizes.subList(testCase.getIterations(), testCase.getIterations() * 2);
-        List<Long> increasedPlabs = plabSizes.subList(testCase.getIterations() * 2, testCase.getIterations() * 3);
+        // The test case does 3 rounds of allocations.  The second round of N allocations and GC's
+        // has a decreasing size of allocations so that iterations N to 2*N -1 will be of decreasing size.
+        // The third round with iterations 2*N to 3*N -1 has increasing sizes of allocation.
+        long startDesiredPLABSize = plabSizes.get(testCase.getIterations());
+        long endDesiredPLABSize = plabSizes.get(testCase.getIterations() * 2 - 1);
 
-        Long prev = decreasedPlabs.get(0);
-        for (int index = 1; index < decreasedPlabs.size(); ++index) {
-            Long current = decreasedPlabs.get(index);
-            if (prev < current) {
-                System.out.println(output);
-                throw new RuntimeException("Test failed! Expect that previous PLAB size should be greater than current. Prev.size: " + prev + " Current size:" + current);
-            }
-            prev = current;
+        if (startDesiredPLABSize < endDesiredPLABSize) {
+            System.out.println(output);
+            throw new RuntimeException("Test failed! Expect that initial PLAB size should be greater than checked. Initial size: " + startDesiredPLABSize + " Checked size:" + endDesiredPLABSize);
         }
 
-        prev = increasedPlabs.get(0);
-        for (int index = 1; index < increasedPlabs.size(); ++index) {
-            Long current = increasedPlabs.get(index);
-            if (prev > current) {
-                System.out.println(output);
-                throw new RuntimeException("Test failed! Expect that previous PLAB size should be less than current. Prev.size: " + prev + " Current size:" + current);
-            }
-            prev = current;
+        startDesiredPLABSize = plabSizes.get(testCase.getIterations() * 2);
+        endDesiredPLABSize = plabSizes.get(testCase.getIterations() * 3 - 1);
+
+        if (startDesiredPLABSize > endDesiredPLABSize) {
+            System.out.println(output);
+            throw new RuntimeException("Test failed! Expect that initial PLAB size should be less than checked. Initial size: " + startDesiredPLABSize + " Checked size:" + endDesiredPLABSize);
         }
 
         System.out.println("Test passed!");
@@ -195,7 +188,6 @@
             return Arrays.asList("-XX:ParallelGCThreads=" + parGCThreads,
                     "-XX:ParallelGCBufferWastePct=" + wastePct,
                     "-XX:+ResizePLAB",
-                    "-Dthreads=" + parGCThreads,
                     "-Dchunk.size=" + chunkSize,
                     "-Diterations=" + iterations,
                     "-XX:NewSize=16m",
--- a/hotspot/test/gc/g1/plab/lib/AppPLABResize.java	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/test/gc/g1/plab/lib/AppPLABResize.java	Wed Mar 23 23:36:29 2016 +0100
@@ -38,7 +38,6 @@
  * Expects the following properties to be set:
  * - iterations - amount of iteration per cycle.
  * - chunk.size - size of objects to be allocated
- * - threads - number of gc threads (-XX:ParallelGCThreads) to calculate PLAB sizes.
  */
 final public class AppPLABResize {
 
@@ -47,7 +46,6 @@
     // Defined by properties.
     private static final int ITERATIONS = Integer.getInteger("iterations");
     private static final long CHUNK = Long.getLong("chunk.size");
-    private static final int GC_THREADS = Integer.getInteger("threads");
 
     private static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox();
 
@@ -59,13 +57,13 @@
      */
     public static void main(String[] args) {
 
-        if (ITERATIONS == 0 || CHUNK == 0 || GC_THREADS == 0) {
+        if (ITERATIONS == 0 || CHUNK == 0) {
             throw new IllegalArgumentException("Properties should be set");
         }
 
         long wordSize = Platform.is32bit() ? 4l : 8l;
         // PLAB size is shared between threads.
-        long initialMemorySize = wordSize * GC_THREADS * MEM_ALLOC_WORDS;
+        long initialMemorySize = wordSize * MEM_ALLOC_WORDS;
 
         // Expect changing memory to half during all iterations.
         long memChangeStep = initialMemorySize / 2 / ITERATIONS;
--- a/hotspot/test/gc/g1/plab/lib/LogParser.java	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/test/gc/g1/plab/lib/LogParser.java	Wed Mar 23 23:36:29 2016 +0100
@@ -57,7 +57,8 @@
 
     private final String log;
 
-    private final Map<Long, Map<ReportType, Map<String,Long>>> reportHolder;
+    // Contains Map of PLAB statistics for given log.
+    private final Map<Long, Map<ReportType, Map<String, Long>>> report;
 
     // GC ID
     private static final Pattern GC_ID_PATTERN = Pattern.compile("\\[gc,plab\\s*\\] GC\\((\\d+)\\)");
@@ -65,7 +66,7 @@
     private static final Pattern PAIRS_PATTERN = Pattern.compile("\\w* \\w+:\\s+\\d+");
 
     /**
-     * Construct LogParser Object
+     * Construct LogParser object, parse log file with PLAB statistics and store it into report.
      *
      * @param log - VM Output
      */
@@ -74,43 +75,44 @@
             throw new IllegalArgumentException("Parameter log should not be null.");
         }
         this.log = log;
-        reportHolder = parseLines();
+        report = parseLines();
     }
 
     /**
-     * @return log which is being processed
+     * @return log which was processed
      */
     public String getLog() {
         return log;
     }
 
     /**
-     * Returns list of log entries.
+     * Returns the GC log entries for Survivor and Old stats.
+     * The entries are represented as a map of gcID to the StatMap.
      *
-     * @return list of Pair with ReportType and Map of parameters/values.
+     * @return The log entries for the Survivor and Old stats.
      */
-    public Map<Long,Map<ReportType, Map<String,Long>>> getEntries() {
-        return reportHolder;
+    public Map<Long, Map<ReportType, Map<String, Long>>> getEntries() {
+        return report;
     }
 
-    private Map<Long,Map<ReportType, Map<String,Long>>> parseLines() throws NumberFormatException {
+    private Map<Long, Map<ReportType, Map<String, Long>>> parseLines() throws NumberFormatException {
         Scanner lineScanner = new Scanner(log);
-        Map<Long,Map<ReportType, Map<String,Long>>> allocationStatistics = new HashMap<>();
+        Map<Long, Map<ReportType, Map<String, Long>>> allocationStatistics = new HashMap<>();
         Optional<Long> gc_id;
         while (lineScanner.hasNextLine()) {
             String line = lineScanner.nextLine();
             gc_id = getGcId(line);
-            if ( gc_id.isPresent() ) {
+            if (gc_id.isPresent()) {
                 Matcher matcher = PAIRS_PATTERN.matcher(line);
                 if (matcher.find()) {
-                    Map<ReportType,Map<String, Long>> oneReportItem;
+                    Map<ReportType, Map<String, Long>> oneReportItem;
                     ReportType reportType;
 
                     if (!allocationStatistics.containsKey(gc_id.get())) {
-                      allocationStatistics.put(gc_id.get(), new EnumMap<>(ReportType.class));
+                        allocationStatistics.put(gc_id.get(), new EnumMap<>(ReportType.class));
                     }
 
-                    if ( line.contains("Young") ) {
+                    if (line.contains("Young")) {
                         reportType = ReportType.SURVIVOR_STATS;
                     } else {
                         reportType = ReportType.OLD_STATS;
@@ -118,7 +120,7 @@
 
                     oneReportItem = allocationStatistics.get(gc_id.get());
                     if (!oneReportItem.containsKey(reportType)) {
-                      oneReportItem.put(reportType,new HashMap<String, Long>());
+                        oneReportItem.put(reportType, new HashMap<>());
                     }
 
                     // Extract all pairs from log.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/Throwable/StackTraceLogging.java	Wed Mar 23 23:36:29 2016 +0100
@@ -0,0 +1,64 @@
+/*
+ * 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.
+ */
+
+/*
+ * @test
+ * @bug 8150778
+ * @summary check stacktrace logging
+ * @library /testlibrary
+ * @modules java.base/sun.misc
+ *          java.management
+ * @build jdk.test.lib.OutputAnalyzer jdk.test.lib.ProcessTools
+ * @compile TestThrowable.java
+ * @run driver StackTraceLogging
+ */
+
+import java.io.File;
+import java.util.Map;
+import jdk.test.lib.OutputAnalyzer;
+import jdk.test.lib.ProcessTools;
+
+public class StackTraceLogging {
+    static void updateEnvironment(ProcessBuilder pb, String environmentVariable, String value) {
+        Map<String, String> env = pb.environment();
+        env.put(environmentVariable, value);
+    }
+
+    static void analyzeOutputOn(ProcessBuilder pb) throws Exception {
+        OutputAnalyzer output = new OutputAnalyzer(pb.start());
+        // These depths match the ones in TestThrowable.java
+        int[] depths = {10, 34, 100, 1024};
+        for (int d : depths) {
+            output.shouldContain("java.lang.RuntimeException, " + d);
+        }
+        output.shouldHaveExitValue(0);
+    }
+
+
+    public static void main(String[] args) throws Exception {
+        ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-Xlog:stacktrace=info",
+                                                                  "-XX:MaxJavaStackTraceDepth=1024",
+                                                                  "TestThrowable");
+        analyzeOutputOn(pb);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/Throwable/TestThrowable.java	Wed Mar 23 23:36:29 2016 +0100
@@ -0,0 +1,78 @@
+/*
+ * 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.
+ */
+
+/*
+ * @test
+ * @bug 8150778
+ * @summary Test exception depths, and code to get stack traces
+ * @library /testlibrary
+ * @run main/othervm -XX:MaxJavaStackTraceDepth=1024 TestThrowable
+ */
+
+import java.lang.reflect.Field;
+import jdk.test.lib.Asserts;
+
+public class TestThrowable {
+
+  // Inner class that throws a lot of exceptions
+  static class Thrower {
+    static int MaxJavaStackTraceDepth = 1024; // as above
+    int[] depths = {10, 34, 100, 1024, 2042};
+    int count = 0;
+
+    int getDepth(Throwable t) throws Exception {
+      Field f = Throwable.class.getDeclaredField("depth");
+      f.setAccessible(true); // it's private
+      return f.getInt(t);
+    }
+
+    void callThrow(int depth) {
+      if (++count < depth) {
+        callThrow(depth);
+      } else {
+        throw new RuntimeException("depth tested " + depth);
+      }
+    }
+    void testThrow() throws Exception {
+      for (int d : depths) {
+        try {
+          count = getDepth(new Throwable());
+          callThrow(d);
+        } catch(Exception e) {
+          e.getStackTrace();
+          System.out.println(e.getMessage());
+          int throwableDepth = getDepth(e);
+          Asserts.assertTrue(throwableDepth == d ||
+                     (d > MaxJavaStackTraceDepth && throwableDepth == MaxJavaStackTraceDepth),
+                     "depth should return the correct value: depth tested=" +
+                     d + " throwableDepth=" + throwableDepth);
+        }
+      }
+    }
+  }
+
+  public static void main(String... unused) throws Exception {
+    Thrower t = new Thrower();
+    t.testThrow();
+  }
+}
--- a/hotspot/test/runtime/logging/ClassInitializationTest.java	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/test/runtime/logging/ClassInitializationTest.java	Wed Mar 23 23:36:29 2016 +0100
@@ -62,16 +62,6 @@
             out.shouldContain("[Initialized").shouldContain("without side effects]");
             out.shouldHaveExitValue(0);
         }
-        // (3) Ensure that VerboseVerification still triggers appropriate messages.
-        pb = ProcessTools.createJavaProcessBuilder("-XX:+UnlockDiagnosticVMOptions",
-                                                   "-XX:+VerboseVerification",
-                                                   "-Xverify:all",
-                                                   "-Xmx64m",
-                                                   "BadMap50");
-        out = new OutputAnalyzer(pb.start());
-        out.shouldContain("End class verification for:");
-        out.shouldContain("Verification for BadMap50 failed");
-        out.shouldContain("Fail over class verification to old verifier for: BadMap50");
     }
     public static class InnerClass {
         public static void main(String[] args) throws Exception {
--- a/hotspot/test/runtime/logging/ClassResolutionTest.java	Tue Mar 22 18:41:09 2016 -0700
+++ b/hotspot/test/runtime/logging/ClassResolutionTest.java	Wed Mar 23 23:36:29 2016 +0100
@@ -58,13 +58,13 @@
     public static void main(String... args) throws Exception {
 
         // (1) classresolve should turn on.
-        ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-Xlog:classresolve=info",
+        ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-Xlog:classresolve=debug",
                                                                   ClassResolutionTestMain.class.getName());
         OutputAnalyzer o = new OutputAnalyzer(pb.start());
         o.shouldContain("[classresolve] ClassResolutionTest$ClassResolutionTestMain$Thing1Handler ClassResolutionTest$ClassResolutionTestMain$Thing1");
 
         // (2) classresolve should turn off.
-        pb = ProcessTools.createJavaProcessBuilder("-Xlog",
+        pb = ProcessTools.createJavaProcessBuilder("-Xlog:classresolve=debug",
                                                    "-Xlog:classresolve=off",
                                                    ClassResolutionTestMain.class.getName());
         o = new OutputAnalyzer(pb.start());
@@ -77,12 +77,12 @@
         o.shouldContain("[classresolve] ClassResolutionTest$ClassResolutionTestMain$Thing1Handler ClassResolutionTest$ClassResolutionTestMain$Thing1");
 
         // (4) TraceClassResolution should turn off.
-        pb = ProcessTools.createJavaProcessBuilder("-Xlog",
+        pb = ProcessTools.createJavaProcessBuilder("-Xlog:classresolve=debug",
                                                    "-XX:-TraceClassResolution",
                                                    ClassResolutionTestMain.class.getName());
         o = new OutputAnalyzer(pb.start());
         o.shouldNotContain("[classresolve]");
 
+    };
 
-    };
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/logging/RemovedDevelopFlagsTest.java	Wed Mar 23 23:36:29 2016 +0100
@@ -0,0 +1,63 @@
+/*
+ * 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.
+ */
+
+
+/*
+ * @test RemovedDevelopFlagsTest
+ * @bug 8146632
+ * @library /testlibrary
+ * @build jdk.test.lib.OutputAnalyzer jdk.test.lib.ProcessTools
+ * @run driver RemovedDevelopFlagsTest
+ */
+import jdk.test.lib.*;
+
+public class RemovedDevelopFlagsTest {
+    public static ProcessBuilder pb;
+
+    public static class RemovedDevelopFlagsTestMain {
+        public static void main(String... args) {
+            System.out.print("Hello!");
+        }
+    }
+
+    public static void exec(String flag, String value) throws Exception {
+        pb = ProcessTools.createJavaProcessBuilder("-XX:+"+flag, RemovedDevelopFlagsTestMain.class.getName());
+        OutputAnalyzer o = new OutputAnalyzer(pb.start());
+        o.shouldContain(flag+" has been removed. Please use "+value+" instead.");
+        o.shouldHaveExitValue(1);
+    }
+
+    public static void main(String... args) throws Exception {
+        if (Platform.isDebugBuild()){
+            exec("TraceClassInitialization", "-Xlog:classinit");
+            exec("TraceClassLoaderData", "-Xlog:classloaderdata");
+            exec("TraceDefaultMethods", "-Xlog:defaultmethods=debug");
+            exec("TraceItables", "-Xlog:itables=debug");
+            exec("TraceSafepoint", "-Xlog:safepoint=debug");
+            exec("TraceStartupTime", "-Xlog:startuptime");
+            exec("TraceVMOperation", "-Xlog:vmoperation=debug");
+            exec("PrintVtables", "-Xlog:vtables=debug");
+            exec("VerboseVerification", "-Xlog:verboseverification");
+        }
+    };
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/logging/SafepointCleanupTest.java	Wed Mar 23 23:36:29 2016 +0100
@@ -0,0 +1,79 @@
+/*
+ * 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.
+ */
+
+/*
+ * @test
+ * @bug 8149991
+ * @summary safepointcleanup=info should have output from the code
+ * @library /testlibrary
+ * @modules java.base/sun.misc
+ *          java.management
+ * @build jdk.test.lib.OutputAnalyzer jdk.test.lib.ProcessTools
+ * @run driver SafepointCleanupTest
+ */
+
+import jdk.test.lib.OutputAnalyzer;
+import jdk.test.lib.ProcessTools;
+
+public class SafepointCleanupTest {
+    static void analyzeOutputOn(ProcessBuilder pb) throws Exception {
+        OutputAnalyzer output = new OutputAnalyzer(pb.start());
+        output.shouldContain("[safepointcleanup]");
+        output.shouldContain("deflating idle monitors");
+        output.shouldContain("updating inline caches");
+        output.shouldContain("compilation policy safepoint handler");
+        output.shouldContain("mark nmethods");
+        output.shouldContain("purging class loader data graph");
+        output.shouldHaveExitValue(0);
+    }
+
+    static void analyzeOutputOff(ProcessBuilder pb) throws Exception {
+        OutputAnalyzer output = new OutputAnalyzer(pb.start());
+        output.shouldNotContain("[safepointcleanup]");
+        output.shouldHaveExitValue(0);
+    }
+
+    public static void main(String[] args) throws Exception {
+        ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-Xlog:safepointcleanup=info",
+                                                                  InnerClass.class.getName());
+        analyzeOutputOn(pb);
+
+        pb = ProcessTools.createJavaProcessBuilder("-XX:+TraceSafepointCleanupTime",
+                                                   InnerClass.class.getName());
+        analyzeOutputOn(pb);
+
+        pb = ProcessTools.createJavaProcessBuilder("-Xlog:safepointcleanup=off",
+                                                   InnerClass.class.getName());
+        analyzeOutputOff(pb);
+
+        pb = ProcessTools.createJavaProcessBuilder("-XX:-TraceSafepointCleanupTime",
+                                                   InnerClass.class.getName());
+        analyzeOutputOff(pb);
+    }
+
+    public static class InnerClass {
+        public static void main(String[] args) throws Exception {
+            System.out.println("Safepoint Cleanup test");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/logging/VerboseVerificationTest.java	Wed Mar 23 23:36:29 2016 +0100
@@ -0,0 +1,69 @@
+/*
+ * 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.
+ */
+
+/*
+ * @test
+ * @bug 8150083
+ * @summary verboseverification=info output should have output from the code
+ * @library /testlibrary
+ * @modules java.base/sun.misc
+ *          java.management
+ * @build jdk.test.lib.OutputAnalyzer jdk.test.lib.ProcessTools
+ * @run driver VerboseVerificationTest
+ */
+
+import jdk.test.lib.OutputAnalyzer;
+import jdk.test.lib.ProcessTools;
+
+public class VerboseVerificationTest {
+    static void analyzeOutputOn(ProcessBuilder pb) throws Exception {
+        OutputAnalyzer output = new OutputAnalyzer(pb.start());
+        output.shouldContain("[verboseverification]");
+        output.shouldContain("Verifying class VerboseVerificationTest$InternalClass with new format");
+        output.shouldContain("Verifying method VerboseVerificationTest$InternalClass.<init>()V");
+        output.shouldContain("End class verification for: VerboseVerificationTest$InternalClass");
+        output.shouldHaveExitValue(0);
+    }
+
+    static void analyzeOutputOff(ProcessBuilder pb) throws Exception {
+        OutputAnalyzer output = new OutputAnalyzer(pb.start());
+        output.shouldNotContain("[verboseverification]");
+        output.shouldHaveExitValue(0);
+    }
+
+    public static void main(String[] args) throws Exception {
+        ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-Xlog:verboseverification=info",
+                                                                  InternalClass.class.getName());
+        analyzeOutputOn(pb);
+
+        pb = ProcessTools.createJavaProcessBuilder("-Xlog:verboseverification=off",
+                                                   InternalClass.class.getName());
+        analyzeOutputOff(pb);
+    }
+
+    public static class InternalClass {
+        public static void main(String[] args) throws Exception {
+            System.out.println("VerboseVerificationTest");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/stress/gc/TestMultiThreadStressRSet.java	Wed Mar 23 23:36:29 2016 +0100
@@ -0,0 +1,305 @@
+/*
+ * 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.
+ */
+
+import java.io.PrintStream;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Random;
+import sun.hotspot.WhiteBox;
+
+/*
+ * @test TestMultiThreadStressRSet.java
+ * @key stress
+ * @requires vm.gc=="G1" | vm.gc=="null"
+ * @requires os.maxMemory > 2G
+ *
+ * @summary Stress G1 Remembered Set using multiple threads
+ * @library /test/lib /testlibrary
+ * @build sun.hotspot.WhiteBox
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ *                              sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
+ *   -XX:+UseG1GC -XX:G1SummarizeRSetStatsPeriod=1 -Xlog:gc
+ *   -Xmx500m -XX:G1HeapRegionSize=1m -XX:MaxGCPauseMillis=1000 TestMultiThreadStressRSet 10 4
+ *
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
+ *   -XX:+UseG1GC -XX:G1SummarizeRSetStatsPeriod=100 -Xlog:gc
+ *   -Xmx1G -XX:G1HeapRegionSize=8m -XX:MaxGCPauseMillis=1000 TestMultiThreadStressRSet 60 16
+ *
+ * @run main/othervm/timeout=700 -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
+ *   -XX:+UseG1GC -XX:G1SummarizeRSetStatsPeriod=100 -Xlog:gc
+ *   -Xmx500m -XX:G1HeapRegionSize=1m -XX:MaxGCPauseMillis=1000 TestMultiThreadStressRSet 600 32
+ */
+public class TestMultiThreadStressRSet {
+
+    private static final Random RND = new Random(2015 * 2016);
+    private static final WhiteBox WB = WhiteBox.getWhiteBox();
+    private static final int REF_SIZE = WB.getHeapOopSize();
+    private static final int REGION_SIZE = WB.g1RegionSize();
+
+    // How many regions to use for the storage
+    private static final int STORAGE_REGIONS = 20;
+
+    // Size a single obj in the storage
+    private static final int OBJ_SIZE = 1024;
+
+    // How many regions of young/old gen to use in the BUFFER
+    private static final int BUFFER_YOUNG_REGIONS = 60;
+    private static final int BUFFER_OLD_REGIONS = 40;
+
+    // Total number of objects in the storage.
+    private final int N;
+
+    // The storage of byte[]
+    private final List<Object> STORAGE;
+
+    // Where references to the Storage will be stored
+    private final List<Object[]> BUFFER;
+
+    // The length of a buffer element.
+    // RSet deals with "cards" (areas of 512 bytes), not with single refs
+    // So, to affect the RSet the BUFFER refs should be allocated in different
+    // memory cards.
+    private final int BUF_ARR_LEN = 100 * (512 / REF_SIZE);
+
+    // Total number of objects in the young/old buffers
+    private final int YOUNG;
+    private final int OLD;
+
+    // To cause Remembered Sets change their coarse level the test uses a window
+    // within STORAGE. All the BUFFER elements refer to only STORAGE objects
+    // from the current window. The window is defined by a range.
+    // The first element has got the index: 'windowStart',
+    // the last one: 'windowStart + windowSize - 1'
+    // The window is shifting periodically.
+    private int windowStart;
+    private final int windowSize;
+
+    // Counter of created worker threads
+    private int counter = 0;
+
+    private volatile String errorMessage = null;
+    private volatile boolean isEnough = false;
+
+    public static void main(String args[]) {
+        if (args.length != 2) {
+            throw new IllegalArgumentException("TEST BUG: wrong arg count " + args.length);
+        }
+        long time = Long.parseLong(args[0]);
+        int threads = Integer.parseInt(args[1]);
+        new TestMultiThreadStressRSet().test(time * 1000, threads);
+    }
+
+    /**
+     * Initiates test parameters, fills out the STORAGE and BUFFER.
+     */
+    public TestMultiThreadStressRSet() {
+
+        N = (REGION_SIZE - 1) * STORAGE_REGIONS / OBJ_SIZE + 1;
+        STORAGE = new ArrayList<>(N);
+        int bytes = OBJ_SIZE - 20;
+        for (int i = 0; i < N - 1; i++) {
+            STORAGE.add(new byte[bytes]);
+        }
+        STORAGE.add(new byte[REGION_SIZE / 2 + 100]); // humongous
+        windowStart = 0;
+        windowSize = REGION_SIZE / OBJ_SIZE;
+
+        BUFFER = new ArrayList<>();
+        int sizeOfBufferObject = 20 + REF_SIZE * BUF_ARR_LEN;
+        OLD = REGION_SIZE * BUFFER_OLD_REGIONS / sizeOfBufferObject;
+        YOUNG = REGION_SIZE * BUFFER_YOUNG_REGIONS / sizeOfBufferObject;
+        for (int i = 0; i < OLD + YOUNG; i++) {
+            BUFFER.add(new Object[BUF_ARR_LEN]);
+        }
+    }
+
+    /**
+     * Does the testing. Steps:
+     * <ul>
+     * <li> starts the Shifter thread
+     * <li> during the given time starts new Worker threads, keeping the number
+     * of live thread under limit.
+     * <li> stops the Shifter thread
+     * </ul>
+     *
+     * @param timeInMillis how long to stress
+     * @param maxThreads the maximum number of Worker thread working together.
+     */
+    public void test(long timeInMillis, int maxThreads) {
+        if (timeInMillis <= 0 || maxThreads <= 0) {
+            throw new IllegalArgumentException("TEST BUG: be positive!");
+        }
+        System.out.println("%% Time to work: " + timeInMillis / 1000 + "s");
+        System.out.println("%% Number of threads: " + maxThreads);
+        long finish = System.currentTimeMillis() + timeInMillis;
+        Shifter shift = new Shifter(this, 1000, (int) (windowSize * 0.9));
+        shift.start();
+        for (int i = 0; i < maxThreads; i++) {
+            new Worker(this, 100).start();
+        }
+        try {
+            while (System.currentTimeMillis() < finish && errorMessage == null) {
+                Thread.sleep(100);
+            }
+        } catch (Throwable t) {
+            printAllStackTraces(System.err);
+            t.printStackTrace(System.err);
+            this.errorMessage = t.getMessage();
+        } finally {
+            isEnough = true;
+        }
+        System.out.println("%% Total work cycles: " + counter);
+        if (errorMessage != null) {
+            throw new RuntimeException(errorMessage);
+        }
+    }
+
+    /**
+     * Returns an element from from the BUFFER (an object array) to keep
+     * references to the storage.
+     *
+     * @return an Object[] from buffer.
+     */
+    private Object[] getFromBuffer() {
+        int index = counter % (OLD + YOUNG);
+        synchronized (BUFFER) {
+            if (index < OLD) {
+                if (counter % 100 == (counter / 100) % 100) {
+                    // need to generate garbage in the old gen to provoke mixed GC
+                    return replaceInBuffer(index);
+                } else {
+                    return BUFFER.get(index);
+                }
+            } else {
+                return replaceInBuffer(index);
+            }
+        }
+    }
+
+    private Object[] replaceInBuffer(int index) {
+        Object[] objs = new Object[BUF_ARR_LEN];
+        BUFFER.set(index, objs);
+        return objs;
+    }
+
+    /**
+     * Returns a random object from the current window within the storage.
+     * A storage element with index from windowStart to windowStart+windowSize.
+     *
+     * @return a random element from the current window within the storage.
+     */
+    private Object getRandomObject() {
+        int index = (windowStart + RND.nextInt(windowSize)) % N;
+        return STORAGE.get(index);
+    }
+
+    private static void printAllStackTraces(PrintStream ps) {
+        Map<Thread, StackTraceElement[]> traces = Thread.getAllStackTraces();
+        for (Thread t : traces.keySet()) {
+            ps.println(t.toString() + " " + t.getState());
+            for (StackTraceElement traceElement : traces.get(t)) {
+                ps.println("\tat " + traceElement);
+            }
+        }
+    }
+
+    /**
+     * Thread to create a number of references from BUFFER to STORAGE.
+     */
+    private static class Worker extends Thread {
+
+        final TestMultiThreadStressRSet boss;
+        final int refs; // number of refs to OldGen
+
+        /**
+         * @param boss the tests
+         * @param refsToOldGen how many references to the OldGen to create
+         */
+        Worker(TestMultiThreadStressRSet boss, int refsToOldGen) {
+            this.boss = boss;
+            this.refs = refsToOldGen;
+        }
+
+        @Override
+        public void run() {
+            try {
+                while (!boss.isEnough) {
+                    Object[] objs = boss.getFromBuffer();
+                    int step = objs.length / refs;
+                    for (int i = 0; i < refs; i += step) {
+                        objs[i] = boss.getRandomObject();
+                    }
+                    boss.counter++;
+                }
+            } catch (Throwable t) {
+                t.printStackTrace(System.out);
+                boss.errorMessage = t.getMessage();
+            }
+        }
+    }
+
+    /**
+     * Periodically shifts the current STORAGE window, removing references
+     * in BUFFER that refer to objects outside the window.
+     */
+    private static class Shifter extends Thread {
+
+        final TestMultiThreadStressRSet boss;
+        final int sleepTime;
+        final int shift;
+
+        Shifter(TestMultiThreadStressRSet boss, int sleepTime, int shift) {
+            this.boss = boss;
+            this.sleepTime = sleepTime;
+            this.shift = shift;
+        }
+
+        @Override
+        public void run() {
+            try {
+                while (!boss.isEnough) {
+                    Thread.sleep(sleepTime);
+                    boss.windowStart += shift;
+                    for (int i = 0; i < boss.OLD; i++) {
+                        Object[] objs = boss.BUFFER.get(i);
+                        for (int j = 0; j < objs.length; j++) {
+                            objs[j] = null;
+                        }
+                    }
+                    if (!WB.g1InConcurrentMark()) {
+                        System.out.println("%% start CMC");
+                        WB.g1StartConcMarkCycle();
+                    } else {
+                        System.out.println("%% CMC is already in progress");
+                    }
+                }
+            } catch (Throwable t) {
+                t.printStackTrace(System.out);
+                boss.errorMessage = t.getMessage();
+            }
+        }
+    }
+}
+