Merge
authorjwilhelm
Sat, 02 Apr 2016 05:39:25 +0200
changeset 37237 7e5787f48bae
parent 36814 2c9a2b0e5c07 (current diff)
parent 37236 0d74be24a3b1 (diff)
child 37238 3d0a96116bff
child 37239 a6cda2376a19
child 37241 b9961c99c356
Merge
hotspot/src/share/vm/ci/ciReplay.cpp
hotspot/src/share/vm/classfile/classLoader.cpp
hotspot/src/share/vm/compiler/compileBroker.cpp
hotspot/src/share/vm/jvmci/jvmciCompilerToVM.cpp
hotspot/src/share/vm/runtime/arguments.cpp
hotspot/src/share/vm/runtime/logTimer.hpp
--- a/hotspot/make/aix/adlc_updater	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/make/aix/adlc_updater	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/make/aix/makefiles/trace.make	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/make/bsd/adlc_updater	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/make/bsd/makefiles/trace.make	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/make/linux/adlc_updater	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/make/linux/makefiles/trace.make	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/make/share/makefiles/mapfile-vers	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/make/solaris/adlc_updater	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/make/solaris/makefiles/trace.make	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/make/windows/build.make	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/make/windows/create_obj_files.sh	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/make/windows/makefiles/defs.make	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/make/windows/makefiles/trace.make	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/make/windows/makefiles/vm.make	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/cpu/aarch64/vm/templateInterpreterGenerator_aarch64.cpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/cpu/ppc/vm/templateInterpreterGenerator_ppc.cpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/cpu/sparc/vm/templateInterpreterGenerator_sparc.cpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/cpu/x86/vm/frame_x86.hpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/cpu/x86/vm/interp_masm_x86.cpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/cpu/x86/vm/templateInterpreterGenerator_x86.cpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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/CommandProcessor.java	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/CommandProcessor.java	Sat Apr 02 05:39:25 2016 +0200
@@ -549,11 +549,9 @@
         },
         new Command("buildreplayjars", "buildreplayjars [ all | app | boot ]  | [ prefix ]", false) {
             // This is used to dump jar files of all the classes
-            // loaded in the core.  Everything on the bootclasspath
+            // loaded in the core.  Everything with null classloader
             // will go in boot.jar and everything else will go in
-            // app.jar.  Then the classes can be loaded by the replay
-            // jvm using -Xbootclasspath/p:boot.jar -cp app.jar. boot.jar usually
-            // not needed, unless changed by jvmti.
+            // app.jar. boot.jar usually not needed, unless changed by jvmti.
             public void doit(Tokens t) {
                 int tcount = t.countTokens();
                 if (tcount > 2) {
--- a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/SAGetopt.java	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/SAGetopt.java	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/SALauncher.java	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/shared/GCCause.java	Sat Apr 02 05:39:25 2016 +0200
@@ -35,6 +35,11 @@
   _gc_locker ("GCLocker Initiated GC"),
   _heap_inspection ("Heap Inspection Initiated GC"),
   _heap_dump ("Heap Dump Initiated GC"),
+  _wb_young_gc ("WhiteBox Initiated Young GC"),
+  _wb_conc_mark ("WhiteBox Initiated Concurrent Mark"),
+  _wb_full_gc ("WhiteBox Initiated Full GC"),
+  _update_allocation_context_stats_inc ("Update Allocation Context Stats"),
+  _update_allocation_context_stats_full ("Update Allocation Context Stats"),
 
   _no_gc ("No GC"),
   _no_cause_specified ("Unknown GCCause"),
@@ -42,6 +47,7 @@
 
   _tenured_generation_full ("Tenured Generation Full"),
   _metadata_GC_threshold ("Metadata GC Threshold"),
+  _metadata_GC_clear_soft_refs ("Metadata GC Clear Soft References"),
 
   _cms_generation_full ("CMS Generation Full"),
   _cms_initial_mark ("CMS Initial Mark"),
@@ -55,7 +61,8 @@
   _g1_inc_collection_pause ("G1 Evacuation Pause"),
   _g1_humongous_allocation ("G1 Humongous Allocation"),
 
-  _last_ditch_collection ("Last ditch collection"),
+  _dcmd_gc_run ("Diagnostic Command"),
+
   _last_gc_cause ("ILLEGAL VALUE - last gc cause - ILLEGAL VALUE");
 
   private final String value;
--- a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/jdi/VirtualMachineImpl.java	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/jdi/VirtualMachineImpl.java	Sat Apr 02 05:39:25 2016 +0200
@@ -780,8 +780,8 @@
         return getPath("java.class.path");
     }
 
-    public List bootClassPath() {
-        return getPath("sun.boot.class.path");
+    public List<String> bootClassPath() {
+        return Collections.emptyList();
     }
 
     public String baseDirectory() {
--- a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/Threads.java	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/Threads.java	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/JSnap.java	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/CompactHashTable.java	Sat Apr 02 05:39:25 2016 +0200
@@ -81,6 +81,12 @@
   }
 
   public Symbol probe(byte[] name, long hash) {
+
+    if (bucketCount() == 0) {
+      // The table is invalid, so don't try to lookup
+      return null;
+    }
+
     long    symOffset;
     Symbol  sym;
     Address baseAddress = baseAddressField.getValue(addr);
--- a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/soql/JSJavaVM.java	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/soql/JSJavaVM.java	Sat Apr 02 05:39:25 2016 +0200
@@ -75,8 +75,6 @@
             return vm.getVMRelease();
         case FIELD_CLASS_PATH:
             return getClassPath();
-        case FIELD_BOOT_CLASS_PATH:
-            return getBootClassPath();
         case FIELD_USER_DIR:
             return getUserDir();
         case FIELD_UNDEFINED:
@@ -143,7 +141,6 @@
         addField("type", FIELD_TYPE);
         addField("version", FIELD_VERSION);
         addField("classPath", FIELD_CLASS_PATH);
-        addField("bootClassPath", FIELD_BOOT_CLASS_PATH);
         addField("userDir", FIELD_USER_DIR);
     }
 
@@ -217,10 +214,6 @@
         return vm.getSystemProperty("java.class.path");
     }
 
-    private String getBootClassPath() {
-        return vm.getSystemProperty("sun.boot.class.path");
-    }
-
     private String getUserDir() {
         return vm.getSystemProperty("user.dir");
     }
--- a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/soql/sa.js	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/soql/sa.js	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/os/aix/vm/os_aix.cpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/os/aix/vm/perfMemory_aix.cpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/os/bsd/vm/os_bsd.cpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/os/bsd/vm/perfMemory_bsd.cpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/os/linux/vm/os_linux.cpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/os/linux/vm/perfMemory_linux.cpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/os/posix/vm/os_posix.cpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/os/solaris/vm/attachListener_solaris.cpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/os/solaris/vm/os_solaris.cpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/os/solaris/vm/perfMemory_solaris.cpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/os/solaris/vm/threadCritical_solaris.cpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/os/windows/vm/os_windows.cpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/os/windows/vm/perfMemory_windows.cpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/c1/c1_Compilation.cpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/c1/c1_LinearScan.cpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/ci/ciReplay.cpp	Sat Apr 02 05:39:25 2016 +0200
@@ -1,4 +1,5 @@
-/* Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
+/*
+ * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -28,6 +29,7 @@
 #include "ci/ciKlass.hpp"
 #include "ci/ciUtilities.hpp"
 #include "compiler/compileBroker.hpp"
+#include "gc/shared/referencePendingListLocker.hpp"
 #include "memory/allocation.inline.hpp"
 #include "memory/oopFactory.hpp"
 #include "memory/resourceArea.hpp"
@@ -574,7 +576,7 @@
     Method* method = parse_method(CHECK);
     if (had_error()) return;
     /* just copied from Method, to build interpret data*/
-    if (InstanceRefKlass::owns_pending_list_lock((JavaThread*)THREAD)) {
+    if (ReferencePendingListLocker::is_locked_by_self()) {
       return;
     }
     // To be properly initialized, some profiling in the MDO needs the
--- a/hotspot/src/share/vm/classfile/classFileParser.cpp	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/classfile/classFileParser.cpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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/classLoader.cpp	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/classfile/classLoader.cpp	Sat Apr 02 05:39:25 2016 +0200
@@ -226,11 +226,12 @@
   return NULL;
 }
 
-ClassPathZipEntry::ClassPathZipEntry(jzfile* zip, const char* zip_name) : ClassPathEntry() {
+ClassPathZipEntry::ClassPathZipEntry(jzfile* zip, const char* zip_name, bool is_boot_append) : ClassPathEntry() {
   _zip = zip;
   char *copy = NEW_C_HEAP_ARRAY(char, strlen(zip_name)+1, mtClass);
   strcpy(copy, zip_name);
   _zip_name = copy;
+  _is_boot_append = is_boot_append;
 }
 
 ClassPathZipEntry::~ClassPathZipEntry() {
@@ -274,11 +275,79 @@
   return buffer;
 }
 
+#if INCLUDE_CDS
+u1* ClassPathZipEntry::open_versioned_entry(const char* name, jint* filesize, TRAPS) {
+  u1* buffer = NULL;
+  if (!_is_boot_append) {
+    assert(DumpSharedSpaces, "Should be called only for non-boot entries during dump time");
+    // We presume default is multi-release enabled
+    const char* multi_ver = Arguments::get_property("jdk.util.jar.enableMultiRelease");
+    const char* verstr = Arguments::get_property("jdk.util.jar.version");
+    bool is_multi_ver = (multi_ver == NULL ||
+                         strcmp(multi_ver, "true") == 0 ||
+                         strcmp(multi_ver, "force")  == 0) &&
+                         is_multiple_versioned(THREAD);
+    // command line version setting
+    int version = 0;
+    const int base_version = 8; // JDK8
+    int cur_ver = JDK_Version::current().major_version();
+    if (verstr != NULL) {
+      version = atoi(verstr);
+      if (version < base_version || version > cur_ver) {
+        is_multi_ver = false;
+        // print out warning, do not use assertion here since it will continue to look
+        // for proper version.
+        warning("JDK%d is not supported in multiple version jars", version);
+      }
+    }
+
+    if (is_multi_ver) {
+      int n;
+      char entry_name[JVM_MAXPATHLEN];
+      if (version > 0) {
+        n = jio_snprintf(entry_name, sizeof(entry_name), "META-INF/versions/%d/%s", version, name);
+        entry_name[n] = '\0';
+        buffer = open_entry((const char*)entry_name, filesize, false, CHECK_NULL);
+        if (buffer == NULL) {
+          warning("Could not find %s in %s, try to find highest version instead", entry_name, _zip_name);
+        }
+      }
+      if (buffer == NULL) {
+        for (int i = cur_ver; i >= base_version; i--) {
+          n = jio_snprintf(entry_name, sizeof(entry_name), "META-INF/versions/%d/%s", i, name);
+          entry_name[n] = '\0';
+          buffer = open_entry((const char*)entry_name, filesize, false, CHECK_NULL);
+          if (buffer != NULL) {
+            break;
+          }
+        }
+      }
+    }
+  }
+  return buffer;
+}
+
+bool ClassPathZipEntry::is_multiple_versioned(TRAPS) {
+  assert(DumpSharedSpaces, "called only at dump time");
+  jint size;
+  char* buffer = (char*)open_entry("META-INF/MANIFEST.MF", &size, false, CHECK_false);
+  if (buffer != NULL) {
+    if (strstr(buffer, "Multi-Release: true") != NULL) {
+      return true;
+    }
+  }
+  return false;
+}
+#endif // INCLUDE_CDS
+
 ClassFileStream* ClassPathZipEntry::open_stream(const char* name, TRAPS) {
   jint filesize;
-  const u1* buffer = open_entry(name, &filesize, false, CHECK_NULL);
+  u1* buffer = open_versioned_entry(name, &filesize, CHECK_NULL);
   if (buffer == NULL) {
-    return NULL;
+    buffer = open_entry(name, &filesize, false, CHECK_NULL);
+    if (buffer == NULL) {
+      return NULL;
+    }
   }
   if (UsePerfData) {
     ClassLoader::perf_sys_classfile_bytes_read()->inc(filesize);
@@ -558,7 +627,7 @@
     char* path = NEW_RESOURCE_ARRAY(char, end - start + 1);
     strncpy(path, &class_path[start], end - start);
     path[end - start] = '\0';
-    update_class_path_entry_list(path, false, mark_append_entry, false);
+    update_class_path_entry_list(path, false, mark_append_entry, false, bootstrap_search);
 
     // Check on the state of the boot loader's append path
     if (mark_append_entry && (_first_append_entry == NULL)) {
@@ -582,7 +651,8 @@
 }
 
 ClassPathEntry* ClassLoader::create_class_path_entry(const char *path, const struct stat* st,
-                                                     bool throw_exception, TRAPS) {
+                                                     bool throw_exception,
+                                                     bool is_boot_append, TRAPS) {
   JavaThread* thread = JavaThread::current();
   ClassPathEntry* new_entry = NULL;
   if ((st->st_mode & S_IFREG) == S_IFREG) {
@@ -611,7 +681,7 @@
         zip = (*ZipOpen)(canonical_path, &error_msg);
       }
       if (zip != NULL && error_msg == NULL) {
-        new_entry = new ClassPathZipEntry(zip, path);
+        new_entry = new ClassPathZipEntry(zip, path, is_boot_append);
       } else {
         ResourceMark rm(thread);
         char *msg;
@@ -644,7 +714,7 @@
 
 // Create a class path zip entry for a given path (return NULL if not found
 // or zip/JAR file cannot be opened)
-ClassPathZipEntry* ClassLoader::create_class_path_zip_entry(const char *path) {
+ClassPathZipEntry* ClassLoader::create_class_path_zip_entry(const char *path, bool is_boot_append) {
   // check for a regular file
   struct stat st;
   if (os::stat(path, &st) == 0) {
@@ -662,7 +732,7 @@
         }
         if (zip != NULL && error_msg == NULL) {
           // create using canonical path
-          return new ClassPathZipEntry(zip, canonical_path);
+          return new ClassPathZipEntry(zip, canonical_path, is_boot_append);
         }
       }
     }
@@ -720,11 +790,11 @@
 }
 
 void ClassLoader::add_to_list(const char *apath) {
-  update_class_path_entry_list((char*)apath, false, false, false);
+  update_class_path_entry_list((char*)apath, false, false, false, false);
 }
 
 void ClassLoader::prepend_to_list(const char *apath) {
-  update_class_path_entry_list((char*)apath, false, false, true);
+  update_class_path_entry_list((char*)apath, false, false, true, false);
 }
 
 // Returns true IFF the file/dir exists and the entry was successfully created.
@@ -732,13 +802,14 @@
                                                bool check_for_duplicates,
                                                bool mark_append_entry,
                                                bool prepend_entry,
+                                               bool is_boot_append,
                                                bool throw_exception) {
   struct stat st;
   if (os::stat(path, &st) == 0) {
     // File or directory found
     ClassPathEntry* new_entry = NULL;
     Thread* THREAD = Thread::current();
-    new_entry = create_class_path_entry(path, &st, throw_exception, CHECK_(false));
+    new_entry = create_class_path_entry(path, &st, throw_exception, is_boot_append, CHECK_(false));
     if (new_entry == NULL) {
       return false;
     }
--- a/hotspot/src/share/vm/classfile/classLoader.hpp	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/classfile/classLoader.hpp	Sat Apr 02 05:39:25 2016 +0200
@@ -104,16 +104,19 @@
  private:
   jzfile* _zip;              // The zip archive
   const char*   _zip_name;   // Name of zip archive
+  bool _is_boot_append;      // entry coming from -Xbootclasspath/a
  public:
   bool is_jrt()            { return false; }
   bool is_jar_file() const { return true;  }
   const char* name() const { return _zip_name; }
   JImageFile* jimage() const { return NULL; }
-  ClassPathZipEntry(jzfile* zip, const char* zip_name);
+  ClassPathZipEntry(jzfile* zip, const char* zip_name, bool is_boot_append);
   ~ClassPathZipEntry();
   u1* open_entry(const char* name, jint* filesize, bool nul_terminate, TRAPS);
+  u1* open_versioned_entry(const char* name, jint* filesize, TRAPS) NOT_CDS_RETURN_(NULL);
   ClassFileStream* open_stream(const char* name, TRAPS);
   void contents_do(void f(const char* name, void* context), void* context);
+  bool is_multiple_versioned(TRAPS) NOT_CDS_RETURN_(false);
   // Debugging
   NOT_PRODUCT(void compile_the_world(Handle loader, TRAPS);)
 };
@@ -223,7 +226,8 @@
   static void load_zip_library();
   static void load_jimage_library();
   static ClassPathEntry* create_class_path_entry(const char *path, const struct stat* st,
-                                                 bool throw_exception, TRAPS);
+                                                 bool throw_exception,
+                                                 bool is_boot_append, TRAPS);
 
  public:
 
@@ -249,6 +253,7 @@
                                            bool check_for_duplicates,
                                            bool mark_append_entry,
                                            bool prepend_entry,
+                                           bool is_boot_append,
                                            bool throw_exception=true);
   static void print_bootclasspath();
 
@@ -394,7 +399,7 @@
   static void prepend_to_list(ClassPathEntry* new_entry);
 
   // creates a class path zip entry (returns NULL if JAR file cannot be opened)
-  static ClassPathZipEntry* create_class_path_zip_entry(const char *apath);
+  static ClassPathZipEntry* create_class_path_zip_entry(const char *apath, bool is_boot_append);
 
   // add a path to class path list
   static void add_to_list(const char* apath);
--- a/hotspot/src/share/vm/classfile/javaClasses.cpp	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/classfile/javaClasses.cpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/classfile/javaClasses.hpp	Sat Apr 02 05:39:25 2016 +0200
@@ -155,11 +155,6 @@
   }
 
   static unsigned int hash_code(oop java_string);
-  static unsigned int latin1_hash_code(typeArrayOop value, int len);
-
-  // This is the string hash code used by the StringTable, which may be
-  // the same as String.hashCode or an alternate hash code.
-  static unsigned int hash_string(oop java_string);
 
   static bool equals(oop java_string, jchar* chars, int len);
   static bool equals(oop str1, oop str2);
@@ -456,6 +451,7 @@
 
 class java_lang_Throwable: AllStatic {
   friend class BacktraceBuilder;
+  friend class BacktraceIterator;
 
  private:
   // Offsets
@@ -481,16 +477,12 @@
 
   static int backtrace_offset;
   static int detailMessage_offset;
-  static int cause_offset;
   static int stackTrace_offset;
+  static int depth_offset;
   static int static_unassigned_stacktrace_offset;
 
-  // Printing
-  static char* print_stack_element_to_buffer(Handle mirror, int method, int version, int bci, int cpref);
   // StackTrace (programmatic access, new since 1.4)
   static void clear_stacktrace(oop throwable);
-  // No stack trace available
-  static const char* no_stack_trace_message();
   // Stacktrace (post JDK 1.7.0 to allow immutability protocol to be followed)
   static void set_stacktrace(oop throwable, oop st_element_array);
   static oop unassigned_stacktrace();
@@ -499,19 +491,20 @@
   // Backtrace
   static oop backtrace(oop throwable);
   static void set_backtrace(oop throwable, oop value);
+  static int depth(oop throwable);
+  static void set_depth(oop throwable, int value);
   // Needed by JVMTI to filter out this internal field.
   static int get_backtrace_offset() { return backtrace_offset;}
   static int get_detailMessage_offset() { return detailMessage_offset;}
   // Message
-  static oop message(oop throwable);
   static oop message(Handle throwable);
   static void set_message(oop throwable, oop value);
   static Symbol* detail_message(oop throwable);
-  static void print_stack_element(outputStream *st, Handle mirror, int method,
-                                  int version, int bci, int cpref);
   static void print_stack_element(outputStream *st, const methodHandle& method, int bci);
   static void print_stack_usage(Handle stream);
 
+  static void compute_offsets();
+
   // Allocate space for backtrace (created but stack trace not filled in)
   static void allocate_backtrace(Handle throwable, TRAPS);
   // Fill in current stack trace for throwable with preallocated backtrace (no GC)
@@ -520,8 +513,7 @@
   static void fill_in_stack_trace(Handle throwable, const methodHandle& method, TRAPS);
   static void fill_in_stack_trace(Handle throwable, const methodHandle& method = methodHandle());
   // Programmatic access to stack trace
-  static oop  get_stack_trace_element(oop throwable, int index, TRAPS);
-  static int  get_stack_trace_depth(oop throwable, TRAPS);
+  static void get_stack_trace_elements(Handle throwable, objArrayHandle stack_trace, TRAPS);
   // Printing
   static void print(Handle throwable, outputStream* st);
   static void print_stack_trace(Handle throwable, outputStream* st);
@@ -1333,7 +1325,6 @@
   static int fileName_offset;
   static int lineNumber_offset;
 
- public:
   // Setters
   static void set_moduleName(oop element, oop value);
   static void set_moduleVersion(oop element, oop value);
@@ -1342,10 +1333,13 @@
   static void set_fileName(oop element, oop value);
   static void set_lineNumber(oop element, int value);
 
+ public:
   // Create an instance of StackTraceElement
-  static oop create(Handle mirror, int method, int version, int bci, int cpref, TRAPS);
   static oop create(const methodHandle& method, int bci, TRAPS);
 
+  static void fill_in(Handle element, InstanceKlass* holder, const methodHandle& method,
+                      int version, int bci, int cpref, TRAPS);
+
   // Debugging
   friend class JavaClasses;
 };
--- a/hotspot/src/share/vm/classfile/loaderConstraints.cpp	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/classfile/loaderConstraints.cpp	Sat Apr 02 05:39:25 2016 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -111,13 +111,14 @@
       if (klass != NULL &&
           klass->class_loader_data()->is_unloading()) {
         probe->set_klass(NULL);
-        if (TraceLoaderConstraints) {
+        if (log_is_enabled(Info, constraints)) {
           ResourceMark rm;
-          tty->print_cr("[Purging class object from constraint for name %s,"
+          outputStream* out = LogHandle(classload, constraints)::info_stream();
+          out->print_cr("purging class object from constraint for name %s,"
                      " loader list:",
                      probe->name()->as_C_string());
           for (int i = 0; i < probe->num_loaders(); i++) {
-            tty->print_cr("[   [%d]: %s", i,
+            out->print_cr("    [%d]: %s", i,
                           probe->loader_data(i)->loader_name());
           }
         }
@@ -126,9 +127,10 @@
       int n = 0;
       while (n < probe->num_loaders()) {
         if (probe->loader_data(n)->is_unloading()) {
-            if (TraceLoaderConstraints) {
+            if (log_is_enabled(Info, classload, constraints)) {
               ResourceMark rm;
-              tty->print_cr("[Purging loader %s from constraint for name %s",
+              outputStream* out = LogHandle(classload, constraints)::info_stream();
+              out->print_cr("purging loader %s from constraint for name %s",
                             probe->loader_data(n)->loader_name(),
                             probe->name()->as_C_string()
                             );
@@ -140,11 +142,12 @@
           probe->set_loader_data(n, probe->loader_data(num));
           probe->set_loader_data(num, NULL);
 
-            if (TraceLoaderConstraints) {
+            if (log_is_enabled(Info, classload, constraints)) {
               ResourceMark rm;
-              tty->print_cr("[New loader list:");
+              outputStream* out = LogHandle(classload, constraints)::info_stream();
+              out->print_cr("new loader list:");
               for (int i = 0; i < probe->num_loaders(); i++) {
-                tty->print_cr("[   [%d]: %s", i,
+                out->print_cr("    [%d]: %s", i,
                               probe->loader_data(i)->loader_name());
               }
             }
@@ -156,9 +159,10 @@
       }
       // Check whether entry should be purged
       if (probe->num_loaders() < 2) {
-            if (TraceLoaderConstraints) {
+            if (log_is_enabled(Info, classload, constraints)) {
               ResourceMark rm;
-              tty->print("[Purging complete constraint for name %s\n",
+              outputStream* out = LogHandle(classload, constraints)::info_stream();
+              out->print_cr("purging complete constraint for name %s",
                          probe->name()->as_C_string());
             }
 
@@ -227,10 +231,11 @@
         p->set_klass(klass);
         p->set_next(bucket(index));
         set_entry(index, p);
-        if (TraceLoaderConstraints) {
+        if (log_is_enabled(Info, classload, constraints)) {
           ResourceMark rm;
-          tty->print("[Adding new constraint for name: %s, loader[0]: %s,"
-                     " loader[1]: %s ]\n",
+          outputStream* out = LogHandle(classload, constraints)::info_stream();
+          out->print_cr("adding new constraint for name: %s, loader[0]: %s,"
+                     " loader[1]: %s",
                      class_name->as_C_string(),
                      SystemDictionary::loader_name(class_loader1()),
                      SystemDictionary::loader_name(class_loader2())
@@ -240,10 +245,11 @@
         /* constraint already imposed */
         if ((*pp1)->klass() == NULL) {
           (*pp1)->set_klass(klass);
-          if (TraceLoaderConstraints) {
+          if (log_is_enabled(Info, classload, constraints)) {
             ResourceMark rm;
-            tty->print("[Setting class object in existing constraint for"
-                       " name: %s and loader %s ]\n",
+            outputStream* out = LogHandle(classload, constraints)::info_stream();
+            out->print_cr("setting class object in existing constraint for"
+                       " name: %s and loader %s",
                        class_name->as_C_string(),
                        SystemDictionary::loader_name(class_loader1())
                        );
@@ -261,8 +267,9 @@
     }
   }
 
-  if (failure_code != 0 && TraceLoaderConstraints) {
+  if (failure_code != 0 && log_is_enabled(Info, classload, constraints)) {
     ResourceMark rm;
+    outputStream* out = LogHandle(classload, constraints)::info_stream();
     const char* reason = "";
     switch(failure_code) {
     case 1: reason = "the class objects presented by loader[0] and loader[1]"
@@ -273,8 +280,8 @@
               " the stored class object in the constraint"; break;
     default: reason = "unknown reason code";
     }
-    tty->print("[Failed to add constraint for name: %s, loader[0]: %s,"
-               " loader[1]: %s, Reason: %s ]\n",
+    out->print_cr("failed to add constraint for name: %s, loader[0]: %s,"
+               " loader[1]: %s, Reason: %s",
                class_name->as_C_string(),
                SystemDictionary::loader_name(class_loader1()),
                SystemDictionary::loader_name(class_loader2()),
@@ -293,10 +300,11 @@
                                                    Symbol* name) {
   LoaderConstraintEntry* p = *(find_loader_constraint(name, loader));
   if (p && p->klass() != NULL && p->klass() != k()) {
-    if (TraceLoaderConstraints) {
+    if (log_is_enabled(Info, classload, constraints)) {
       ResourceMark rm;
-      tty->print("[Constraint check failed for name %s, loader %s: "
-                 "the presented class object differs from that stored ]\n",
+      outputStream* out = LogHandle(classload, constraints)::info_stream();
+      out->print_cr("constraint check failed for name %s, loader %s: "
+                 "the presented class object differs from that stored",
                  name->as_C_string(),
                  SystemDictionary::loader_name(loader()));
     }
@@ -304,10 +312,11 @@
   } else {
     if (p && p->klass() == NULL) {
       p->set_klass(k());
-      if (TraceLoaderConstraints) {
+      if (log_is_enabled(Info, classload, constraints)) {
         ResourceMark rm;
-        tty->print("[Updating constraint for name %s, loader %s, "
-                   "by setting class object ]\n",
+        outputStream* out = LogHandle(classload, constraints)::info_stream();
+        out->print_cr("updating constraint for name %s, loader %s, "
+                   "by setting class object",
                    name->as_C_string(),
                    SystemDictionary::loader_name(loader()));
       }
@@ -353,13 +362,14 @@
   int num = p->num_loaders();
   p->set_loader(num, loader());
   p->set_num_loaders(num + 1);
-  if (TraceLoaderConstraints) {
+  if (log_is_enabled(Info, classload, constraints)) {
     ResourceMark rm;
-    tty->print("[Extending constraint for name %s by adding loader[%d]: %s %s",
+    outputStream* out = LogHandle(classload, constraints)::info_stream();
+    out->print_cr("extending constraint for name %s by adding loader[%d]: %s %s",
                p->name()->as_C_string(),
                num,
                SystemDictionary::loader_name(loader()),
-               (p->klass() == NULL ? " and setting class object ]\n" : " ]\n")
+               (p->klass() == NULL ? " and setting class object" : "")
                );
   }
   if (p->klass() == NULL) {
@@ -392,18 +402,19 @@
     p1->set_num_loaders(num + 1);
   }
 
-  if (TraceLoaderConstraints) {
+  if (log_is_enabled(Info, classload, constraints)) {
     ResourceMark rm;
-    tty->print_cr("[Merged constraints for name %s, new loader list:",
+    outputStream* out = LogHandle(classload, constraints)::info_stream();
+    out->print_cr("merged constraints for name %s, new loader list:",
                   p1->name()->as_C_string()
                   );
 
     for (int i = 0; i < p1->num_loaders(); i++) {
-      tty->print_cr("[   [%d]: %s", i,
+      out->print_cr("    [%d]: %s", i,
                     p1->loader_data(i)->loader_name());
     }
     if (p1->klass() == NULL) {
-      tty->print_cr("[... and setting class object]");
+      out->print_cr("... and setting class object");
     }
   }
 
@@ -473,7 +484,6 @@
 // Called with the system dictionary lock held
 void LoaderConstraintTable::print() {
   ResourceMark rm;
-
   assert_locked_or_safepoint(SystemDictionary_lock);
   tty->print_cr("Java loader constraints (entries=%d)", _loader_constraint_size);
   for (int cindex = 0; cindex < _loader_constraint_size; cindex++) {
--- a/hotspot/src/share/vm/classfile/stringTable.cpp	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/classfile/stringTable.cpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/classfile/stringTable.hpp	Sat Apr 02 05:39:25 2016 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -111,7 +111,8 @@
   // Hashing algorithm, used as the hash value used by the
   //     StringTable for bucket selection and comparison (stored in the
   //     HashtableEntry structures).  This is used in the String.intern() method.
-  template<typename T> static unsigned int hash_string(const T* s, int len);
+  static unsigned int hash_string(const jchar* s, int len);
+  static unsigned int hash_string(oop string);
 
   // Internal test.
   static void test_alt_hash() PRODUCT_RETURN;
--- a/hotspot/src/share/vm/classfile/symbolTable.cpp	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/classfile/symbolTable.cpp	Sat Apr 02 05:39:25 2016 +0200
@@ -160,6 +160,11 @@
 // Create a new table and using alternate hash code, populate the new table
 // with the existing strings.   Set flag to use the alternate hash code afterwards.
 void SymbolTable::rehash_table() {
+  if (DumpSharedSpaces) {
+    tty->print_cr("Warning: rehash_table should not be called while dumping archive");
+    return;
+  }
+
   assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint");
   // This should never happen with -Xshare:dump but it might in testing mode.
   if (DumpSharedSpaces) return;
@@ -201,6 +206,11 @@
 
 Symbol* SymbolTable::lookup_shared(const char* name,
                                    int len, unsigned int hash) {
+  if (use_alternate_hashcode()) {
+    // hash_code parameter may use alternate hashing algorithm but the shared table
+    // always uses the same original hash code.
+    hash = hash_shared_symbol(name, len);
+  }
   return _shared_table.lookup(name, hash, len);
 }
 
@@ -234,6 +244,10 @@
            java_lang_String::hash_code((const jbyte*)s, len);
 }
 
+unsigned int SymbolTable::hash_shared_symbol(const char* s, int len) {
+  return java_lang_String::hash_code((const jbyte*)s, len);
+}
+
 
 // We take care not to be blocking while holding the
 // SymbolTable_lock. Otherwise, the system might deadlock, since the
@@ -536,7 +550,7 @@
     HashtableEntry<Symbol*, mtSymbol>* p = the_table()->bucket(i);
     for ( ; p != NULL; p = p->next()) {
       Symbol* s = (Symbol*)(p->literal());
-      unsigned int fixed_hash = hash_symbol((char*)s->bytes(), s->utf8_length());
+      unsigned int fixed_hash =  hash_shared_symbol((char*)s->bytes(), s->utf8_length());
       assert(fixed_hash == p->hash(), "must not rehash during dumping");
       ch_table.add(fixed_hash, s);
     }
--- a/hotspot/src/share/vm/classfile/symbolTable.hpp	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/classfile/symbolTable.hpp	Sat Apr 02 05:39:25 2016 +0200
@@ -175,6 +175,7 @@
   }
 
   static unsigned int hash_symbol(const char* s, int len);
+  static unsigned int hash_shared_symbol(const char* s, int len);
 
   static Symbol* lookup(const char* name, int len, TRAPS);
   // lookup only, won't add. Also calculate hash.
--- a/hotspot/src/share/vm/classfile/systemDictionary.cpp	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/classfile/systemDictionary.cpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/classfile/verificationType.cpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/classfile/verifier.cpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/classfile/vmSymbols.hpp	Sat Apr 02 05:39:25 2016 +0200
@@ -102,7 +102,6 @@
   template(java_security_SecureClassLoader,           "java/security/SecureClassLoader")          \
   template(java_net_URL,                              "java/net/URL")                             \
   template(java_util_jar_Manifest,                    "java/util/jar/Manifest")                   \
-  template(impliesCreateAccessControlContext_name,    "impliesCreateAccessControlContext")        \
   template(java_io_OutputStream,                      "java/io/OutputStream")                     \
   template(java_io_Reader,                            "java/io/Reader")                           \
   template(java_io_BufferedReader,                    "java/io/BufferedReader")                   \
@@ -326,7 +325,6 @@
   template(java_lang_StackFrameInfo,                  "java/lang/StackFrameInfo")                 \
   template(java_lang_LiveStackFrameInfo,              "java/lang/LiveStackFrameInfo")             \
   template(java_lang_StackStreamFactory_AbstractStackWalker, "java/lang/StackStreamFactory$AbstractStackWalker") \
-  template(doStackWalk_name,                          "doStackWalk")                              \
   template(doStackWalk_signature,                     "(JIIII)Ljava/lang/Object;")                \
   template(asPrimitive_name,                          "asPrimitive")                              \
   template(asPrimitive_int_signature,                 "(I)Ljava/lang/LiveStackFrame$PrimitiveValue;") \
@@ -377,14 +375,13 @@
   template(type_name,                                 "type")                                     \
   template(findNative_name,                           "findNative")                               \
   template(deadChild_name,                            "deadChild")                                \
-  template(addClass_name,                             "addClass")                                 \
-  template(throwIllegalAccessError_name,              "throwIllegalAccessError")                  \
   template(getFromClass_name,                         "getFromClass")                             \
   template(dispatch_name,                             "dispatch")                                 \
   template(getSystemClassLoader_name,                 "getSystemClassLoader")                     \
   template(fillInStackTrace_name,                     "fillInStackTrace")                         \
   template(getCause_name,                             "getCause")                                 \
   template(initCause_name,                            "initCause")                                \
+  template(depth_name,                                "depth")                                    \
   template(setProperty_name,                          "setProperty")                              \
   template(getProperty_name,                          "getProperty")                              \
   template(context_name,                              "context")                                  \
@@ -472,10 +469,6 @@
   template(url_code_signer_array_void_signature,      "(Ljava/net/URL;[Ljava/security/CodeSigner;)V") \
   template(module_entry_name,                         "module_entry")                             \
                                                                                                   \
-  /* non-intrinsic name/signature pairs: */                                                       \
-  template(register_method_name,                      "register")                                 \
-  do_alias(register_method_signature,         object_void_signature)                              \
-                                                                                                  \
   /* name symbols needed by intrinsics */                                                         \
   VM_INTRINSICS_DO(VM_INTRINSIC_IGNORE, VM_SYMBOL_IGNORE, template, VM_SYMBOL_IGNORE, VM_ALIAS_IGNORE) \
                                                                                                   \
--- a/hotspot/src/share/vm/compiler/compileBroker.cpp	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/compiler/compileBroker.cpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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"
@@ -901,7 +903,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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/compiler/methodLiveness.cpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/gc/cms/compactibleFreeListSpace.cpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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
@@ -2541,7 +2536,7 @@
         _blocks_to_claim[i].sample(
           MAX2(CMSOldPLABMin,
           MIN2(CMSOldPLABMax,
-               _global_num_blocks[i]/(_global_num_workers[i]*CMSOldPLABNumRefills))));
+               _global_num_blocks[i]/_global_num_workers[i]/CMSOldPLABNumRefills)));
       }
       // Reset counters for next round
       _global_num_workers[i] = 0;
--- a/hotspot/src/share/vm/gc/cms/concurrentMarkSweepGeneration.cpp	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/gc/cms/concurrentMarkSweepGeneration.cpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/gc/cms/concurrentMarkSweepThread.cpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/gc/cms/concurrentMarkSweepThread.hpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/gc/cms/parCardTableModRefBS.cpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/gc/cms/parNewGeneration.cpp	Sat Apr 02 05:39:25 2016 +0200
@@ -233,11 +233,15 @@
     if (word_sz * 100 < ParallelGCBufferWastePct * plab->word_sz()) {
       // Is small enough; abandon this buffer and start a new one.
       plab->retire();
-      size_t buf_size = plab->word_sz();
+      // The minimum size has to be twice SurvivorAlignmentInBytes to
+      // allow for padding used in the alignment of 1 word.  A padding
+      // of 1 is too small for a filler word so the padding size will
+      // be increased by SurvivorAlignmentInBytes.
+      size_t min_usable_size = 2 * static_cast<size_t>(SurvivorAlignmentInBytes >> LogHeapWordSize);
+      size_t buf_size = MAX2(plab->word_sz(), min_usable_size);
       HeapWord* buf_space = sp->par_allocate(buf_size);
       if (buf_space == NULL) {
-        const size_t min_bytes =
-          PLAB::min_size() << LogHeapWordSize;
+        const size_t min_bytes = MAX2(PLAB::min_size(), min_usable_size) << LogHeapWordSize;
         size_t free_bytes = sp->free();
         while(buf_space == NULL && free_bytes >= min_bytes) {
           buf_size = free_bytes >> LogHeapWordSize;
@@ -253,7 +257,10 @@
         // Note that we cannot compare buf_size < word_sz below
         // because of AlignmentReserve (see PLAB::allocate()).
         assert(obj != NULL || plab->words_remaining() < word_sz,
-               "Else should have been able to allocate");
+               "Else should have been able to allocate requested object size "
+               SIZE_FORMAT ", PLAB size " SIZE_FORMAT ", SurvivorAlignmentInBytes "
+               SIZE_FORMAT ", words_remaining " SIZE_FORMAT,
+               word_sz, buf_size, SurvivorAlignmentInBytes, plab->words_remaining());
         // It's conceivable that we may be able to use the
         // buffer we just grabbed for subsequent small requests
         // even if not for this one.
@@ -901,7 +908,7 @@
     size_policy->minor_collection_begin();
   }
 
-  GCTraceTime(Trace, gc) t1("ParNew", NULL, gch->gc_cause());
+  GCTraceTime(Trace, gc, phases) t1("ParNew", NULL, gch->gc_cause());
 
   age_table()->clear();
   to()->clear(SpaceDecorator::Mangle);
--- a/hotspot/src/share/vm/gc/cms/parOopClosures.inline.hpp	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/gc/cms/parOopClosures.inline.hpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/gc/cms/vmCMSOperations.cpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/gc/cms/vmCMSOperations.hpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/gc/cms/vmStructs_cms.hpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/gc/g1/collectionSetChooser.cpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/gc/g1/collectionSetChooser.hpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/gc/g1/concurrentG1Refine.cpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/gc/g1/concurrentG1Refine.hpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/gc/g1/concurrentG1RefineThread.cpp	Sat Apr 02 05:39:25 2016 +0200
@@ -76,9 +76,8 @@
 }
 
 void ConcurrentG1RefineThread::wait_for_completed_buffers() {
-  DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set();
   MutexLockerEx x(_monitor, Mutex::_no_safepoint_check_flag);
-  while (!_should_terminate && !is_active()) {
+  while (!should_terminate() && !is_active()) {
     _monitor->wait(Mutex::_no_safepoint_check_flag);
   }
 }
@@ -109,22 +108,13 @@
   }
 }
 
-void ConcurrentG1RefineThread::run() {
-  initialize_in_thread();
-  wait_for_universe_init();
-
-  run_service();
-
-  terminate();
-}
-
 void ConcurrentG1RefineThread::run_service() {
   _vtime_start = os::elapsedVTime();
 
-  while (!_should_terminate) {
+  while (!should_terminate()) {
     // Wait for work
     wait_for_completed_buffers();
-    if (_should_terminate) {
+    if (should_terminate()) {
       break;
     }
 
@@ -135,7 +125,12 @@
     {
       SuspendibleThreadSetJoiner sts_join;
 
-      do {
+      while (!should_terminate()) {
+        if (sts_join.should_yield()) {
+          sts_join.yield();
+          continue;             // Re-check for termination after yield delay.
+        }
+
         size_t curr_buffer_num = dcqs.completed_buffers_num();
         // If the number of the buffers falls down into the yellow zone,
         // that means that the transition period after the evacuation pause has ended.
@@ -147,17 +142,23 @@
         if (_next != NULL && !_next->is_active() && curr_buffer_num > _next->_threshold) {
           _next->activate();
         }
-      } while (dcqs.apply_closure_to_completed_buffer(_refine_closure,
-                                                      _worker_id + _worker_id_offset,
-                                                      _deactivation_threshold,
-                                                      false /* during_pause */));
 
-      deactivate();
-      log_debug(gc, refine)("Deactivated %d, off threshold: " SIZE_FORMAT ", current: " SIZE_FORMAT,
-                            _worker_id, _deactivation_threshold,
-                            dcqs.completed_buffers_num());
+        // Process the next buffer, if there are enough left.
+        if (!dcqs.apply_closure_to_completed_buffer(_refine_closure,
+                                                    _worker_id + _worker_id_offset,
+                                                    _deactivation_threshold,
+                                                    false /* during_pause */)) {
+          break; // Deactivate, number of buffers fell below threshold.
+        }
+      }
     }
 
+    deactivate();
+    log_debug(gc, refine)("Deactivated %d, off threshold: " SIZE_FORMAT
+                          ", current: " SIZE_FORMAT,
+                          _worker_id, _deactivation_threshold,
+                          dcqs.completed_buffers_num());
+
     if (os::supports_vtime()) {
       _vtime_accum = (os::elapsedVTime() - _vtime_start);
     } else {
@@ -168,23 +169,6 @@
   log_debug(gc, refine)("Stopping %d", _worker_id);
 }
 
-void ConcurrentG1RefineThread::stop() {
-  // it is ok to take late safepoints here, if needed
-  {
-    MutexLockerEx mu(Terminator_lock);
-    _should_terminate = true;
-  }
-
-  stop_service();
-
-  {
-    MutexLockerEx mu(Terminator_lock);
-    while (!_has_terminated) {
-      Terminator_lock->wait();
-    }
-  }
-}
-
 void ConcurrentG1RefineThread::stop_service() {
   MutexLockerEx x(_monitor, Mutex::_no_safepoint_check_flag);
   _monitor->notify();
--- a/hotspot/src/share/vm/gc/g1/concurrentG1RefineThread.hpp	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/gc/g1/concurrentG1RefineThread.hpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/gc/g1/concurrentMarkThread.cpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/gc/g1/concurrentMarkThread.hpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/gc/g1/dirtyCardQueue.cpp	Sat Apr 02 05:39:25 2016 +0200
@@ -110,44 +110,6 @@
   }
 }
 
-bool DirtyCardQueue::apply_closure(CardTableEntryClosure* cl,
-                                   bool consume,
-                                   uint worker_i) {
-  bool res = true;
-  if (_buf != NULL) {
-    res = apply_closure_to_buffer(cl, _buf, _index, _sz,
-                                  consume,
-                                  worker_i);
-    if (res && consume) {
-      _index = _sz;
-    }
-  }
-  return res;
-}
-
-bool DirtyCardQueue::apply_closure_to_buffer(CardTableEntryClosure* cl,
-                                             void** buf,
-                                             size_t index, size_t sz,
-                                             bool consume,
-                                             uint worker_i) {
-  if (cl == NULL) return true;
-  size_t limit = byte_index_to_index(sz);
-  for (size_t i = byte_index_to_index(index); i < limit; ++i) {
-    jbyte* card_ptr = static_cast<jbyte*>(buf[i]);
-    if (card_ptr != NULL) {
-      // Set the entry to null, so we don't do it again (via the test
-      // above) if we reconsider this buffer.
-      if (consume) {
-        buf[i] = NULL;
-      }
-      if (!cl->do_card_ptr(card_ptr, worker_i)) {
-        return false;
-      }
-    }
-  }
-  return true;
-}
-
 DirtyCardQueueSet::DirtyCardQueueSet(bool notify_when_complete) :
   PtrQueueSet(notify_when_complete),
   _mut_process_closure(NULL),
@@ -188,22 +150,57 @@
   t->dirty_card_queue().handle_zero_index();
 }
 
-bool DirtyCardQueueSet::mut_process_buffer(void** buf) {
+bool DirtyCardQueueSet::apply_closure_to_buffer(CardTableEntryClosure* cl,
+                                                BufferNode* node,
+                                                bool consume,
+                                                uint worker_i) {
+  if (cl == NULL) return true;
+  bool result = true;
+  void** buf = BufferNode::make_buffer_from_node(node);
+  size_t limit = DirtyCardQueue::byte_index_to_index(buffer_size());
+  size_t i = DirtyCardQueue::byte_index_to_index(node->index());
+  for ( ; i < limit; ++i) {
+    jbyte* card_ptr = static_cast<jbyte*>(buf[i]);
+    assert(card_ptr != NULL, "invariant");
+    if (!cl->do_card_ptr(card_ptr, worker_i)) {
+      result = false;           // Incomplete processing.
+      break;
+    }
+  }
+  if (consume) {
+    size_t new_index = DirtyCardQueue::index_to_byte_index(i);
+    assert(new_index <= buffer_size(), "invariant");
+    node->set_index(new_index);
+  }
+  return result;
+}
+
+#ifndef ASSERT
+#define assert_fully_consumed(node, buffer_size)
+#else
+#define assert_fully_consumed(node, buffer_size)                \
+  do {                                                          \
+    size_t _afc_index = (node)->index();                        \
+    size_t _afc_size = (buffer_size);                           \
+    assert(_afc_index == _afc_size,                             \
+           "Buffer was not fully consumed as claimed: index: "  \
+           SIZE_FORMAT ", size: " SIZE_FORMAT,                  \
+            _afc_index, _afc_size);                             \
+  } while (0)
+#endif // ASSERT
+
+bool DirtyCardQueueSet::mut_process_buffer(BufferNode* node) {
   guarantee(_free_ids != NULL, "must be");
 
-  // claim a par id
-  uint worker_i = _free_ids->claim_par_id();
+  uint worker_i = _free_ids->claim_par_id(); // temporarily claim an id
+  bool result = apply_closure_to_buffer(_mut_process_closure, node, true, worker_i);
+  _free_ids->release_par_id(worker_i); // release the id
 
-  bool b = DirtyCardQueue::apply_closure_to_buffer(_mut_process_closure, buf, 0,
-                                                   _sz, true, worker_i);
-  if (b) {
+  if (result) {
+    assert_fully_consumed(node, buffer_size());
     Atomic::inc(&_processed_buffers_mut);
   }
-
-  // release the id
-  _free_ids->release_par_id(worker_i);
-
-  return b;
+  return result;
 }
 
 
@@ -239,49 +236,31 @@
   if (nd == NULL) {
     return false;
   } else {
-    void** buf = BufferNode::make_buffer_from_node(nd);
-    size_t index = nd->index();
-    if (DirtyCardQueue::apply_closure_to_buffer(cl,
-                                                buf, index, _sz,
-                                                true, worker_i)) {
+    if (apply_closure_to_buffer(cl, nd, true, worker_i)) {
+      assert_fully_consumed(nd, buffer_size());
       // Done with fully processed buffer.
-      deallocate_buffer(buf);
+      deallocate_buffer(nd);
       Atomic::inc(&_processed_buffers_rs_thread);
-      return true;
     } else {
       // Return partially processed buffer to the queue.
-      enqueue_complete_buffer(buf, index);
-      return false;
+      guarantee(!during_pause, "Should never stop early");
+      enqueue_complete_buffer(nd);
     }
-  }
-}
-
-void DirtyCardQueueSet::apply_closure_to_all_completed_buffers(CardTableEntryClosure* cl) {
-  BufferNode* nd = _completed_buffers_head;
-  while (nd != NULL) {
-    bool b =
-      DirtyCardQueue::apply_closure_to_buffer(cl,
-                                              BufferNode::make_buffer_from_node(nd),
-                                              0, _sz, false);
-    guarantee(b, "Should not stop early.");
-    nd = nd->next();
+    return true;
   }
 }
 
 void DirtyCardQueueSet::par_apply_closure_to_all_completed_buffers(CardTableEntryClosure* cl) {
   BufferNode* nd = _cur_par_buffer_node;
   while (nd != NULL) {
-    BufferNode* next = (BufferNode*)nd->next();
-    BufferNode* actual = (BufferNode*)Atomic::cmpxchg_ptr((void*)next, (volatile void*)&_cur_par_buffer_node, (void*)nd);
+    BufferNode* next = nd->next();
+    void* actual = Atomic::cmpxchg_ptr(next, &_cur_par_buffer_node, nd);
     if (actual == nd) {
-      bool b =
-        DirtyCardQueue::apply_closure_to_buffer(cl,
-                                                BufferNode::make_buffer_from_node(actual),
-                                                0, _sz, false);
+      bool b = apply_closure_to_buffer(cl, nd, false);
       guarantee(b, "Should not stop early.");
       nd = next;
     } else {
-      nd = actual;
+      nd = static_cast<BufferNode*>(actual);
     }
   }
 }
@@ -304,7 +283,7 @@
   while (buffers_to_delete != NULL) {
     BufferNode* nd = buffers_to_delete;
     buffers_to_delete = nd->next();
-    deallocate_buffer(BufferNode::make_buffer_from_node(nd));
+    deallocate_buffer(nd);
   }
 
 }
@@ -320,6 +299,13 @@
   shared_dirty_card_queue()->reset();
 }
 
+void DirtyCardQueueSet::concatenate_log(DirtyCardQueue& dcq) {
+  if (!dcq.is_empty()) {
+    enqueue_complete_buffer(
+      BufferNode::make_node_from_buffer(dcq.get_buf(), dcq.get_index()));
+    dcq.reinitialize();
+  }
+}
 
 void DirtyCardQueueSet::concatenate_logs() {
   // Iterate over all the threads, if we find a partial log add it to
@@ -329,23 +315,9 @@
   _max_completed_queue = max_jint;
   assert(SafepointSynchronize::is_at_safepoint(), "Must be at safepoint.");
   for (JavaThread* t = Threads::first(); t; t = t->next()) {
-    DirtyCardQueue& dcq = t->dirty_card_queue();
-    if (dcq.size() != 0) {
-      void** buf = dcq.get_buf();
-      // We must NULL out the unused entries, then enqueue.
-      size_t limit = dcq.byte_index_to_index(dcq.get_index());
-      for (size_t i = 0; i < limit; ++i) {
-        buf[i] = NULL;
-      }
-      enqueue_complete_buffer(dcq.get_buf(), dcq.get_index());
-      dcq.reinitialize();
-    }
+    concatenate_log(t->dirty_card_queue());
   }
-  if (_shared_dirty_card_queue.size() != 0) {
-    enqueue_complete_buffer(_shared_dirty_card_queue.get_buf(),
-                            _shared_dirty_card_queue.get_index());
-    _shared_dirty_card_queue.reinitialize();
-  }
+  concatenate_log(_shared_dirty_card_queue);
   // Restore the completed buffer queue limit.
   _max_completed_queue = save_max_completed_queue;
 }
--- a/hotspot/src/share/vm/gc/g1/dirtyCardQueue.hpp	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/gc/g1/dirtyCardQueue.hpp	Sat Apr 02 05:39:25 2016 +0200
@@ -37,7 +37,7 @@
 public:
   // Process the card whose card table entry is "card_ptr".  If returns
   // "false", terminate the iteration early.
-  virtual bool do_card_ptr(jbyte* card_ptr, uint worker_i = 0) = 0;
+  virtual bool do_card_ptr(jbyte* card_ptr, uint worker_i) = 0;
 };
 
 // A ptrQueue whose elements are "oops", pointers to object heads.
@@ -52,23 +52,6 @@
   // Process queue entries and release resources.
   void flush() { flush_impl(); }
 
-  // Apply the closure to all elements, and reset the index to make the
-  // buffer empty.  If a closure application returns "false", return
-  // "false" immediately, halting the iteration.  If "consume" is true,
-  // deletes processed entries from logs.
-  bool apply_closure(CardTableEntryClosure* cl,
-                     bool consume = true,
-                     uint worker_i = 0);
-
-  // Apply the closure to all elements of "buf", down to "index"
-  // (inclusive.)  If returns "false", then a closure application returned
-  // "false", and we return immediately.  If "consume" is true, entries are
-  // set to NULL as they are processed, so they will not be processed again
-  // later.
-  static bool apply_closure_to_buffer(CardTableEntryClosure* cl,
-                                      void** buf, size_t index, size_t sz,
-                                      bool consume = true,
-                                      uint worker_i = 0);
   void **get_buf() { return _buf;}
   size_t get_index() { return _index;}
   void reinitialize() { _buf = 0; _sz = 0; _index = 0;}
@@ -94,8 +77,19 @@
 
   DirtyCardQueue _shared_dirty_card_queue;
 
-  // Override.
-  bool mut_process_buffer(void** buf);
+  // Apply the closure to the elements of "node" from it's index to
+  // buffer_size.  If all closure applications return true, then
+  // returns true.  Stops processing after the first closure
+  // application that returns false, and returns false from this
+  // function.  If "consume" is true, the node's index is updated to
+  // exclude the processed elements, e.g. up to the element for which
+  // the closure returned false.
+  bool apply_closure_to_buffer(CardTableEntryClosure* cl,
+                               BufferNode* node,
+                               bool consume,
+                               uint worker_i = 0);
+
+  bool mut_process_buffer(BufferNode* node);
 
   // Protected by the _cbl_mon.
   FreeIdSet* _free_ids;
@@ -107,6 +101,9 @@
 
   // Current buffer node used for parallel iteration.
   BufferNode* volatile _cur_par_buffer_node;
+
+  void concatenate_log(DirtyCardQueue& dcq);
+
 public:
   DirtyCardQueueSet(bool notify_when_complete = true);
 
@@ -125,13 +122,18 @@
 
   static void handle_zero_index_for_thread(JavaThread* t);
 
-  // If there exists some completed buffer, pop it, then apply the
-  // specified closure to all its elements, nulling out those elements
-  // processed.  If all elements are processed, returns "true".  If no
-  // completed buffers exist, returns false.  If a completed buffer exists,
-  // but is only partially completed before a "yield" happens, the
-  // partially completed buffer (with its processed elements set to NULL)
-  // is returned to the completed buffer set, and this call returns false.
+  // If there are more than stop_at completed buffers, pop one, apply
+  // the specified closure to its active elements, and return true.
+  // Otherwise return false.
+  //
+  // A completely processed buffer is freed.  However, if a closure
+  // invocation returns false, processing is stopped and the partially
+  // processed buffer (with its index updated to exclude the processed
+  // elements, e.g. up to the element for which the closure returned
+  // false) is returned to the completed buffer set.
+  //
+  // If during_pause is true, stop_at must be zero, and the closure
+  // must never return false.
   bool apply_closure_to_completed_buffer(CardTableEntryClosure* cl,
                                          uint worker_i,
                                          size_t stop_at,
@@ -139,13 +141,10 @@
 
   BufferNode* get_completed_buffer(size_t stop_at);
 
-  // Applies the current closure to all completed buffers,
-  // non-consumptively.
-  void apply_closure_to_all_completed_buffers(CardTableEntryClosure* cl);
-
   void reset_for_par_iteration() { _cur_par_buffer_node = _completed_buffers_head; }
   // Applies the current closure to all completed buffers, non-consumptively.
-  // Parallel version.
+  // Can be used in parallel, all callers using the iteration state initialized
+  // by reset_for_par_iteration.
   void par_apply_closure_to_all_completed_buffers(CardTableEntryClosure* cl);
 
   DirtyCardQueue* shared_dirty_card_queue() {
--- a/hotspot/src/share/vm/gc/g1/g1AllocRegion.cpp	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/gc/g1/g1AllocRegion.cpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/gc/g1/g1AllocRegion.hpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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()");
@@ -3138,7 +3109,7 @@
 }
 
 void G1CollectedHeap::print_taskqueue_stats() const {
-  if (!log_develop_is_enabled(Trace, gc, task, stats)) {
+  if (!log_is_enabled(Trace, gc, task, stats)) {
     return;
   }
   LogHandle(gc, task, stats) log;
@@ -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());
@@ -3253,7 +3228,7 @@
                                                                   Threads::number_of_non_daemon_threads());
     workers()->set_active_workers(active_workers);
 
-    g1_policy()->note_gc_start(active_workers);
+    g1_policy()->note_gc_start();
 
     TraceCollectorStats tcs(g1mm()->incremental_collection_counters());
     TraceMemoryManagerStats tms(false /* fullGC */, gc_cause());
@@ -3336,10 +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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.hpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/gc/g1/g1CollectorPolicy.cpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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,11 +183,11 @@
   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) {
-  phase_times()->note_gc_start(num_active_workers);
+void G1CollectorPolicy::note_gc_start() {
+  phase_times()->note_gc_start();
 }
 
 // Create the jstat counters for the policy.
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/gc/g1/g1CollectorPolicy.hpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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();
 
@@ -478,7 +317,7 @@
 
   void init();
 
-  virtual void note_gc_start(uint num_active_workers);
+  virtual void note_gc_start();
 
   // Create jstat counters for the policy.
   virtual void initialize_gc_policy_counters();
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/gc/g1/g1CollectorState.hpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.cpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.hpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/gc/g1/g1EvacStats.cpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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();
 }
--- a/hotspot/src/share/vm/gc/g1/g1FromCardCache.cpp	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/gc/g1/g1FromCardCache.cpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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,8 +37,8 @@
   guarantee(_cache == NULL, "Should not call this multiple times");
 
   _max_regions = max_num_regions;
-  _cache = Padded2DArray<int, mtGC>::create_unfreeable(num_par_rem_sets,
-                                                       _max_regions,
+  _cache = Padded2DArray<int, mtGC>::create_unfreeable(_max_regions,
+                                                       num_par_rem_sets,
                                                        &_static_mem_size);
 
   invalidate(0, _max_regions);
--- a/hotspot/src/share/vm/gc/g1/g1FromCardCache.hpp	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/gc/g1/g1FromCardCache.hpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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
@@ -32,8 +32,11 @@
 // a per-region and per-thread basis.
 class G1FromCardCache : public AllStatic {
  private:
-  // Array of card indices. Indexed by thread X and heap region to minimize
+  // Array of card indices. Indexed by heap region (rows) and thread (columns) to minimize
   // thread contention.
+  // This order minimizes the time to clear all entries for a given region during region
+  // freeing. I.e. a single clear of a single memory area instead of multiple separate
+  // accesses with a large stride per region.
   static int** _cache;
   static uint _max_regions;
   static size_t _static_mem_size;
@@ -58,11 +61,11 @@
   }
 
   static int at(uint worker_id, uint region_idx) {
-    return _cache[worker_id][region_idx];
+    return _cache[region_idx][worker_id];
   }
 
   static void set(uint worker_id, uint region_idx, int val) {
-    _cache[worker_id][region_idx] = val;
+    _cache[region_idx][worker_id] = val;
   }
 
   static void initialize(uint num_par_rem_sets, uint max_num_regions);
--- a/hotspot/src/share/vm/gc/g1/g1GCPhaseTimes.cpp	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/gc/g1/g1GCPhaseTimes.cpp	Sat Apr 02 05:39:25 2016 +0200
@@ -33,7 +33,7 @@
 #include "runtime/timer.hpp"
 #include "runtime/os.hpp"
 
-static const char* Indents[5] = {"", "  ", "    ", "     ", "       "};
+static const char* Indents[5] = {"", "  ", "    ", "      ", "        "};
 
 G1GCPhaseTimes::G1GCPhaseTimes(uint max_gc_threads) :
   _max_gc_threads(max_gc_threads)
@@ -94,11 +94,8 @@
   _gc_par_phases[PreserveCMReferents] = new WorkerDataArray<double>(max_gc_threads, "Parallel Preserve CM Refs (ms):");
 }
 
-void G1GCPhaseTimes::note_gc_start(uint active_gc_threads) {
-  assert(active_gc_threads > 0, "The number of threads must be > 0");
-  assert(active_gc_threads <= _max_gc_threads, "The number of active threads must be <= the max number of threads");
+void G1GCPhaseTimes::note_gc_start() {
   _gc_start_counter = os::elapsed_counter();
-  _active_gc_threads = active_gc_threads;
   _cur_expand_heap_time_ms = 0.0;
   _external_accounted_time_ms = 0.0;
 
@@ -109,31 +106,55 @@
   }
 }
 
+#define ASSERT_PHASE_UNINITIALIZED(phase) \
+    assert(_gc_par_phases[phase]->get(i) == uninitialized, "Phase " #phase " reported for thread that was not started");
+
+double G1GCPhaseTimes::worker_time(GCParPhases phase, uint worker) {
+  double value = _gc_par_phases[phase]->get(worker);
+  if (value != WorkerDataArray<double>::uninitialized()) {
+    return value;
+  }
+  return 0.0;
+}
+
 void G1GCPhaseTimes::note_gc_end() {
   _gc_pause_time_ms = TimeHelper::counter_to_millis(os::elapsed_counter() - _gc_start_counter);
-  for (uint i = 0; i < _active_gc_threads; i++) {
-    double worker_time = _gc_par_phases[GCWorkerEnd]->get(i) - _gc_par_phases[GCWorkerStart]->get(i);
-    record_time_secs(GCWorkerTotal, i , worker_time);
+
+  double uninitialized = WorkerDataArray<double>::uninitialized();
+
+  for (uint i = 0; i < _max_gc_threads; i++) {
+    double worker_start = _gc_par_phases[GCWorkerStart]->get(i);
+    if (worker_start != uninitialized) {
+      assert(_gc_par_phases[GCWorkerEnd]->get(i) != uninitialized, "Worker started but not ended.");
+      double total_worker_time = _gc_par_phases[GCWorkerEnd]->get(i) - _gc_par_phases[GCWorkerStart]->get(i);
+      record_time_secs(GCWorkerTotal, i , total_worker_time);
 
-    double worker_known_time =
-        _gc_par_phases[ExtRootScan]->get(i) +
-        _gc_par_phases[SATBFiltering]->get(i) +
-        _gc_par_phases[UpdateRS]->get(i) +
-        _gc_par_phases[ScanRS]->get(i) +
-        _gc_par_phases[CodeRoots]->get(i) +
-        _gc_par_phases[ObjCopy]->get(i) +
-        _gc_par_phases[Termination]->get(i);
+      double worker_known_time =
+          worker_time(ExtRootScan, i)
+          + worker_time(SATBFiltering, i)
+          + worker_time(UpdateRS, i)
+          + worker_time(ScanRS, i)
+          + worker_time(CodeRoots, i)
+          + worker_time(ObjCopy, i)
+          + worker_time(Termination, i);
 
-    record_time_secs(Other, i, worker_time - worker_known_time);
-  }
-
-  for (int i = 0; i < GCParPhasesSentinel; i++) {
-    if (_gc_par_phases[i] != NULL) {
-      _gc_par_phases[i]->verify(_active_gc_threads);
+      record_time_secs(Other, i, total_worker_time - worker_known_time);
+    } else {
+      // Make sure all slots are uninitialized since this thread did not seem to have been started
+      ASSERT_PHASE_UNINITIALIZED(GCWorkerEnd);
+      ASSERT_PHASE_UNINITIALIZED(ExtRootScan);
+      ASSERT_PHASE_UNINITIALIZED(SATBFiltering);
+      ASSERT_PHASE_UNINITIALIZED(UpdateRS);
+      ASSERT_PHASE_UNINITIALIZED(ScanRS);
+      ASSERT_PHASE_UNINITIALIZED(CodeRoots);
+      ASSERT_PHASE_UNINITIALIZED(ObjCopy);
+      ASSERT_PHASE_UNINITIALIZED(Termination);
     }
   }
 }
 
+#undef ASSERT_PHASE_UNINITIALIZED
+
 // record the time a phase took in seconds
 void G1GCPhaseTimes::record_time_secs(GCParPhases phase, uint worker_i, double secs) {
   _gc_par_phases[phase]->set(worker_i, secs);
@@ -150,12 +171,12 @@
 
 // return the average time for a phase in milliseconds
 double G1GCPhaseTimes::average_time_ms(GCParPhases phase) {
-  return _gc_par_phases[phase]->average(_active_gc_threads) * 1000.0;
+  return _gc_par_phases[phase]->average() * 1000.0;
 }
 
 size_t G1GCPhaseTimes::sum_thread_work_items(GCParPhases phase) {
   assert(_gc_par_phases[phase]->thread_work_items() != NULL, "No sub count");
-  return _gc_par_phases[phase]->thread_work_items()->sum(_active_gc_threads);
+  return _gc_par_phases[phase]->thread_work_items()->sum();
 }
 
 template <class T>
@@ -164,19 +185,19 @@
   if (log.is_level(LogLevel::Trace)) {
     outputStream* trace_out = log.trace_stream();
     trace_out->print("%s", indent);
-    phase->print_details_on(trace_out, _active_gc_threads);
+    phase->print_details_on(trace_out);
   }
 }
 
 void G1GCPhaseTimes::log_phase(WorkerDataArray<double>* phase, uint indent, outputStream* out, bool print_sum) {
   out->print("%s", Indents[indent]);
-  phase->print_summary_on(out, _active_gc_threads, print_sum);
+  phase->print_summary_on(out, print_sum);
   details(phase, Indents[indent]);
 
   WorkerDataArray<size_t>* work_items = phase->thread_work_items();
   if (work_items != NULL) {
     out->print("%s", Indents[indent + 1]);
-    work_items->print_summary_on(out, _active_gc_threads, true);
+    work_items->print_summary_on(out, true);
     details(work_items, Indents[indent + 1]);
   }
 }
@@ -277,11 +298,11 @@
   }
   debug_line("Choose CSet", (_recorded_young_cset_choice_time_ms + _recorded_non_young_cset_choice_time_ms));
   debug_line("Preserve CM Refs", _recorded_preserve_cm_referents_time_ms);
+  trace_phase(_gc_par_phases[PreserveCMReferents]);
   debug_line("Reference Processing", _cur_ref_proc_time_ms);
   debug_line("Reference Enqueuing", _cur_ref_enq_time_ms);
   debug_line("Redirty Cards", _recorded_redirty_logged_cards_time_ms);
   trace_phase(_gc_par_phases[RedirtyCards]);
-  trace_phase(_gc_par_phases[PreserveCMReferents]);
   if (G1EagerReclaimHumongousObjects) {
     debug_line("Humongous Register", _cur_fast_reclaim_humongous_register_time_ms);
     trace_line_sz("Humongous Total", _cur_fast_reclaim_humongous_total);
--- a/hotspot/src/share/vm/gc/g1/g1GCPhaseTimes.hpp	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/gc/g1/g1GCPhaseTimes.hpp	Sat Apr 02 05:39:25 2016 +0200
@@ -32,7 +32,6 @@
 template <class T> class WorkerDataArray;
 
 class G1GCPhaseTimes : public CHeapObj<mtGC> {
-  uint _active_gc_threads;
   uint _max_gc_threads;
   jlong _gc_start_counter;
   double _gc_pause_time_ms;
@@ -123,6 +122,7 @@
   double _cur_verify_before_time_ms;
   double _cur_verify_after_time_ms;
 
+  double worker_time(GCParPhases phase, uint worker);
   void note_gc_end();
 
   template <class T>
@@ -133,7 +133,7 @@
 
  public:
   G1GCPhaseTimes(uint max_gc_threads);
-  void note_gc_start(uint active_gc_threads);
+  void note_gc_start();
   void print();
 
   // record the time a phase took in seconds
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/gc/g1/g1HeapSizingPolicy.cpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/gc/g1/g1HeapTransition.cpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/gc/g1/g1HotCardCache.cpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/gc/g1/g1HotCardCache.hpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/gc/g1/g1MarkSweep.cpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/gc/g1/g1MonitoringSupport.cpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/gc/g1/g1ParScanThreadState.cpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/gc/g1/g1StringDedup.cpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/gc/g1/g1StringDedupThread.cpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/gc/g1/g1StringDedupThread.hpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/gc/g1/g1YoungRemSetSamplingThread.cpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/gc/g1/g1YoungRemSetSamplingThread.hpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/gc/g1/g1_globals.hpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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/heapRegionBounds.hpp	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/gc/g1/heapRegionBounds.hpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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
@@ -25,6 +25,8 @@
 #ifndef SHARE_VM_GC_G1_HEAPREGIONBOUNDS_HPP
 #define SHARE_VM_GC_G1_HEAPREGIONBOUNDS_HPP
 
+#include "memory/allocation.hpp"
+
 class HeapRegionBounds : public AllStatic {
 private:
   // Minimum region size; we won't go lower than that.
--- a/hotspot/src/share/vm/gc/g1/ptrQueue.cpp	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/gc/g1/ptrQueue.cpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/gc/g1/ptrQueue.hpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/gc/g1/satbMarkQueue.cpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/gc/g1/satbMarkQueue.hpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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/suspendibleThreadSet.cpp	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/gc/g1/suspendibleThreadSet.cpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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
@@ -25,6 +25,7 @@
 #include "precompiled.hpp"
 #include "gc/g1/suspendibleThreadSet.hpp"
 #include "runtime/mutexLocker.hpp"
+#include "runtime/semaphore.hpp"
 #include "runtime/thread.inline.hpp"
 
 uint   SuspendibleThreadSet::_nthreads          = 0;
@@ -32,6 +33,19 @@
 bool   SuspendibleThreadSet::_suspend_all       = false;
 double SuspendibleThreadSet::_suspend_all_start = 0.0;
 
+static Semaphore* _synchronize_wakeup = NULL;
+
+void SuspendibleThreadSet_init() {
+  assert(_synchronize_wakeup == NULL, "STS already initialized");
+  _synchronize_wakeup = new Semaphore();
+}
+
+bool SuspendibleThreadSet::is_synchronized() {
+  assert_lock_strong(STS_lock);
+  assert(_nthreads_stopped <= _nthreads, "invariant");
+  return _nthreads_stopped == _nthreads;
+}
+
 void SuspendibleThreadSet::join() {
   assert(!Thread::current()->is_suspendible_thread(), "Thread already joined");
   MonitorLockerEx ml(STS_lock, Mutex::_no_safepoint_check_flag);
@@ -48,31 +62,30 @@
   assert(_nthreads > 0, "Invalid");
   DEBUG_ONLY(Thread::current()->clear_suspendible_thread();)
   _nthreads--;
-  if (_suspend_all) {
-    ml.notify_all();
+  if (_suspend_all && is_synchronized()) {
+    // This leave completes a request, so inform the requestor.
+    _synchronize_wakeup->signal();
   }
 }
 
 void SuspendibleThreadSet::yield() {
   assert(Thread::current()->is_suspendible_thread(), "Must have joined");
+  MonitorLockerEx ml(STS_lock, Mutex::_no_safepoint_check_flag);
   if (_suspend_all) {
-    MonitorLockerEx ml(STS_lock, Mutex::_no_safepoint_check_flag);
-    if (_suspend_all) {
-      _nthreads_stopped++;
-      if (_nthreads_stopped == _nthreads) {
-        if (ConcGCYieldTimeout > 0) {
-          double now = os::elapsedTime();
-          guarantee((now - _suspend_all_start) * 1000.0 < (double)ConcGCYieldTimeout, "Long delay");
-        }
+    _nthreads_stopped++;
+    if (is_synchronized()) {
+      if (ConcGCYieldTimeout > 0) {
+        double now = os::elapsedTime();
+        guarantee((now - _suspend_all_start) * 1000.0 < (double)ConcGCYieldTimeout, "Long delay");
       }
-      ml.notify_all();
-      while (_suspend_all) {
-        ml.wait(Mutex::_no_safepoint_check_flag);
-      }
-      assert(_nthreads_stopped > 0, "Invalid");
-      _nthreads_stopped--;
-      ml.notify_all();
+      // This yield completes the request, so inform the requestor.
+      _synchronize_wakeup->signal();
     }
+    while (_suspend_all) {
+      ml.wait(Mutex::_no_safepoint_check_flag);
+    }
+    assert(_nthreads_stopped > 0, "Invalid");
+    _nthreads_stopped--;
   }
 }
 
@@ -81,18 +94,41 @@
   if (ConcGCYieldTimeout > 0) {
     _suspend_all_start = os::elapsedTime();
   }
+  {
+    MonitorLockerEx ml(STS_lock, Mutex::_no_safepoint_check_flag);
+    assert(!_suspend_all, "Only one at a time");
+    _suspend_all = true;
+    if (is_synchronized()) {
+      return;
+    }
+  } // Release lock before semaphore wait.
+
+  // Semaphore initial count is zero.  To reach here, there must be at
+  // least one not yielded thread in the set, e.g. is_synchronized()
+  // was false before the lock was released.  A thread in the set will
+  // signal the semaphore iff it is the last to yield or leave while
+  // there is an active suspend request.  So there will be exactly one
+  // signal, which will increment the semaphore count to one, which
+  // will then be consumed by this wait, returning it to zero.  No
+  // thread can exit yield or enter the set until desynchronize is
+  // called, so there are no further opportunities for the semaphore
+  // being signaled until we get back here again for some later
+  // synchronize call.  Hence, there is no need to re-check for
+  // is_synchronized after the wait; it will always be true there.
+  _synchronize_wakeup->wait();
+
+#ifdef ASSERT
   MonitorLockerEx ml(STS_lock, Mutex::_no_safepoint_check_flag);
-  assert(!_suspend_all, "Only one at a time");
-  _suspend_all = true;
-  while (_nthreads_stopped < _nthreads) {
-    ml.wait(Mutex::_no_safepoint_check_flag);
-  }
+  assert(_suspend_all, "STS not synchronizing");
+  assert(is_synchronized(), "STS not synchronized");
+#endif
 }
 
 void SuspendibleThreadSet::desynchronize() {
   assert(Thread::current()->is_VM_thread(), "Must be the VM thread");
   MonitorLockerEx ml(STS_lock, Mutex::_no_safepoint_check_flag);
-  assert(_nthreads_stopped == _nthreads, "Invalid");
+  assert(_suspend_all, "STS not synchronizing");
+  assert(is_synchronized(), "STS not synchronized");
   _suspend_all = false;
   ml.notify_all();
 }
--- a/hotspot/src/share/vm/gc/g1/suspendibleThreadSet.hpp	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/gc/g1/suspendibleThreadSet.hpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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,6 +45,8 @@
   static bool   _suspend_all;
   static double _suspend_all_start;
 
+  static bool is_synchronized();
+
   // Add the current thread to the set. May block if a suspension is in progress.
   static void join();
 
--- a/hotspot/src/share/vm/gc/g1/vm_operations_g1.cpp	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/gc/g1/vm_operations_g1.cpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/gc/g1/vm_operations_g1.hpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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/workerDataArray.cpp	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/gc/g1/workerDataArray.cpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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,67 +27,178 @@
 #include "utilities/ostream.hpp"
 
 template <>
-void WorkerDataArray<double>::WDAPrinter::summary(outputStream* out, const char* title, double min, double avg, double max, double diff, double sum, bool print_sum) {
-  out->print("%-25s Min: %4.1lf, Avg: %4.1lf, Max: %4.1lf, Diff: %4.1lf", title, min * MILLIUNITS, avg * MILLIUNITS, max * MILLIUNITS, diff* MILLIUNITS);
+size_t WorkerDataArray<size_t>::uninitialized() {
+  return (size_t)-1;
+}
+
+template <>
+double WorkerDataArray<double>::uninitialized() {
+  return -1.0;
+}
+
+template <>
+void WorkerDataArray<double>::WDAPrinter::summary(outputStream* out, double min, double avg, double max, double diff, double sum, bool print_sum) {
+  out->print(" Min: %4.1lf, Avg: %4.1lf, Max: %4.1lf, Diff: %4.1lf", min * MILLIUNITS, avg * MILLIUNITS, max * MILLIUNITS, diff* MILLIUNITS);
   if (print_sum) {
-    out->print_cr(", Sum: %4.1lf", sum * MILLIUNITS);
-  } else {
-    out->cr();
+    out->print(", Sum: %4.1lf", sum * MILLIUNITS);
   }
 }
 
 template <>
-void WorkerDataArray<size_t>::WDAPrinter::summary(outputStream* out, const char* title, size_t min, double avg, size_t max, size_t diff, size_t sum, bool print_sum) {
-  out->print("%-25s Min: " SIZE_FORMAT ", Avg: %4.1lf, Max: " SIZE_FORMAT ", Diff: " SIZE_FORMAT, title, min, avg, max, diff);
+void WorkerDataArray<size_t>::WDAPrinter::summary(outputStream* out, size_t min, double avg, size_t max, size_t diff, size_t sum, bool print_sum) {
+  out->print(" Min: " SIZE_FORMAT ", Avg: %4.1lf, Max: " SIZE_FORMAT ", Diff: " SIZE_FORMAT, min, avg, max, diff);
   if (print_sum) {
-    out->print_cr(", Sum: " SIZE_FORMAT, sum);
-  } else {
-    out->cr();
+    out->print(", Sum: " SIZE_FORMAT, sum);
   }
 }
 
 template <>
-void WorkerDataArray<double>::WDAPrinter::details(const WorkerDataArray<double>* phase, outputStream* out, uint active_threads) {
+void WorkerDataArray<double>::WDAPrinter::details(const WorkerDataArray<double>* phase, outputStream* out) {
   out->print("%-25s", "");
-  for (uint i = 0; i < active_threads; ++i) {
-    out->print(" %4.1lf", phase->get(i) * 1000.0);
+  for (uint i = 0; i < phase->_length; ++i) {
+    double value = phase->get(i);
+    if (value != phase->uninitialized()) {
+      out->print(" %4.1lf", phase->get(i) * 1000.0);
+    } else {
+      out->print(" -");
+    }
   }
   out->cr();
 }
 
 template <>
-void WorkerDataArray<size_t>::WDAPrinter::details(const WorkerDataArray<size_t>* phase, outputStream* out, uint active_threads) {
+void WorkerDataArray<size_t>::WDAPrinter::details(const WorkerDataArray<size_t>* phase, outputStream* out) {
   out->print("%-25s", "");
-  for (uint i = 0; i < active_threads; ++i) {
-    out->print("  " SIZE_FORMAT, phase->get(i));
+  for (uint i = 0; i < phase->_length; ++i) {
+    size_t value = phase->get(i);
+    if (value != phase->uninitialized()) {
+      out->print("  " SIZE_FORMAT, phase->get(i));
+    } else {
+      out->print(" -");
+    }
   }
   out->cr();
 }
 
 #ifndef PRODUCT
-void WorkerDataArray_test() {
-  const uint length = 3;
-  const char* title = "Test array";
+
+#include "memory/resourceArea.hpp"
+
+void WorkerDataArray_test_verify_string(const char* expected_string, const char* actual_string) {
+  const size_t expected_len = strlen(expected_string);
+
+  assert(expected_len == strlen(actual_string),
+      "Wrong string length, expected " SIZE_FORMAT " but got " SIZE_FORMAT "(Expected '%s' but got: '%s')",
+      expected_len, strlen(actual_string), expected_string, actual_string);
 
-  WorkerDataArray<size_t> array(length, title);
-  assert(strncmp(array.title(), title, strlen(title)) == 0 , "Expected titles to match");
+  // Can't use strncmp here because floating point values use different decimal points for different locales.
+  // Allow strings to differ in "." vs. "," only. This should still catch most errors.
+  for (size_t i = 0; i < expected_len; i++) {
+    char e = expected_string[i];
+    char a = actual_string[i];
+    if (e != a) {
+      if ((e == '.' || e == ',') && (a == '.' || a == ',')) {
+        // Most likely just a difference in locale
+      } else {
+        assert(false, "Expected '%s' but got: '%s'", expected_string, actual_string);
+      }
+    }
+  }
+}
+
+void WorkerDataArray_test_verify_array(WorkerDataArray<size_t>& array, size_t expected_sum, double expected_avg, const char* expected_summary, const char* exected_details) {
+  const double epsilon = 0.0001;
+  assert(array.sum() == expected_sum, "Wrong sum, expected: " SIZE_FORMAT " but got: " SIZE_FORMAT, expected_sum, array.sum());
+  assert(fabs(array.average() - expected_avg) < epsilon, "Wrong average, expected: %f but got: %f", expected_avg, array.average());
 
-  const size_t expected[length] = {5, 3, 7};
-  for (uint i = 0; i < length; i++) {
-    array.set(i, expected[i]);
-  }
-  for (uint i = 0; i < length; i++) {
-    assert(array.get(i) == expected[i], "Expected elements to match");
+  ResourceMark rm;
+  stringStream out;
+  array.print_summary_on(&out);
+  WorkerDataArray_test_verify_string(expected_summary, out.as_string());
+  out.reset();
+  array.print_details_on(&out);
+  WorkerDataArray_test_verify_string(exected_details, out.as_string());
+}
+
+void WorkerDataArray_test_verify_array(WorkerDataArray<double>& array, double expected_sum, double expected_avg, const char* expected_summary, const char* exected_details) {
+  const double epsilon = 0.0001;
+  assert(fabs(array.sum() - expected_sum) < epsilon, "Wrong sum, expected: %f but got: %f", expected_sum, array.sum());
+  assert(fabs(array.average() - expected_avg) < epsilon, "Wrong average, expected: %f but got: %f", expected_avg, array.average());
+
+  ResourceMark rm;
+  stringStream out;
+  array.print_summary_on(&out);
+  WorkerDataArray_test_verify_string(expected_summary, out.as_string());
+  out.reset();
+  array.print_details_on(&out);
+  WorkerDataArray_test_verify_string(exected_details, out.as_string());
+}
+
+void WorkerDataArray_test_basic() {
+  WorkerDataArray<size_t> array(3, "Test array");
+  array.set(0, 5);
+  array.set(1, 3);
+  array.set(2, 7);
+
+  WorkerDataArray_test_verify_array(array, 15, 5.0,
+      "Test array                Min: 3, Avg:  5.0, Max: 7, Diff: 4, Sum: 15, Workers: 3\n",
+      "                           5  3  7\n" );
+}
+
+void WorkerDataArray_test_add() {
+  WorkerDataArray<size_t> array(3, "Test array");
+  array.set(0, 5);
+  array.set(1, 3);
+  array.set(2, 7);
+
+  for (uint i = 0; i < 3; i++) {
+    array.add(i, 1);
   }
 
-  assert(array.sum(length) == (5 + 3 + 7), "Expected sums to match");
-  assert(array.average(length) == 5.0, "Expected averages to match");
+  WorkerDataArray_test_verify_array(array, 18, 6.0,
+      "Test array                Min: 4, Avg:  6.0, Max: 8, Diff: 4, Sum: 18, Workers: 3\n",
+      "                           6  4  8\n" );
+}
+
+void WorkerDataArray_test_with_uninitialized() {
+  WorkerDataArray<size_t> array(3, "Test array");
+  array.set(0, 5);
+  array.set(1, WorkerDataArray<size_t>::uninitialized());
+  array.set(2, 7);
+
+  WorkerDataArray_test_verify_array(array, 12, 6,
+      "Test array                Min: 5, Avg:  6.0, Max: 7, Diff: 2, Sum: 12, Workers: 2\n",
+      "                           5 -  7\n" );
+}
+
+void WorkerDataArray_test_uninitialized() {
+  WorkerDataArray<size_t> array(3, "Test array");
+  array.set(0, WorkerDataArray<size_t>::uninitialized());
+  array.set(1, WorkerDataArray<size_t>::uninitialized());
+  array.set(2, WorkerDataArray<size_t>::uninitialized());
 
-  for (uint i = 0; i < length; i++) {
-    array.add(i, 1);
-  }
-  for (uint i = 0; i < length; i++) {
-    assert(array.get(i) == expected[i] + 1, "Expected add to increment values");
-  }
+  WorkerDataArray_test_verify_array(array, 0, 0.0,
+      "Test array                skipped\n",
+      "                          - - -\n" );
 }
+
+void WorkerDataArray_test_double_with_uninitialized() {
+  WorkerDataArray<double> array(3, "Test array");
+  array.set(0, 5.1 / MILLIUNITS);
+  array.set(1, WorkerDataArray<double>::uninitialized());
+  array.set(2, 7.2 / MILLIUNITS);
+
+  WorkerDataArray_test_verify_array(array, 12.3 / MILLIUNITS, 6.15 / MILLIUNITS,
+      "Test array                Min:  5.1, Avg:  6.1, Max:  7.2, Diff:  2.1, Sum: 12.3, Workers: 2\n",
+      "                           5.1 -  7.2\n" );
+}
+
+void WorkerDataArray_test() {
+  WorkerDataArray_test_basic();
+  WorkerDataArray_test_add();
+  WorkerDataArray_test_with_uninitialized();
+  WorkerDataArray_test_uninitialized();
+  WorkerDataArray_test_double_with_uninitialized();
+}
+
 #endif
--- a/hotspot/src/share/vm/gc/g1/workerDataArray.hpp	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/gc/g1/workerDataArray.hpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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
@@ -32,16 +32,13 @@
 
 template <class T>
 class WorkerDataArray  : public CHeapObj<mtGC> {
+  friend class WDAPrinter;
   T*          _data;
   uint        _length;
   const char* _title;
 
   WorkerDataArray<size_t>* _thread_work_items;
 
-  NOT_PRODUCT(inline T uninitialized() const;)
-
-  void set_all(T value);
-
  public:
   WorkerDataArray(uint length, const char* title);
   ~WorkerDataArray();
@@ -52,37 +49,38 @@
     return _thread_work_items;
   }
 
+  static T uninitialized();
+
   void set(uint worker_i, T value);
   T get(uint worker_i) const;
 
   void add(uint worker_i, T value);
 
-  double average(uint active_threads) const;
-  T sum(uint active_threads) const;
+  // The sum() and average() methods below consider uninitialized slots to be 0.
+  double average() const;
+  T sum() const;
 
   const char* title() const {
     return _title;
   }
 
-  void clear();
-
-  void reset() PRODUCT_RETURN;
-  void verify(uint active_threads) const PRODUCT_RETURN;
+  void reset();
+  void set_all(T value);
 
 
  private:
   class WDAPrinter {
   public:
-    static void summary(outputStream* out, const char* title, double min, double avg, double max, double diff, double sum, bool print_sum);
-    static void summary(outputStream* out, const char* title, size_t min, double avg, size_t max, size_t diff, size_t sum, bool print_sum);
+    static void summary(outputStream* out, double min, double avg, double max, double diff, double sum, bool print_sum);
+    static void summary(outputStream* out, size_t min, double avg, size_t max, size_t diff, size_t sum, bool print_sum);
 
-    static void details(const WorkerDataArray<double>* phase, outputStream* out, uint active_threads);
-    static void details(const WorkerDataArray<size_t>* phase, outputStream* out, uint active_threads);
+    static void details(const WorkerDataArray<double>* phase, outputStream* out);
+    static void details(const WorkerDataArray<size_t>* phase, outputStream* out);
   };
 
  public:
-  void print_summary_on(outputStream* out, uint active_threads, bool print_sum = true) const;
-  void print_details_on(outputStream* out, uint active_threads) const;
+  void print_summary_on(outputStream* out, bool print_sum = true) const;
+  void print_details_on(outputStream* out) const;
 };
 
 #endif // SHARE_VM_GC_G1_WORKERDATAARRAY_HPP
--- a/hotspot/src/share/vm/gc/g1/workerDataArray.inline.hpp	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/gc/g1/workerDataArray.inline.hpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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
@@ -50,7 +50,6 @@
 template <typename T>
 T WorkerDataArray<T>::get(uint worker_i) const {
   assert(worker_i < _length, "Worker %d is greater than max: %d", worker_i, _length);
-  assert(_data[worker_i] != uninitialized(), "No data added for worker %d", worker_i);
   return _data[worker_i];
 }
 
@@ -78,25 +77,31 @@
 }
 
 template <typename T>
-double WorkerDataArray<T>::average(uint active_threads) const {
-  return sum(active_threads) / (double) active_threads;
+double WorkerDataArray<T>::average() const {
+  uint contributing_threads = 0;
+  for (uint i = 0; i < _length; ++i) {
+    if (get(i) != uninitialized()) {
+      contributing_threads++;
+    }
+  }
+  if (contributing_threads == 0) {
+    return 0.0;
+  }
+  return sum() / (double) contributing_threads;
 }
 
 template <typename T>
-T WorkerDataArray<T>::sum(uint active_threads) const {
-  T s = get(0);
-  for (uint i = 1; i < active_threads; ++i) {
-    s += get(i);
+T WorkerDataArray<T>::sum() const {
+  T s = 0;
+  for (uint i = 0; i < _length; ++i) {
+    if (get(i) != uninitialized()) {
+      s += get(i);
+    }
   }
   return s;
 }
 
 template <typename T>
-void WorkerDataArray<T>::clear() {
-  set_all(0);
-}
-
-template <typename T>
 void WorkerDataArray<T>::set_all(T value) {
   for (uint i = 0; i < _length; i++) {
     _data[i] = value;
@@ -104,27 +109,42 @@
 }
 
 template <class T>
-void WorkerDataArray<T>::print_summary_on(outputStream* out, uint active_threads, bool print_sum) const {
-  T max = get(0);
-  T min = max;
-  T sum = 0;
-  for (uint i = 1; i < active_threads; ++i) {
-    T value = get(i);
-    max = MAX2(max, value);
-    min = MIN2(min, value);
-    sum += value;
+void WorkerDataArray<T>::print_summary_on(outputStream* out, bool print_sum) const {
+  out->print("%-25s", title());
+  uint start = 0;
+  while (start < _length && get(start) == uninitialized()) {
+    start++;
   }
-  T diff = max - min;
-  double avg = sum / (double) active_threads;
-  WDAPrinter::summary(out, title(), min, avg, max, diff, sum, print_sum);
+  if (start < _length) {
+    T min = get(start);
+    T max = min;
+    T sum = 0;
+    uint contributing_threads = 0;
+    for (uint i = start; i < _length; ++i) {
+      T value = get(i);
+      if (value != uninitialized()) {
+        max = MAX2(max, value);
+        min = MIN2(min, value);
+        sum += value;
+        contributing_threads++;
+      }
+    }
+    T diff = max - min;
+    assert(contributing_threads != 0, "Must be since we found a used value for the start index");
+    double avg = sum / (double) contributing_threads;
+    WDAPrinter::summary(out, min, avg, max, diff, sum, print_sum);
+    out->print_cr(", Workers: %d", contributing_threads);
+  } else {
+    // No data for this phase.
+    out->print_cr(" skipped");
+  }
 }
 
 template <class T>
-void WorkerDataArray<T>::print_details_on(outputStream* out, uint active_threads) const {
-  WDAPrinter::details(this, out, active_threads);
+void WorkerDataArray<T>::print_details_on(outputStream* out) const {
+  WDAPrinter::details(this, out);
 }
 
-#ifndef PRODUCT
 template <typename T>
 void WorkerDataArray<T>::reset() {
   set_all(uninitialized());
@@ -133,27 +153,4 @@
   }
 }
 
-template <typename T>
-void WorkerDataArray<T>::verify(uint active_threads) const {
-  assert(active_threads <= _length, "Wrong number of active threads");
-  for (uint i = 0; i < active_threads; i++) {
-    assert(_data[i] != uninitialized(),
-           "Invalid data for worker %u in '%s'", i, _title);
-  }
-  if (_thread_work_items != NULL) {
-    _thread_work_items->verify(active_threads);
-  }
-}
-
-template <>
-inline size_t WorkerDataArray<size_t>::uninitialized() const {
-  return (size_t)-1;
-}
-
-template <>
-inline double WorkerDataArray<double>::uninitialized() const {
-  return -1.0;
-}
-#endif
-
 #endif // SHARE_VM_GC_G1_WORKERDATAARRAY_INLINE_HPP
--- a/hotspot/src/share/vm/gc/g1/youngList.cpp	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/gc/g1/youngList.cpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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/gcTaskManager.cpp	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/gc/parallel/gcTaskManager.cpp	Sat Apr 02 05:39:25 2016 +0200
@@ -30,6 +30,7 @@
 #include "logging/log.hpp"
 #include "memory/allocation.hpp"
 #include "memory/allocation.inline.hpp"
+#include "memory/resourceArea.hpp"
 #include "runtime/mutex.hpp"
 #include "runtime/mutexLocker.hpp"
 #include "runtime/orderAccess.inline.hpp"
@@ -404,12 +405,15 @@
     for (uint t = 0; t < workers(); t += 1) {
       set_thread(t, GCTaskThread::create(this, t, processor_assignment[t]));
     }
-    if (TraceGCTaskThread) {
-      tty->print("GCTaskManager::initialize: distribution:");
+    LogHandle(gc, task, thread) log;
+    if (log.is_trace()) {
+      ResourceMark rm;
+      outputStream* out = log.trace_stream();
+      out->print("GCTaskManager::initialize: distribution:");
       for (uint t = 0; t < workers(); t += 1) {
-        tty->print("  %u", processor_assignment[t]);
+        out->print("  %u", processor_assignment[t]);
       }
-      tty->cr();
+      out->cr();
     }
     FREE_C_HEAP_ARRAY(uint, processor_assignment);
   }
--- a/hotspot/src/share/vm/gc/parallel/gcTaskThread.cpp	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/gc/parallel/gcTaskThread.cpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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
@@ -107,14 +107,11 @@
   this->initialize_named_thread();
   // Bind yourself to your processor.
   if (processor_id() != GCTaskManager::sentinel_worker()) {
-    if (TraceGCTaskThread) {
-      tty->print_cr("GCTaskThread::run: "
-                    "  binding to processor %u", processor_id());
-    }
+    log_trace(gc, task, thread)("GCTaskThread::run: binding to processor %u", processor_id());
     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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/gc/parallel/mutableSpace.cpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/gc/parallel/parallelScavengeHeap.cpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/gc/parallel/psMarkSweep.cpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/gc/parallel/psOldGen.cpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/gc/parallel/psParallelCompact.cpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/gc/parallel/psPromotionManager.cpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/gc/parallel/psPromotionManager.hpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/gc/parallel/psScavenge.cpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/gc/parallel/psScavenge.hpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/gc/serial/defNewGeneration.cpp	Sat Apr 02 05:39:25 2016 +0200
@@ -460,11 +460,11 @@
                   (HeapWord*)_virtual_space.high());
     gch->barrier_set()->resize_covered_region(cmr);
 
-    log_debug(gc, heap, ergo)(
+    log_debug(gc, ergo, heap)(
         "New generation size " SIZE_FORMAT "K->" SIZE_FORMAT "K [eden=" SIZE_FORMAT "K,survivor=" SIZE_FORMAT "K]",
         new_size_before/K, _virtual_space.committed_size()/K,
         eden()->capacity()/K, from()->capacity()/K);
-    log_trace(gc, heap, ergo)(
+    log_trace(gc, ergo, heap)(
         "  [allowed " SIZE_FORMAT "K extra for %d threads]",
           thread_increase_size/K, threads_count);
       }
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/gc/serial/genMarkSweep.cpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/gc/shared/barrierSet.cpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/gc/shared/barrierSet.inline.hpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/gc/shared/cardGeneration.cpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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/cardTableModRefBS.cpp	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/gc/shared/cardTableModRefBS.cpp	Sat Apr 02 05:39:25 2016 +0200
@@ -500,16 +500,14 @@
     bool failed = (val_equals) ? (curr_val != val) : (curr_val == val);
     if (failed) {
       if (!failures) {
-        tty->cr();
-        tty->print_cr("== CT verification failed: [" INTPTR_FORMAT "," INTPTR_FORMAT "]", p2i(start), p2i(end));
-        tty->print_cr("==   %sexpecting value: %d",
-                      (val_equals) ? "" : "not ", val);
+        log_error(gc, verify)("== CT verification failed: [" INTPTR_FORMAT "," INTPTR_FORMAT "]", p2i(start), p2i(end));
+        log_error(gc, verify)("==   %sexpecting value: %d", (val_equals) ? "" : "not ", val);
         failures = true;
       }
-      tty->print_cr("==   card " PTR_FORMAT " [" PTR_FORMAT "," PTR_FORMAT "], "
-                    "val: %d", p2i(curr), p2i(addr_for(curr)),
-                    p2i((HeapWord*) (((size_t) addr_for(curr)) + card_size)),
-                    (int) curr_val);
+      log_error(gc, verify)("==   card " PTR_FORMAT " [" PTR_FORMAT "," PTR_FORMAT "], val: %d",
+                            p2i(curr), p2i(addr_for(curr)),
+                            p2i((HeapWord*) (((size_t) addr_for(curr)) + card_size)),
+                            (int) curr_val);
     }
   }
   guarantee(!failures, "there should not have been any failures");
--- a/hotspot/src/share/vm/gc/shared/cardTableModRefBS.hpp	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/gc/shared/cardTableModRefBS.hpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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
@@ -89,14 +89,6 @@
   MemRegion _guard_region;
 
  protected:
-  // Initialization utilities; covered_words is the size of the covered region
-  // in, um, words.
-  inline size_t cards_required(size_t covered_words) {
-    // Add one for a guard card, used to detect errors.
-    const size_t words = align_size_up(covered_words, card_size_in_words);
-    return words / card_size_in_words + 1;
-  }
-
   inline size_t compute_byte_map_size();
 
   // Finds and return the index of the region, if any, to which the given
@@ -172,6 +164,14 @@
 
   bool has_write_ref_pre_barrier() { return false; }
 
+  // Initialization utilities; covered_words is the size of the covered region
+  // in, um, words.
+  inline size_t cards_required(size_t covered_words) {
+    // Add one for a guard card, used to detect errors.
+    const size_t words = align_size_up(covered_words, card_size_in_words);
+    return words / card_size_in_words + 1;
+  }
+
 protected:
 
   CardTableModRefBS(MemRegion whole_heap, const BarrierSet::FakeRtti& fake_rtti);
--- a/hotspot/src/share/vm/gc/shared/cardTableRS.cpp	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/gc/shared/cardTableRS.cpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/gc/shared/collectedHeap.cpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/gc/shared/collectedHeap.hpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/gc/shared/collectorPolicy.cpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/gc/shared/concurrentGCThread.cpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/gc/shared/concurrentGCThread.hpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/gc/shared/gcCause.cpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/gc/shared/gcCause.hpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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/gcLocker.cpp	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/gc/shared/gcLocker.cpp	Sat Apr 02 05:39:25 2016 +0200
@@ -51,10 +51,10 @@
       }
     }
     if (_jni_lock_count != count) {
-      tty->print_cr("critical counts don't match: %d != %d", _jni_lock_count, count);
+      log_error(gc, verify)("critical counts don't match: %d != %d", _jni_lock_count, count);
       for (JavaThread* thr = Threads::first(); thr; thr = thr->next()) {
         if (thr->in_critical()) {
-          tty->print_cr(INTPTR_FORMAT " in_critical %d", p2i(thr), thr->in_critical());
+          log_error(gc, verify)(INTPTR_FORMAT " in_critical %d", p2i(thr), thr->in_critical());
         }
       }
     }
--- a/hotspot/src/share/vm/gc/shared/gcTrace.cpp	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/gc/shared/gcTrace.cpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/gc/shared/gcTrace.hpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/gc/shared/gcTraceTime.inline.hpp	Sat Apr 02 05:39:25 2016 +0200
@@ -33,31 +33,33 @@
 #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)"
 
 template <LogLevelType Level, LogTagType T0, LogTagType T1, LogTagType T2, LogTagType T3, LogTagType T4, LogTagType GuardTag >
 void GCTraceTimeImpl<Level, T0, T1, T2, T3, T4, GuardTag>::log_start(jlong start_counter) {
-  if (Log<PREFIX_LOG_TAG(start), T0, T1, T2, T3>::is_level(Level)) {
+  STATIC_ASSERT(T0 != LogTag::__NO_TAG); // Need some tag to log on.
+  STATIC_ASSERT(T4 == LogTag::__NO_TAG); // Need to leave at least the last tag for the "start" tag in log_start()
+
+  // Get log with start tag appended (replace first occurrence of NO_TAG)
+  const LogTagType start_tag = PREFIX_LOG_TAG(start);
+  const LogTagType no_tag = PREFIX_LOG_TAG(_NO_TAG);
+  Log<T0,
+      T1 == no_tag ? start_tag : T1,
+      T1 != no_tag && T2 == no_tag ? start_tag : T2,
+      T2 != no_tag && T3 == no_tag ? start_tag : T3,
+      T3 != no_tag && T4 == no_tag ? start_tag : T4
+    > log;
+
+  if (log.is_level(Level)) {
     FormatBuffer<> start_msg("%s", _title);
     if (_gc_cause != GCCause::_no_gc) {
       start_msg.append(" (%s)", GCCause::to_string(_gc_cause));
     }
     start_msg.append(" (%.3fs)", TimeHelper::counter_to_seconds(start_counter));
     // Make sure to put the "start" tag last in the tag set
-    STATIC_ASSERT(T0 != LogTag::__NO_TAG); // Need some tag to log on.
-    STATIC_ASSERT(T4 == LogTag::__NO_TAG); // Need to leave at least the last tag for the "start" tag in log_start()
-    if (T1 == LogTag::__NO_TAG) {
-      Log<T0, PREFIX_LOG_TAG(start)>::template write<Level>("%s", start_msg.buffer());
-    } else if (T2 == LogTag::__NO_TAG) {
-      Log<T0, T1, PREFIX_LOG_TAG(start)>::template write<Level>("%s", start_msg.buffer());
-    } else if (T3 == LogTag::__NO_TAG) {
-      Log<T0, T1, T2, PREFIX_LOG_TAG(start)>::template write<Level>("%s", start_msg.buffer());
-    } else {
-      Log<T0, T1, T2, T3, PREFIX_LOG_TAG(start)>::template write<Level>("%s", start_msg.buffer());
-    }
+    log.template write<Level>("%s", start_msg.buffer());
   }
 }
 
--- a/hotspot/src/share/vm/gc/shared/genCollectedHeap.cpp	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/gc/shared/genCollectedHeap.cpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/gc/shared/genCollectedHeap.hpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/gc/shared/generation.hpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/gc/shared/plab.cpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/gc/shared/preservedMarks.cpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/gc/shared/preservedMarks.hpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/gc/shared/referenceProcessor.cpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/gc/shared/referenceProcessor.hpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/gc/shared/spaceDecorator.cpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/gc/shared/taskqueue.hpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/gc/shared/taskqueue.inline.hpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/gc/shared/threadLocalAllocBuffer.inline.hpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/gc/shared/vmGCOperations.cpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/gc/shared/vmGCOperations.hpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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/gc/shared/workgroup.cpp	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/gc/shared/workgroup.cpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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
@@ -40,12 +40,7 @@
 // initialization of the workers and report such to the
 // caller.
 bool AbstractWorkGang::initialize_workers() {
-
-  if (TraceWorkGang) {
-    tty->print_cr("Constructing work gang %s with %d threads",
-                  name(),
-                  total_workers());
-  }
+  log_develop_trace(gc, workgang)("Constructing work gang %s with %u threads", name(), total_workers());
   _workers = NEW_C_HEAP_ARRAY(AbstractGangWorker*, total_workers(), mtInternal);
   if (_workers == NULL) {
     vm_exit_out_of_memory(0, OOM_MALLOC_ERROR, "Cannot create GangWorker array.");
@@ -279,10 +274,7 @@
   this->initialize_named_thread();
   assert(_gang != NULL, "No gang to run in");
   os::set_priority(this, NearMaxPriority);
-  if (TraceWorkGang) {
-    tty->print_cr("Running gang worker for gang %s id %u",
-                  gang()->name(), id());
-  }
+  log_develop_trace(gc, workgang)("Running gang worker for gang %s id %u", gang()->name(), id());
   // The VM thread should not execute here because MutexLocker's are used
   // as (opposed to MutexLockerEx's).
   assert(!Thread::current()->is_VM_thread(), "VM thread should not be part"
@@ -311,27 +303,14 @@
   gang()->dispatcher()->worker_done_with_task();
 }
 
-void GangWorker::print_task_started(WorkData data) {
-  if (TraceWorkGang) {
-    tty->print_cr("Running work gang %s task %s worker %u", name(), data._task->name(), data._worker_id);
-  }
-}
+void GangWorker::run_task(WorkData data) {
+  GCIdMark gc_id_mark(data._task->gc_id());
+  log_develop_trace(gc, workgang)("Running work gang: %s task: %s worker: %u", name(), data._task->name(), data._worker_id);
 
-void GangWorker::print_task_done(WorkData data) {
-  if (TraceWorkGang) {
-    tty->print_cr("\nFinished work gang %s task %s worker %u", name(), data._task->name(), data._worker_id);
-    Thread* me = Thread::current();
-    tty->print_cr("  T: " PTR_FORMAT "  VM_thread: %d", p2i(me), me->is_VM_thread());
-  }
-}
-
-void GangWorker::run_task(WorkData data) {
-  print_task_started(data);
-
-  GCIdMark gc_id_mark(data._task->gc_id());
   data._task->work(data._worker_id);
 
-  print_task_done(data);
+  log_develop_trace(gc, workgang)("Finished work gang: %s task: %s worker: %u thread: " PTR_FORMAT,
+                                  name(), data._task->name(), data._worker_id, p2i(Thread::current()));
 }
 
 void GangWorker::loop() {
--- a/hotspot/src/share/vm/gc/shared/workgroup.hpp	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/gc/shared/workgroup.hpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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
@@ -152,7 +152,7 @@
     _active_workers = MAX2(1U, _active_workers);
     assert(UseDynamicNumberOfGCThreads || _active_workers == _total_workers,
            "Unless dynamic should use total workers");
-    log_info(gc, task)("GC Workers: %d", _active_workers);
+    log_info(gc, task)("GC Workers: using %d out of %d", _active_workers, _total_workers);
   }
 
   // Return the Ith worker.
@@ -234,9 +234,6 @@
   void run_task(WorkData work);
   void signal_task_done();
 
-  void print_task_started(WorkData data);
-  void print_task_done(WorkData data);
-
   WorkGang* gang() const { return (WorkGang*)_gang; }
 };
 
--- a/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/interpreter/cppInterpreter.cpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/interpreter/interpreterRuntime.hpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/interpreter/templateInterpreter.cpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/interpreter/templateTable.cpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/jvmci/jvmciCompilerToVM.cpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/logging/log.cpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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
@@ -23,6 +23,24 @@
  */
 
 #include "precompiled.hpp"
+#include "logging/log.hpp"
+#include "memory/allocation.inline.hpp"
+
+void LogWriteHelper::write_large(LogTagSet& lts,
+                                 LogLevelType level,
+                                 const char* prefix,
+                                 size_t prefix_len,
+                                 size_t msg_len,
+                                 const char* fmt,
+                                 va_list args) {
+  size_t newbuf_len = prefix_len + msg_len + 1;
+  char* newbuf = NEW_C_HEAP_ARRAY(char, newbuf_len, mtLogging);
+  memcpy(newbuf, prefix, prefix_len);
+  int ret = os::log_vsnprintf(newbuf + prefix_len, newbuf_len - prefix_len, fmt, args);
+  assert(ret >= 0, "Log message buffer issue");
+  lts.log(level, newbuf);
+  FREE_C_HEAP_ARRAY(char, newbuf);
+}
 
 /////////////// Unit tests ///////////////
 
@@ -33,66 +51,6 @@
 #include "logging/logOutput.hpp"
 #include "memory/resourceArea.hpp"
 
-void Test_log_length() {
-  remove("loglengthoutput.txt");
-
-  // Write long message to output file
-  ResourceMark rm;
-  LogHandle(logging) log;
-  bool success = LogConfiguration::parse_log_arguments("loglengthoutput.txt", "logging=trace",
-    NULL, NULL, log.error_stream());
-  assert(success, "test unable to configure logging");
-  log.trace("01:1234567890-"
-            "02:1234567890-"
-            "03:1234567890-"
-            "04:1234567890-"
-            "05:1234567890-"
-            "06:1234567890-"
-            "07:1234567890-"
-            "08:1234567890-"
-            "09:1234567890-"
-            "10:1234567890-"
-            "11:1234567890-"
-            "12:1234567890-"
-            "13:1234567890-"
-            "14:1234567890-"
-            "15:1234567890-"
-            "16:1234567890-"
-            "17:1234567890-"
-            "18:1234567890-"
-            "19:1234567890-"
-            "20:1234567890-"
-            "21:1234567890-"
-            "22:1234567890-"
-            "23:1234567890-"
-            "24:1234567890-"
-            "25:1234567890-"
-            "26:1234567890-"
-            "27:1234567890-"
-            "28:1234567890-"
-            "29:1234567890-"
-            "30:1234567890-"
-            "31:1234567890-"
-            "32:1234567890-"
-            "33:1234567890-"
-            "34:1234567890-"
-            "35:1234567890-"
-            "36:1234567890-"
-            "37:1234567890-");
-  LogConfiguration::parse_log_arguments("loglengthoutput.txt", "all=off",
-    NULL, NULL, log.error_stream());
-
-  // Look for end of message in output file
-  FILE* fp = fopen("loglengthoutput.txt", "r");
-  assert(fp, "File read error");
-  char output[600];
-  if (fgets(output, 600, fp) != NULL) {
-    assert(strstr(output, "37:1234567890-"), "logging print size error");
-  }
-  fclose(fp);
-  remove("loglengthoutput.txt");
-}
-
 #define assert_str_eq(s1, s2) \
   assert(strcmp(s1, s2) == 0, "Expected '%s' to equal '%s'", s1, s2)
 
@@ -102,14 +60,67 @@
 #define assert_char_not_in(c, s) \
   assert(strchr(s, c) == NULL, "Expected '%s' to *not* contain character '%c'", s, c)
 
+class TestLogFile {
+ private:
+  char file_name[256];
+
+  void set_name(const char* test_name) {
+    const char* tmpdir = os::get_temp_directory();
+    int pos = jio_snprintf(file_name, sizeof(file_name), "%s%svmtest.%s.%d.log", tmpdir, os::file_separator(), test_name, os::current_process_id());
+    assert(pos > 0, "too small log file name buffer");
+    assert((size_t)pos < sizeof(file_name), "too small log file name buffer");
+  }
+
+ public:
+  TestLogFile(const char* test_name) {
+    set_name(test_name);
+    remove(name());
+  }
+
+  ~TestLogFile() {
+    remove(name());
+  }
+
+  const char* name() {
+    return file_name;
+  }
+};
+
+class TestLogSavedConfig {
+ private:
+  char* _saved_config;
+  char* _new_output;
+  LogHandle(logging) _log;
+ public:
+  TestLogSavedConfig(const char* apply_output = NULL, const char* apply_setting = NULL) : _new_output(0) {
+    _saved_config = os::strdup_check_oom(LogOutput::Stdout->config_string());
+    bool success = LogConfiguration::parse_log_arguments("stdout", "all=off", NULL, NULL, _log.error_stream());
+    assert(success, "test unable to turn all off");
+
+    if (apply_output) {
+      _new_output = os::strdup_check_oom(apply_output);
+      bool success = LogConfiguration::parse_log_arguments(_new_output, apply_setting,  NULL, NULL, _log.error_stream());
+      assert(success, "test unable to apply test log configuration");
+    }
+  }
+
+  ~TestLogSavedConfig() {
+    if (_new_output) {
+      bool success = LogConfiguration::parse_log_arguments(_new_output, "all=off", NULL, NULL, _log.error_stream());
+      assert(success, "test unable to turn all off");
+      os::free(_new_output);
+    }
+
+    bool success = LogConfiguration::parse_log_arguments("stdout", _saved_config, NULL, NULL, _log.error_stream());
+    assert(success, "test unable to restore log configuration");
+    os::free(_saved_config);
+  }
+};
+
 void Test_configure_stdout() {
   ResourceMark rm;
-  LogHandle(logging) log;
   LogOutput* stdoutput = LogOutput::Stdout;
-
-  // Save current stdout config and clear it
-  char* saved_config = os::strdup_check_oom(stdoutput->config_string());
-  LogConfiguration::parse_log_arguments("stdout", "all=off", NULL, NULL, log.error_stream());
+  TestLogSavedConfig tlsc;
 
   // Enable 'logging=info', verifying it has been set
   LogConfiguration::configure_stdout(LogLevel::Info, true, LOG_TAGS(logging));
@@ -131,9 +142,129 @@
   LogConfiguration::configure_stdout(LogLevel::Off, false, LOG_TAGS(gc));
   LogConfiguration::configure_stdout(LogLevel::Off, true, LOG_TAGS(logging));
   assert_str_eq("all=off", stdoutput->config_string());
+}
 
-  // Restore saved configuration
-  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;
+
+  TestLogSavedConfig log_cfg("stdout", "logging+test=trace");
+
+  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)");
+
+  // We need to renable stderr error logging since "disable_logging" disable it all.
+  // TestLogSavedConfig log_cfg will only renable stdout for us.
+  LogConfiguration::parse_log_arguments("stderr", "all=warning", NULL, NULL, log.error_stream());
+  assert(Test_logconfiguration_subscribe_triggered == 4, "subscription not triggered (3)");
+}
+
+#define LOG_PREFIX_STR "THE_PREFIX "
+#define LOG_LINE_STR "a log line"
+
+size_t Test_log_prefix_prefixer(char* buf, size_t len) {
+  int ret = jio_snprintf(buf, len, LOG_PREFIX_STR);
+  assert(ret > 0, "Failed to print prefix. Log buffer too small?");
+  return (size_t) ret;
+}
+
+void Test_log_prefix() {
+  ResourceMark rm;
+  TestLogFile log_file("log_prefix");
+  TestLogSavedConfig log_cfg(log_file.name(), "logging+test=trace");
+
+  log_trace(logging, test)(LOG_LINE_STR);
+
+  FILE* fp = fopen(log_file.name(), "r");
+  assert(fp, "File read error");
+  char output[1024];
+  if (fgets(output, 1024, fp) != NULL) {
+    assert(strstr(output, LOG_PREFIX_STR LOG_LINE_STR), "logging prefix error");
+  }
+  fclose(fp);
 }
+
+void Test_log_big() {
+  char big_msg[4096] = {0};
+  char Xchar = '~';
+
+  ResourceMark rm;
+  TestLogFile log_file("log_big");
+  TestLogSavedConfig log_cfg(log_file.name(), "logging+test=trace");
+
+  memset(big_msg, Xchar, sizeof(big_msg) - 1);
+
+  log_trace(logging, test)("%s", big_msg);
+
+  FILE* fp = fopen(log_file.name(), "r");
+  assert(fp, "File read error");
+  char output[sizeof(big_msg)+128 /*decorators*/ ];
+  if (fgets(output, sizeof(output), fp) != NULL) {
+    assert(strstr(output, LOG_PREFIX_STR), "logging prefix error");
+    size_t count = 0;
+    for (size_t ps = 0 ; output[ps + count] != '\0'; output[ps + count] == Xchar ? count++ : ps++);
+    assert(count == (sizeof(big_msg) - 1) , "logging msg error");
+  }
+  fclose(fp);
+}
+
+void Test_logtagset_duplicates() {
+  for (LogTagSet* ts = LogTagSet::first(); ts != NULL; ts = ts->next()) {
+    char ts_name[512];
+    ts->label(ts_name, sizeof(ts_name), ",");
+
+    // verify that NO_TAG is never followed by a real tag
+    for (size_t i = 0; i < LogTag::MaxTags; i++) {
+      if (ts->tag(i) == LogTag::__NO_TAG) {
+        for (i++; i < LogTag::MaxTags; i++) {
+          assert(ts->tag(i) == LogTag::__NO_TAG,
+                 "NO_TAG was followed by a real tag (%s) in tagset %s",
+                 LogTag::name(ts->tag(i)), ts_name);
+        }
+      }
+    }
+
+    // verify that there are no duplicate tagsets (same tags in different order)
+    for (LogTagSet* other = ts->next(); other != NULL; other = other->next()) {
+      if (ts->ntags() != other->ntags()) {
+        continue;
+      }
+      bool equal = true;
+      for (size_t i = 0; i < ts->ntags(); i++) {
+        LogTagType tag = ts->tag(i);
+        if (!other->contains(tag)) {
+          equal = false;
+          break;
+        }
+      }
+      // Since tagsets are implemented using template arguments, using both of
+      // the (logically equivalent) tagsets (t1, t2) and (t2, t1) somewhere will
+      // instantiate two different LogTagSetMappings. This causes multiple
+      // tagset instances to be created for the same logical set. We want to
+      // avoid this to save time, memory and prevent any confusion around it.
+      if (equal) {
+        char other_name[512];
+        other->label(other_name, sizeof(other_name), ",");
+        assert(false, "duplicate LogTagSets found: '%s' vs '%s' "
+               "(tags must always be specified in the same order for each tagset)",
+               ts_name, other_name);
+      }
+    }
+  }
+}
+
 #endif // PRODUCT
--- a/hotspot/src/share/vm/logging/log.hpp	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/logging/log.hpp	Sat Apr 02 05:39:25 2016 +0200
@@ -29,7 +29,6 @@
 #include "logging/logTagSet.hpp"
 #include "logging/logTag.hpp"
 #include "memory/allocation.hpp"
-#include "memory/allocation.inline.hpp"
 #include "runtime/os.hpp"
 #include "utilities/debug.hpp"
 #include "utilities/ostream.hpp"
@@ -87,6 +86,26 @@
 //
 #define LogHandle(...)  Log<LOG_TAGS(__VA_ARGS__)>
 
+template <LogTagType T0, LogTagType T1, LogTagType T2, LogTagType T3, LogTagType T4, LogTagType GuardTag>
+class Log;
+
+// Non-template helper class for implementing write-slowpath in cpp
+class LogWriteHelper : AllStatic {
+ private:
+
+  template <LogTagType T0, LogTagType T1, LogTagType T2, LogTagType T3, LogTagType T4, LogTagType GuardTag>
+  friend class Log;
+
+  ATTRIBUTE_PRINTF(6, 0)
+  static void write_large(LogTagSet& lts,
+                          LogLevelType level,
+                          const char* prefix,
+                          size_t prefix_len,
+                          size_t msg_len,
+                          const char* fmt,
+                          va_list args);
+};
+
 template <LogTagType T0, LogTagType T1 = LogTag::__NO_TAG, LogTagType T2 = LogTag::__NO_TAG, LogTagType T3 = LogTag::__NO_TAG,
           LogTagType T4 = LogTag::__NO_TAG, LogTagType GuardTag = LogTag::__NO_TAG>
 class Log VALUE_OBJ_CLASS_SPEC {
@@ -133,21 +152,14 @@
     // Check that string fits in buffer; resize buffer if necessary
     int ret = os::log_vsnprintf(buf + prefix_len, sizeof(buf) - prefix_len, fmt, args);
     assert(ret >= 0, "Log message buffer issue");
-    if ((size_t)ret >= sizeof(buf)) {
-      size_t newbuf_len = prefix_len + ret + 1;
-      char* newbuf = NEW_C_HEAP_ARRAY(char, newbuf_len, mtLogging);
-      prefix_len = LogPrefix<T0, T1, T2, T3, T4>::prefix(newbuf, newbuf_len);
-      ret = os::log_vsnprintf(newbuf + prefix_len, newbuf_len - prefix_len, fmt, saved_args);
-      assert(ret >= 0, "Log message buffer issue");
-      puts(level, newbuf);
-      FREE_C_HEAP_ARRAY(char, newbuf);
+    size_t msg_len = ret;
+    LogTagSet& lts = LogTagSetMapping<T0, T1, T2, T3, T4>::tagset();
+    if (msg_len >= sizeof(buf)) {
+      LogWriteHelper::write_large(lts, level, buf, prefix_len, msg_len, fmt, saved_args);
     } else {
-      puts(level, buf);
+      lts.log(level, buf);
     }
-  }
-
-  static void puts(LogLevelType level, const char* string) {
-    LogTagSetMapping<T0, T1, T2, T3, T4>::tagset().log(level, string);
+    va_end(saved_args);
   }
 
 #define LOG_LEVEL(level, name) ATTRIBUTE_PRINTF(2, 0) \
--- a/hotspot/src/share/vm/logging/logConfiguration.cpp	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/logging/logConfiguration.cpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/logging/logConfiguration.hpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/logging/logFileOutput.cpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/logging/logPrefix.hpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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
@@ -38,23 +38,30 @@
 // List of prefixes for specific tags and/or tagsets.
 // Syntax: LOG_PREFIX(<name of prefixer function>, LOG_TAGS(<chosen log tags>))
 // Where the prefixer function matches the following signature: size_t (*)(char*, size_t)
+
+// Prefix function for internal vm test
+DEBUG_ONLY(size_t Test_log_prefix_prefixer(char* buf, size_t len);)
+
 #define LOG_PREFIX_LIST \
   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, humongous)) \
   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)) \
@@ -70,7 +77,9 @@
   LOG_PREFIX(GCId::print_prefix, LOG_TAGS(gc, task, start)) \
   LOG_PREFIX(GCId::print_prefix, LOG_TAGS(gc, task, stats)) \
   LOG_PREFIX(GCId::print_prefix, LOG_TAGS(gc, task, time)) \
-  LOG_PREFIX(GCId::print_prefix, LOG_TAGS(gc, tlab))
+  DEBUG_ONLY(LOG_PREFIX(Test_log_prefix_prefixer, LOG_TAGS(logging, test))) \
+  LOG_PREFIX(GCId::print_prefix, LOG_TAGS(gc, tlab)) \
+  LOG_PREFIX(GCId::print_prefix, LOG_TAGS(gc, workgang))
 
 
 // The empty prefix, used when there's no prefix defined.
--- a/hotspot/src/share/vm/logging/logTag.hpp	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/logging/logTag.hpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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"
 
@@ -33,6 +34,7 @@
 #define LOG_TAG_LIST \
   LOG_TAG(alloc) \
   LOG_TAG(age) \
+  LOG_TAG(arguments) \
   LOG_TAG(barrier) \
   LOG_TAG(biasedlocking) \
   LOG_TAG(bot) \
@@ -45,6 +47,7 @@
   LOG_TAG(classunload) /* Trace unloading of classes */ \
   LOG_TAG(classpath) \
   LOG_TAG(compaction) \
+  LOG_TAG(constraints) \
   LOG_TAG(cpu) \
   LOG_TAG(cset) \
   LOG_TAG(defaultmethods) \
@@ -64,32 +67,41 @@
   LOG_TAG(metaspace) \
   LOG_TAG(modules) \
   LOG_TAG(monitorinflation) \
+  LOG_TAG(monitormismatch) \
   LOG_TAG(os) \
   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) \
+  DEBUG_ONLY(LOG_TAG(test)) \
   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(workgang) \
+  LOG_TAG_LIST_EXT
 
 #define PREFIX_LOG_TAG(T) (LogTag::_##T)
 
--- a/hotspot/src/share/vm/logging/logTagSet.hpp	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/logging/logTagSet.hpp	Sat Apr 02 05:39:25 2016 +0200
@@ -68,6 +68,10 @@
     return _ntags;
   }
 
+  LogTagType tag(size_t idx) const {
+    return _tag[idx];
+  }
+
   bool contains(LogTagType tag) const {
     for (size_t i = 0; _tag[i] != LogTag::__NO_TAG; i++) {
       if (tag == _tag[i]) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/logging/logTag_ext.hpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/memory/allocation.cpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/memory/allocation.hpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/memory/allocation.inline.hpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/memory/filemap.cpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/memory/iterator.hpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/memory/metaspace.cpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/memory/metaspaceShared.cpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/memory/universe.cpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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();
 
@@ -880,6 +878,57 @@
   return UnscaledNarrowOop;
 }
 
+void initialize_known_method(LatestMethodCache* method_cache,
+                             InstanceKlass* ik,
+                             const char* method,
+                             Symbol* signature,
+                             bool is_static, TRAPS)
+{
+  TempNewSymbol name = SymbolTable::new_symbol(method, CHECK);
+  Method* m = NULL;
+  // The klass must be linked before looking up the method.
+  if (!ik->link_class_or_fail(THREAD) ||
+      ((m = ik->find_method(name, signature)) == NULL) ||
+      is_static != m->is_static()) {
+    ResourceMark rm(THREAD);
+    // NoSuchMethodException doesn't actually work because it tries to run the
+    // <init> function before java_lang_Class is linked. Print error and exit.
+    vm_exit_during_initialization(err_msg("Unable to link/verify %s.%s method",
+                                 ik->name()->as_C_string(), method));
+  }
+  method_cache->init(ik, m);
+}
+
+void Universe::initialize_known_methods(TRAPS) {
+  // Set up static method for registering finalizers
+  initialize_known_method(_finalizer_register_cache,
+                          SystemDictionary::Finalizer_klass(),
+                          "register",
+                          vmSymbols::object_void_signature(), true, CHECK);
+
+  initialize_known_method(_throw_illegal_access_error_cache,
+                          SystemDictionary::internal_Unsafe_klass(),
+                          "throwIllegalAccessError",
+                          vmSymbols::void_method_signature(), true, CHECK);
+
+  // Set up method for registering loaded classes in class loader vector
+  initialize_known_method(_loader_addClass_cache,
+                          SystemDictionary::ClassLoader_klass(),
+                          "addClass",
+                          vmSymbols::class_void_signature(), false, CHECK);
+
+  // Set up method for checking protection domain
+  initialize_known_method(_pd_implies_cache,
+                          SystemDictionary::ProtectionDomain_klass(),
+                          "impliesCreateAccessControlContext",
+                          vmSymbols::void_boolean_signature(), false, CHECK);
+
+  // Set up method for stack walking
+  initialize_known_method(_do_stack_walk_cache,
+                          SystemDictionary::AbstractStackWalker_klass(),
+                          "doStackWalk",
+                          vmSymbols::doStackWalk_signature(), false, CHECK);
+}
 
 void universe2_init() {
   EXCEPTION_MARK;
@@ -908,46 +957,46 @@
   HandleMark hm(THREAD);
   Klass* k;
   instanceKlassHandle k_h;
-    // Setup preallocated empty java.lang.Class array
-    Universe::_the_empty_class_klass_array = oopFactory::new_objArray(SystemDictionary::Class_klass(), 0, CHECK_false);
+  // Setup preallocated empty java.lang.Class array
+  Universe::_the_empty_class_klass_array = oopFactory::new_objArray(SystemDictionary::Class_klass(), 0, CHECK_false);
 
-    // Setup preallocated OutOfMemoryError errors
-    k = SystemDictionary::resolve_or_fail(vmSymbols::java_lang_OutOfMemoryError(), true, CHECK_false);
-    k_h = instanceKlassHandle(THREAD, k);
-    Universe::_out_of_memory_error_java_heap = k_h->allocate_instance(CHECK_false);
-    Universe::_out_of_memory_error_metaspace = k_h->allocate_instance(CHECK_false);
-    Universe::_out_of_memory_error_class_metaspace = k_h->allocate_instance(CHECK_false);
-    Universe::_out_of_memory_error_array_size = k_h->allocate_instance(CHECK_false);
-    Universe::_out_of_memory_error_gc_overhead_limit =
-      k_h->allocate_instance(CHECK_false);
-    Universe::_out_of_memory_error_realloc_objects = k_h->allocate_instance(CHECK_false);
+  // Setup preallocated OutOfMemoryError errors
+  k = SystemDictionary::resolve_or_fail(vmSymbols::java_lang_OutOfMemoryError(), true, CHECK_false);
+  k_h = instanceKlassHandle(THREAD, k);
+  Universe::_out_of_memory_error_java_heap = k_h->allocate_instance(CHECK_false);
+  Universe::_out_of_memory_error_metaspace = k_h->allocate_instance(CHECK_false);
+  Universe::_out_of_memory_error_class_metaspace = k_h->allocate_instance(CHECK_false);
+  Universe::_out_of_memory_error_array_size = k_h->allocate_instance(CHECK_false);
+  Universe::_out_of_memory_error_gc_overhead_limit =
+    k_h->allocate_instance(CHECK_false);
+  Universe::_out_of_memory_error_realloc_objects = k_h->allocate_instance(CHECK_false);
 
-    // Setup preallocated cause message for delayed StackOverflowError
-    if (StackReservedPages > 0) {
-      Universe::_delayed_stack_overflow_error_message =
-        java_lang_String::create_oop_from_str("Delayed StackOverflowError due to ReservedStackAccess annotated method", CHECK_false);
-    }
+  // Setup preallocated cause message for delayed StackOverflowError
+  if (StackReservedPages > 0) {
+    Universe::_delayed_stack_overflow_error_message =
+      java_lang_String::create_oop_from_str("Delayed StackOverflowError due to ReservedStackAccess annotated method", CHECK_false);
+  }
 
-    // Setup preallocated NullPointerException
-    // (this is currently used for a cheap & dirty solution in compiler exception handling)
-    k = SystemDictionary::resolve_or_fail(vmSymbols::java_lang_NullPointerException(), true, CHECK_false);
-    Universe::_null_ptr_exception_instance = InstanceKlass::cast(k)->allocate_instance(CHECK_false);
-    // Setup preallocated ArithmeticException
-    // (this is currently used for a cheap & dirty solution in compiler exception handling)
-    k = SystemDictionary::resolve_or_fail(vmSymbols::java_lang_ArithmeticException(), true, CHECK_false);
-    Universe::_arithmetic_exception_instance = InstanceKlass::cast(k)->allocate_instance(CHECK_false);
-    // Virtual Machine Error for when we get into a situation we can't resolve
-    k = SystemDictionary::resolve_or_fail(
-      vmSymbols::java_lang_VirtualMachineError(), true, CHECK_false);
-    bool linked = InstanceKlass::cast(k)->link_class_or_fail(CHECK_false);
-    if (!linked) {
-      tty->print_cr("Unable to link/verify VirtualMachineError class");
-      return false; // initialization failed
-    }
-    Universe::_virtual_machine_error_instance =
-      InstanceKlass::cast(k)->allocate_instance(CHECK_false);
+  // Setup preallocated NullPointerException
+  // (this is currently used for a cheap & dirty solution in compiler exception handling)
+  k = SystemDictionary::resolve_or_fail(vmSymbols::java_lang_NullPointerException(), true, CHECK_false);
+  Universe::_null_ptr_exception_instance = InstanceKlass::cast(k)->allocate_instance(CHECK_false);
+  // Setup preallocated ArithmeticException
+  // (this is currently used for a cheap & dirty solution in compiler exception handling)
+  k = SystemDictionary::resolve_or_fail(vmSymbols::java_lang_ArithmeticException(), true, CHECK_false);
+  Universe::_arithmetic_exception_instance = InstanceKlass::cast(k)->allocate_instance(CHECK_false);
+  // Virtual Machine Error for when we get into a situation we can't resolve
+  k = SystemDictionary::resolve_or_fail(
+    vmSymbols::java_lang_VirtualMachineError(), true, CHECK_false);
+  bool linked = InstanceKlass::cast(k)->link_class_or_fail(CHECK_false);
+  if (!linked) {
+    tty->print_cr("Unable to link/verify VirtualMachineError class");
+    return false; // initialization failed
+  }
+  Universe::_virtual_machine_error_instance =
+    InstanceKlass::cast(k)->allocate_instance(CHECK_false);
 
-    Universe::_vm_exception = InstanceKlass::cast(k)->allocate_instance(CHECK_false);
+  Universe::_vm_exception = InstanceKlass::cast(k)->allocate_instance(CHECK_false);
 
   if (!DumpSharedSpaces) {
     // These are the only Java fields that are currently set during shared space dumping.
@@ -988,71 +1037,7 @@
     Universe::_preallocated_out_of_memory_error_avail_count = (jint)len;
   }
 
-
-  // Setup static method for registering finalizers
-  // The finalizer klass must be linked before looking up the method, in
-  // case it needs to get rewritten.
-  SystemDictionary::Finalizer_klass()->link_class(CHECK_false);
-  Method* m = SystemDictionary::Finalizer_klass()->find_method(
-                                  vmSymbols::register_method_name(),
-                                  vmSymbols::register_method_signature());
-  if (m == NULL || !m->is_static()) {
-    tty->print_cr("Unable to link/verify Finalizer.register method");
-    return false; // initialization failed (cannot throw exception yet)
-  }
-  Universe::_finalizer_register_cache->init(
-    SystemDictionary::Finalizer_klass(), m);
-
-  SystemDictionary::internal_Unsafe_klass()->link_class(CHECK_false);
-  m = SystemDictionary::internal_Unsafe_klass()->find_method(
-                                  vmSymbols::throwIllegalAccessError_name(),
-                                  vmSymbols::void_method_signature());
-  if (m != NULL && !m->is_static()) {
-    // Note null is okay; this method is used in itables, and if it is null,
-    // then AbstractMethodError is thrown instead.
-    tty->print_cr("Unable to link/verify Unsafe.throwIllegalAccessError method");
-    return false; // initialization failed (cannot throw exception yet)
-  }
-  Universe::_throw_illegal_access_error_cache->init(
-    SystemDictionary::internal_Unsafe_klass(), m);
-
-  // Setup method for registering loaded classes in class loader vector
-  SystemDictionary::ClassLoader_klass()->link_class(CHECK_false);
-  m = SystemDictionary::ClassLoader_klass()->find_method(vmSymbols::addClass_name(), vmSymbols::class_void_signature());
-  if (m == NULL || m->is_static()) {
-    tty->print_cr("Unable to link/verify ClassLoader.addClass method");
-    return false; // initialization failed (cannot throw exception yet)
-  }
-  Universe::_loader_addClass_cache->init(
-    SystemDictionary::ClassLoader_klass(), m);
-
-  // Setup method for checking protection domain
-  SystemDictionary::ProtectionDomain_klass()->link_class(CHECK_false);
-  m = SystemDictionary::ProtectionDomain_klass()->
-            find_method(vmSymbols::impliesCreateAccessControlContext_name(),
-                        vmSymbols::void_boolean_signature());
-  // Allow NULL which should only happen with bootstrapping.
-  if (m != NULL) {
-    if (m->is_static()) {
-      // NoSuchMethodException doesn't actually work because it tries to run the
-      // <init> function before java_lang_Class is linked. Print error and exit.
-      tty->print_cr("ProtectionDomain.impliesCreateAccessControlContext() has the wrong linkage");
-      return false; // initialization failed
-    }
-    Universe::_pd_implies_cache->init(
-      SystemDictionary::ProtectionDomain_klass(), m);
-  }
-
-  // Setup method for stack walking
-  InstanceKlass::cast(SystemDictionary::AbstractStackWalker_klass())->link_class(CHECK_false);
-  m = InstanceKlass::cast(SystemDictionary::AbstractStackWalker_klass())->
-            find_method(vmSymbols::doStackWalk_name(),
-                        vmSymbols::doStackWalk_signature());
-  // Allow NULL which should only happen with bootstrapping.
-  if (m != NULL) {
-    Universe::_do_stack_walk_cache->init(
-      SystemDictionary::AbstractStackWalker_klass(), m);
-  }
+  Universe::initialize_known_methods(CHECK_false);
 
   // This needs to be done before the first scavenge/gc, since
   // it's an input to soft ref clearing policy.
@@ -1098,19 +1083,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/memory/universe.hpp	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/memory/universe.hpp	Sat Apr 02 05:39:25 2016 +0200
@@ -323,6 +323,9 @@
 
   static Method*      do_stack_walk_method()          { return _do_stack_walk_cache->get_method(); }
 
+  // Function to initialize these
+  static void initialize_known_methods(TRAPS);
+
   static oop          null_ptr_exception_instance()   { return _null_ptr_exception_instance;   }
   static oop          arithmetic_exception_instance() { return _arithmetic_exception_instance; }
   static oop          virtual_machine_error_instance() { return _virtual_machine_error_instance; }
--- a/hotspot/src/share/vm/oops/constantPool.cpp	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/oops/constantPool.cpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/oops/generateOopMap.cpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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
@@ -24,13 +24,16 @@
 
 #include "precompiled.hpp"
 #include "interpreter/bytecodeStream.hpp"
+#include "logging/log.hpp"
 #include "oops/generateOopMap.hpp"
 #include "oops/oop.inline.hpp"
 #include "oops/symbol.hpp"
 #include "runtime/handles.inline.hpp"
 #include "runtime/java.hpp"
 #include "runtime/relocator.hpp"
+#include "runtime/timerTrace.hpp"
 #include "utilities/bitMap.inline.hpp"
+#include "utilities/ostream.hpp"
 #include "prims/methodHandles.hpp"
 
 //
@@ -786,7 +789,7 @@
         bb->set_changed(true);
       }
     } else {
-      if (TraceMonitorMismatch) {
+      if (log_is_enabled(Info, monitormismatch)) {
         report_monitor_mismatch("monitor stack height merge conflict");
       }
       // When the monitor stacks are not matched, we set _monitor_top to
@@ -855,7 +858,7 @@
     _monitor_safe = false;
      _monitor_top = bad_monitors;
 
-    if (TraceMonitorMismatch) {
+    if (log_is_enabled(Info, monitormismatch)) {
       report_monitor_mismatch("monitor stack underflow");
     }
     return CellTypeState::ref; // just to keep the analysis going.
@@ -871,7 +874,7 @@
     _monitor_safe = false;
     _monitor_top = bad_monitors;
 
-    if (TraceMonitorMismatch) {
+    if (log_is_enabled(Info, monitormismatch)) {
       report_monitor_mismatch("monitor stack overflow");
     }
     return;
@@ -1244,7 +1247,7 @@
   // We don't set _monitor_top to bad_monitors because there are no successors
   // to this exceptional exit.
 
-  if (TraceMonitorMismatch && _monitor_safe) {
+  if (log_is_enabled(Info, monitormismatch) && _monitor_safe) {
     // We check _monitor_safe so that we only report the first mismatched
     // exceptional exit.
     report_monitor_mismatch("non-empty monitor stack at exceptional exit");
@@ -1254,11 +1257,11 @@
 }
 
 void GenerateOopMap::report_monitor_mismatch(const char *msg) {
-#ifndef PRODUCT
-  tty->print("    Monitor mismatch in method ");
-  method()->print_short_name(tty);
-  tty->print_cr(": %s", msg);
-#endif
+  ResourceMark rm;
+  outputStream* out = LogHandle(monitormismatch)::info_stream();
+  out->print("Monitor mismatch in method ");
+  method()->print_short_name(out);
+  out->print_cr(": %s", msg);
 }
 
 void GenerateOopMap::print_states(outputStream *os,
@@ -1781,7 +1784,7 @@
     _monitor_top = bad_monitors;
     _monitor_safe = false;
 
-    if (TraceMonitorMismatch) {
+    if (log_is_enabled(Info, monitormismatch)) {
       report_monitor_mismatch("nested redundant lock -- bailout...");
     }
     return;
@@ -1819,7 +1822,7 @@
     bb->set_changed(true);
     bb->_monitor_top = bad_monitors;
 
-    if (TraceMonitorMismatch) {
+    if (log_is_enabled(Info, monitormismatch)) {
       report_monitor_mismatch("improper monitor pair");
     }
   } else {
@@ -1845,7 +1848,7 @@
     // Since there are no successors to the *return bytecode, it
     // isn't necessary to set _monitor_top to bad_monitors.
 
-    if (TraceMonitorMismatch) {
+    if (log_is_enabled(Info, monitormismatch)) {
       report_monitor_mismatch("non-empty monitor stack at return");
     }
   }
--- a/hotspot/src/share/vm/oops/instanceKlass.inline.hpp	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/oops/instanceKlass.inline.hpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/oops/instanceRefKlass.cpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/oops/instanceRefKlass.hpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/oops/method.cpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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/oops/objArrayKlass.cpp	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/oops/objArrayKlass.cpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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
@@ -461,8 +461,6 @@
 
 #endif //PRODUCT
 
-static int max_objArray_print_length = 4;
-
 void ObjArrayKlass::oop_print_value_on(oop obj, outputStream* st) {
   assert(obj->is_objArray(), "must be objArray");
   st->print("a ");
@@ -470,16 +468,6 @@
   int len = objArrayOop(obj)->length();
   st->print("[%d] ", len);
   obj->print_address_on(st);
-  if (NOT_PRODUCT(PrintOopAddress ||) PrintMiscellaneous && (WizardMode || Verbose)) {
-    st->print("{");
-    for (int i = 0; i < len; i++) {
-      if (i > max_objArray_print_length) {
-        st->print("..."); break;
-      }
-      st->print(" " INTPTR_FORMAT, (intptr_t)(void*)objArrayOop(obj)->obj_at(i));
-    }
-    st->print(" }");
-  }
 }
 
 const char* ObjArrayKlass::internal_name() const {
--- a/hotspot/src/share/vm/oops/oop.cpp	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/oops/oop.cpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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
@@ -44,9 +44,8 @@
 }
 
 void oopDesc::print_address_on(outputStream* st) const {
-  if (PrintOopAddress) {
-    st->print("{" INTPTR_FORMAT "}", p2i(this));
-  }
+  st->print("{" INTPTR_FORMAT "}", p2i(this));
+
 }
 
 void oopDesc::print()         { print_on(tty);         }
@@ -76,7 +75,7 @@
     st->print("NULL");
   } else if (java_lang_String::is_instance(obj)) {
     java_lang_String::print(obj, st);
-    if (PrintOopAddress) print_address_on(st);
+    print_address_on(st);
   } else {
     klass()->oop_print_value_on(obj, st);
   }
--- a/hotspot/src/share/vm/opto/compile.hpp	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/opto/compile.hpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/prims/jni.cpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/prims/jvm.cpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/prims/jvm.h	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/prims/jvmtiEnv.cpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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"
@@ -475,7 +476,7 @@
     // terminating the VM so we check one more time.
 
     // create the zip entry
-    ClassPathZipEntry* zip_entry = ClassLoader::create_class_path_zip_entry(segment);
+    ClassPathZipEntry* zip_entry = ClassLoader::create_class_path_zip_entry(segment, true);
     if (zip_entry == NULL) {
       return JVMTI_ERROR_ILLEGAL_ARGUMENT;
     }
@@ -519,7 +520,7 @@
 
     // create the zip entry (which will open the zip file and hence
     // check that the segment is indeed a zip file).
-    ClassPathZipEntry* zip_entry = ClassLoader::create_class_path_zip_entry(segment);
+    ClassPathZipEntry* zip_entry = ClassLoader::create_class_path_zip_entry(segment, false);
     if (zip_entry == NULL) {
       return JVMTI_ERROR_ILLEGAL_ARGUMENT;
     }
--- a/hotspot/src/share/vm/prims/jvmtiExport.cpp	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/prims/jvmtiExport.cpp	Sat Apr 02 05:39:25 2016 +0200
@@ -2315,6 +2315,8 @@
 }
 
 ////////////////////////////////////////////////////////////////////////////////////////////////
+#if INCLUDE_SERVICES
+// Attach is disabled if SERVICES is not included
 
 // type for the Agent_OnAttach entry point
 extern "C" {
@@ -2416,6 +2418,7 @@
   return result;
 }
 
+#endif // INCLUDE_SERVICES
 ////////////////////////////////////////////////////////////////////////////////////////////////
 
 // Setup current current thread for event collection.
--- a/hotspot/src/share/vm/prims/jvmtiExport.hpp	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/prims/jvmtiExport.hpp	Sat Apr 02 05:39:25 2016 +0200
@@ -377,9 +377,11 @@
 
   static void transition_pending_onload_raw_monitors() NOT_JVMTI_RETURN;
 
+#if INCLUDE_SERVICES
   // attach support
   static jint load_agent_library(const char *agent, const char *absParam, const char *options, outputStream* out) NOT_JVMTI_RETURN_(JNI_ERR);
   static jint load_agent_library(AttachOperation* op, outputStream* out) NOT_JVMTI_RETURN_(JNI_ERR);
+#endif
 
   // SetNativeMethodPrefix support
   static char** get_all_native_method_prefixes(int* count_ptr) NOT_JVMTI_RETURN_(NULL);
--- a/hotspot/src/share/vm/prims/methodHandles.cpp	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/prims/methodHandles.cpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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/unsafe.cpp	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/prims/unsafe.cpp	Sat Apr 02 05:39:25 2016 +0200
@@ -905,7 +905,10 @@
   }
 
   const Klass* host_klass = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(host_class));
-  assert(host_klass != NULL, "invariant");
+  // Primitive types have NULL Klass* fields in their java.lang.Class instances.
+  if (host_klass == NULL) {
+    THROW_0(vmSymbols::java_lang_IllegalArgumentException());
+  }
 
   const char* host_source = host_klass->external_name();
   Handle      host_loader(THREAD, host_klass->class_loader());
--- a/hotspot/src/share/vm/prims/whitebox.cpp	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/prims/whitebox.cpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/runtime/arguments.cpp	Sat Apr 02 05:39:25 2016 +0200
@@ -66,15 +66,15 @@
 #define DEFAULT_VENDOR_URL_BUG "http://bugreport.java.com/bugreport/crash.jsp"
 #define DEFAULT_JAVA_LAUNCHER  "generic"
 
-#define UNSUPPORTED_GC_OPTION(gc)                                     \
-do {                                                                  \
-  if (gc) {                                                           \
-    if (FLAG_IS_CMDLINE(gc)) {                                        \
-      warning(#gc " is not supported in this VM.  Using Serial GC."); \
-    }                                                                 \
-    FLAG_SET_DEFAULT(gc, false);                                      \
-  }                                                                   \
-} while(0)
+#define UNSUPPORTED_GC_OPTION(gc)                         \
+  do {                                                    \
+    if (gc) {                                             \
+      if (FLAG_IS_CMDLINE(gc)) {                          \
+        warning("-XX:+" #gc " not supported in this VM"); \
+      }                                                   \
+      FLAG_SET_DEFAULT(gc, false);                        \
+    }                                                     \
+  } while(0)
 
 char*  Arguments::_jvm_flags_file               = NULL;
 char** Arguments::_jvm_flags_array              = NULL;
@@ -385,6 +385,7 @@
   { "JNIDetachReleasesMonitors",     JDK_Version::undefined(), JDK_Version::jdk(9), JDK_Version::jdk(10) },
   { "UseAltSigs",                    JDK_Version::undefined(), JDK_Version::jdk(9), JDK_Version::jdk(10) },
   { "SegmentedHeapDumpThreshold",    JDK_Version::undefined(), JDK_Version::jdk(9), JDK_Version::jdk(10) },
+  { "PrintOopAddress",               JDK_Version::undefined(), JDK_Version::jdk(9), JDK_Version::jdk(10) },
 
 #ifdef TEST_VERIFY_SPECIAL_JVM_FLAGS
   { "dep > obs",                    JDK_Version::jdk(9), JDK_Version::jdk(8), JDK_Version::undefined() },
@@ -417,16 +418,36 @@
 };
 
 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) },
+  { "TraceLoaderConstraints",    LogLevel::Info,  true,  LOG_TAGS(classload, constraints) },
+  { "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" },
+  { "TraceMonitorMismatch",       "-Xlog:monitormismatch=info" },
+  { "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 +499,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];
@@ -961,14 +994,39 @@
   return NULL;
 }
 
-AliasedLoggingFlag Arguments::catch_logging_aliases(const char* name){
+void log_deprecated_flag(const char* name, bool on, AliasedLoggingFlag alf) {
+  LogTagType tagSet[] = {alf.tag0, alf.tag1, alf.tag2, alf.tag3, alf.tag4, alf.tag5};
+  // Set tagset string buffer at max size of 256, large enough for any alias tagset
+  const int max_tagset_size = 256;
+  int max_tagset_len = max_tagset_size - 1;
+  char tagset_buffer[max_tagset_size];
+  tagset_buffer[0] = '\0';
+
+  // Write tag-set for aliased logging option, in string list form
+  int max_tags = sizeof(tagSet)/sizeof(tagSet[0]);
+  for (int i = 0; i < max_tags && tagSet[i] != LogTag::__NO_TAG; i++) {
+    if (i > 0) {
+      strncat(tagset_buffer, ",", max_tagset_len - strlen(tagset_buffer));
+    }
+    strncat(tagset_buffer, LogTag::name(tagSet[i]), max_tagset_len - strlen(tagset_buffer));
+  }
+
+  log_warning(arguments)("-XX:%s%s is deprecated. Will use -Xlog:%s=%s instead.",
+                         (on) ? "+" : "-",
+                         name,
+                         tagset_buffer,
+                         (on) ? LogLevel::name(alf.level) : "off");
+}
+
+AliasedLoggingFlag Arguments::catch_logging_aliases(const char* name, bool on){
   for (size_t i = 0; aliased_logging_flags[i].alias_name != NULL; i++) {
     const AliasedLoggingFlag& alf = aliased_logging_flags[i];
     if (strcmp(alf.alias_name, name) == 0) {
+      log_deprecated_flag(name, on, alf);
       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 +1039,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, false);
     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 +1053,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, true);
     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 +1259,23 @@
     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){
+        log_warning(arguments)("%s has been removed. Please use %s instead.",
+                               stripped_argname,
+                               replacement);
+        return false;
+      }
+    }
+#endif //PRODUCT
   }
 
   // For locked flags, report a custom error message if available.
@@ -1897,26 +1964,45 @@
                                           CollectorPolicy::compute_heap_alignment());
 }
 
+bool Arguments::gc_selected() {
+#if INCLUDE_ALL_GCS
+  return UseSerialGC || UseParallelGC || UseParallelOldGC || UseConcMarkSweepGC || UseG1GC;
+#else
+  return UseSerialGC;
+#endif // INCLUDE_ALL_GCS
+}
+
 void Arguments::select_gc_ergonomically() {
+#if INCLUDE_ALL_GCS
   if (os::is_server_class_machine()) {
     if (should_auto_select_low_pause_collector()) {
-      FLAG_SET_ERGO(bool, UseConcMarkSweepGC, true);
+      FLAG_SET_ERGO_IF_DEFAULT(bool, UseConcMarkSweepGC, true);
     } else {
 #if defined(JAVASE_EMBEDDED)
-      FLAG_SET_ERGO(bool, UseParallelGC, true);
+      FLAG_SET_ERGO_IF_DEFAULT(bool, UseParallelGC, true);
 #else
-      FLAG_SET_ERGO(bool, UseG1GC, true);
+      FLAG_SET_ERGO_IF_DEFAULT(bool, UseG1GC, true);
 #endif
     }
   } else {
-    FLAG_SET_ERGO(bool, UseSerialGC, true);
-  }
+    FLAG_SET_ERGO_IF_DEFAULT(bool, UseSerialGC, true);
+  }
+#else
+  UNSUPPORTED_GC_OPTION(UseG1GC);
+  UNSUPPORTED_GC_OPTION(UseParallelGC);
+  UNSUPPORTED_GC_OPTION(UseParallelOldGC);
+  UNSUPPORTED_GC_OPTION(UseConcMarkSweepGC);
+  UNSUPPORTED_GC_OPTION(UseParNewGC);
+  FLAG_SET_ERGO_IF_DEFAULT(bool, UseSerialGC, true);
+#endif // INCLUDE_ALL_GCS
 }
 
 void Arguments::select_gc() {
   if (!gc_selected()) {
     select_gc_ergonomically();
-    guarantee(gc_selected(), "No GC selected");
+    if (!gc_selected()) {
+      vm_exit_during_initialization("Garbage collector not selected (default collector explicitly disabled)", NULL);
+    }
   }
 }
 
@@ -2041,16 +2127,6 @@
   log_trace(gc)("ConcGCThreads: %u", ConcGCThreads);
 }
 
-#if !INCLUDE_ALL_GCS
-#ifdef ASSERT
-static bool verify_serial_gc_flags() {
-  return (UseSerialGC &&
-        !(UseParNewGC || (UseConcMarkSweepGC) || UseG1GC ||
-          UseParallelGC || UseParallelOldGC));
-}
-#endif // ASSERT
-#endif // INCLUDE_ALL_GCS
-
 void Arguments::set_gc_specific_flags() {
 #if INCLUDE_ALL_GCS
   // Set per-collector flags
@@ -2072,8 +2148,6 @@
     // Keeping the heap 100% free is hard ;-) so limit it to 99%.
     FLAG_SET_ERGO(uintx, MinHeapFreeRatio, 99);
   }
-#else // INCLUDE_ALL_GCS
-  assert(verify_serial_gc_flags(), "SerialGC unset");
 #endif // INCLUDE_ALL_GCS
 }
 
@@ -3923,17 +3997,6 @@
   }
 }
 
-#if !INCLUDE_ALL_GCS
-static void force_serial_gc() {
-  FLAG_SET_DEFAULT(UseSerialGC, true);
-  UNSUPPORTED_GC_OPTION(UseG1GC);
-  UNSUPPORTED_GC_OPTION(UseParallelGC);
-  UNSUPPORTED_GC_OPTION(UseParallelOldGC);
-  UNSUPPORTED_GC_OPTION(UseConcMarkSweepGC);
-  UNSUPPORTED_GC_OPTION(UseParNewGC);
-}
-#endif // INCLUDE_ALL_GCS
-
 // Sharing support
 // Construct the path to the archive
 static char* get_shared_archive_path() {
@@ -4328,9 +4391,6 @@
   // Set object alignment values.
   set_object_alignment();
 
-#if !INCLUDE_ALL_GCS
-  force_serial_gc();
-#endif // INCLUDE_ALL_GCS
 #if !INCLUDE_CDS
   if (DumpSharedSpaces || RequireSharedSpaces) {
     jio_fprintf(defaultStream::error_stream(),
--- a/hotspot/src/share/vm/runtime/arguments.hpp	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/runtime/arguments.hpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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.
@@ -517,7 +526,7 @@
   // Return NULL if the arg has expired.
   static const char* handle_aliases_and_deprecation(const char* arg, bool warn);
   static bool lookup_logging_aliases(const char* arg, char* buffer);
-  static AliasedLoggingFlag catch_logging_aliases(const char* name);
+  static AliasedLoggingFlag catch_logging_aliases(const char* name, bool on);
   static short  CompileOnlyClassesNum;
   static short  CompileOnlyClassesMax;
   static char** CompileOnlyClasses;
@@ -558,7 +567,7 @@
   static jint adjust_after_os();
 
   static void set_gc_specific_flags();
-  static inline bool gc_selected(); // whether a gc has been selected
+  static bool gc_selected(); // whether a gc has been selected
   static void select_gc_ergonomically();
 #if INCLUDE_JVMCI
   // Check consistency of jvmci vm argument settings.
@@ -723,10 +732,6 @@
   static void check_unsupported_dumping_properties() NOT_CDS_RETURN;
 };
 
-bool Arguments::gc_selected() {
-  return UseConcMarkSweepGC || UseG1GC || UseParallelGC || UseParallelOldGC || UseSerialGC;
-}
-
 // Disable options not supported in this release, with a warning if they
 // were explicitly requested on the command-line
 #define UNSUPPORTED_OPTION(opt, description)                    \
--- a/hotspot/src/share/vm/runtime/commandLineFlagConstraintList.cpp	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/runtime/commandLineFlagConstraintList.cpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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
@@ -290,13 +290,11 @@
 #endif // INCLUDE_ALL_GCS
 }
 
-// Find constraints by name and return only if found constraint's type is equal or lower than current validating type.
-CommandLineFlagConstraint* CommandLineFlagConstraintList::find_if_needs_check(const char* name) {
+CommandLineFlagConstraint* CommandLineFlagConstraintList::find(const char* name) {
   CommandLineFlagConstraint* found = NULL;
   for (int i=0; i<length(); i++) {
     CommandLineFlagConstraint* constraint = at(i);
-    if ((strcmp(constraint->name(), name) == 0) &&
-        (constraint->type() <= _validating_type)) {
+    if (strcmp(constraint->name(), name) == 0) {
       found = constraint;
       break;
     }
@@ -304,6 +302,16 @@
   return found;
 }
 
+// Find constraints by name and return only if found constraint's type is equal or lower than current validating type.
+CommandLineFlagConstraint* CommandLineFlagConstraintList::find_if_needs_check(const char* name) {
+  CommandLineFlagConstraint* found = NULL;
+  CommandLineFlagConstraint* constraint = find(name);
+  if (constraint && (constraint->type() <= _validating_type)) {
+    found = constraint;
+  }
+  return found;
+}
+
 // Check constraints for specific constraint type.
 bool CommandLineFlagConstraintList::check_constraints(CommandLineFlagConstraint::ConstraintType type) {
   guarantee(type > _validating_type, "Constraint check is out of order.");
--- a/hotspot/src/share/vm/runtime/commandLineFlagConstraintList.hpp	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/runtime/commandLineFlagConstraintList.hpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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
@@ -89,6 +89,7 @@
   static void init();
   static int length() { return (_constraints != NULL) ? _constraints->length() : 0; }
   static CommandLineFlagConstraint* at(int i) { return (_constraints != NULL) ? _constraints->at(i) : NULL; }
+  static CommandLineFlagConstraint* find(const char* name);
   static CommandLineFlagConstraint* find_if_needs_check(const char* name);
   static void add(CommandLineFlagConstraint* constraint) { _constraints->append(constraint); }
   // True if 'AfterErgo' or later constraint functions are validated.
--- a/hotspot/src/share/vm/runtime/commandLineFlagConstraintsGC.cpp	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/runtime/commandLineFlagConstraintsGC.cpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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"
@@ -113,7 +114,7 @@
 
 static Flag::Error MinPLABSizeBounds(const char* name, size_t value, bool verbose) {
 #if INCLUDE_ALL_GCS
-  if ((UseConcMarkSweepGC || UseG1GC) && (value < PLAB::min_size())) {
+  if ((UseConcMarkSweepGC || UseG1GC || UseParallelGC) && (value < PLAB::min_size())) {
     CommandLineError::print(verbose,
                             "%s (" SIZE_FORMAT ") must be "
                             "greater than or equal to ergonomic PLAB minimum size (" SIZE_FORMAT ")\n",
@@ -126,7 +127,7 @@
 
 static Flag::Error MaxPLABSizeBounds(const char* name, size_t value, bool verbose) {
 #if INCLUDE_ALL_GCS
-  if ((UseConcMarkSweepGC || UseG1GC) && (value > PLAB::max_size())) {
+  if ((UseConcMarkSweepGC || UseG1GC || UseParallelGC) && (value > PLAB::max_size())) {
     CommandLineError::print(verbose,
                             "%s (" SIZE_FORMAT ") must be "
                             "less than or equal to ergonomic PLAB maximum size (" SIZE_FORMAT ")\n",
@@ -381,6 +382,39 @@
   return Flag::SUCCESS;
 }
 
+Flag::Error ParGCCardsPerStrideChunkConstraintFunc(intx value, bool verbose) {
+#if INCLUDE_ALL_GCS
+  if (UseConcMarkSweepGC) {
+    // ParGCCardsPerStrideChunk should be compared with card table size.
+    size_t heap_size = Universe::heap()->reserved_region().word_size();
+    CardTableModRefBS* bs = (CardTableModRefBS*)GenCollectedHeap::heap()->rem_set()->bs();
+    size_t card_table_size = bs->cards_required(heap_size) - 1; // Valid card table size
+
+    if ((size_t)value > card_table_size) {
+      CommandLineError::print(verbose,
+                              "ParGCCardsPerStrideChunk (" INTX_FORMAT ") is too large for the heap size and "
+                              "must be less than or equal to card table size (" SIZE_FORMAT ")\n",
+                              value, card_table_size);
+      return Flag::VIOLATES_CONSTRAINT;
+    }
+
+    // ParGCCardsPerStrideChunk is used with n_strides(ParallelGCThreads*ParGCStridesPerThread)
+    // from CardTableModRefBSForCTRS::process_stride(). Note that ParGCStridesPerThread is already checked
+    // not to make an overflow with ParallelGCThreads from its constraint function.
+    uintx n_strides = ParallelGCThreads * ParGCStridesPerThread;
+    uintx ergo_max = max_uintx / n_strides;
+    if ((uintx)value > ergo_max) {
+      CommandLineError::print(verbose,
+                              "ParGCCardsPerStrideChunk (" INTX_FORMAT ") must be "
+                              "less than or equal to ergonomic maximum (" UINTX_FORMAT ")\n",
+                              value, ergo_max);
+      return Flag::VIOLATES_CONSTRAINT;
+    }
+  }
+#endif
+  return Flag::SUCCESS;
+}
+
 Flag::Error CMSOldPLABMinConstraintFunc(size_t value, bool verbose) {
   Flag::Error status = Flag::SUCCESS;
 
@@ -448,6 +482,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 +639,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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/runtime/commandLineFlagConstraintsGC.hpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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
@@ -56,11 +56,13 @@
 #endif // INCLUDE_ALL_GCS
 
 Flag::Error ParGCStridesPerThreadConstraintFunc(uintx value, bool verbose);
+Flag::Error ParGCCardsPerStrideChunkConstraintFunc(intx value, bool verbose);
 Flag::Error CMSOldPLABMinConstraintFunc(size_t value, bool verbose);
 Flag::Error CMSOldPLABMaxConstraintFunc(size_t value, bool verbose);
 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/commandLineFlagConstraintsRuntime.cpp	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/runtime/commandLineFlagConstraintsRuntime.cpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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
@@ -130,3 +130,36 @@
     return Flag::SUCCESS;
   }
 }
+
+static inline Flag::Error sharedConstraintFunc(const char *name, size_t value, size_t taken, bool verbose) {
+  size_t available = (MAX_SHARED_DELTA-(taken+SHARED_PAGE));
+  if (value > available) {
+    CommandLineError::print(verbose,
+                            "%s (" SIZE_FORMAT ") must be "
+                            "smaller than or equal to (" SIZE_FORMAT ")\n",
+                            name, value, available);
+    return Flag::VIOLATES_CONSTRAINT;
+  } else {
+    return Flag::SUCCESS;
+  }
+}
+
+Flag::Error SharedReadWriteSizeConstraintFunc(size_t value, bool verbose) {
+  size_t taken = (SharedReadOnlySize+SharedMiscDataSize+SharedMiscCodeSize);
+  return sharedConstraintFunc("SharedReadWriteSize", value, taken, verbose);
+}
+
+Flag::Error SharedReadOnlySizeConstraintFunc(size_t value, bool verbose) {
+  size_t taken = (SharedReadWriteSize+SharedMiscDataSize+SharedMiscCodeSize);
+  return sharedConstraintFunc("SharedReadOnlySize", value, taken, verbose);
+}
+
+Flag::Error SharedMiscDataSizeConstraintFunc(size_t value, bool verbose) {
+  size_t taken = (SharedReadWriteSize+SharedReadOnlySize+SharedMiscCodeSize);
+  return sharedConstraintFunc("SharedMiscDataSize", value, taken, verbose);
+}
+
+Flag::Error SharedMiscCodeSizeConstraintFunc(size_t value, bool verbose) {
+  size_t taken = (SharedReadWriteSize+SharedReadOnlySize+SharedMiscDataSize);
+  return sharedConstraintFunc("SharedMiscCodeSize", value, taken, verbose);
+}
--- a/hotspot/src/share/vm/runtime/commandLineFlagConstraintsRuntime.hpp	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/runtime/commandLineFlagConstraintsRuntime.hpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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
@@ -45,4 +45,9 @@
 
 Flag::Error PerfDataSamplingIntervalFunc(intx value, bool verbose);
 
+Flag::Error SharedReadWriteSizeConstraintFunc(size_t value, bool verbose);
+Flag::Error SharedReadOnlySizeConstraintFunc(size_t value, bool verbose);
+Flag::Error SharedMiscDataSizeConstraintFunc(size_t value, bool verbose);
+Flag::Error SharedMiscCodeSizeConstraintFunc(size_t value, bool verbose);
+
 #endif /* SHARE_VM_RUNTIME_COMMANDLINEFLAGCONSTRAINTSRUNTIME_HPP */
--- a/hotspot/src/share/vm/runtime/commandLineFlagRangeList.cpp	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/runtime/commandLineFlagRangeList.cpp	Sat Apr 02 05:39:25 2016 +0200
@@ -27,6 +27,7 @@
 #include "classfile/symbolTable.hpp"
 #include "gc/shared/referenceProcessor.hpp"
 #include "runtime/arguments.hpp"
+#include "runtime/commandLineFlagConstraintList.hpp"
 #include "runtime/commandLineFlagRangeList.hpp"
 #include "runtime/os.hpp"
 #include "runtime/task.hpp"
@@ -378,12 +379,18 @@
   return found;
 }
 
-void CommandLineFlagRangeList::print(const char* name, outputStream* st, bool unspecified) {
+void CommandLineFlagRangeList::print(outputStream* st, const char* name, RangeStrFunc default_range_str_func) {
   CommandLineFlagRange* range = CommandLineFlagRangeList::find(name);
   if (range != NULL) {
     range->print(st);
-  } else if (unspecified == true) {
-    st->print("[                           ...                           ]");
+  } else {
+    CommandLineFlagConstraint* constraint = CommandLineFlagConstraintList::find(name);
+    if (constraint != NULL) {
+      assert(default_range_str_func!=NULL, "default_range_str_func must be provided");
+      st->print("%s", default_range_str_func());
+    } else {
+      st->print("[                           ...                           ]");
+    }
   }
 }
 
--- a/hotspot/src/share/vm/runtime/commandLineFlagRangeList.hpp	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/runtime/commandLineFlagRangeList.hpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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
@@ -71,7 +71,7 @@
   static CommandLineFlagRange* at(int i) { return (_ranges != NULL) ? _ranges->at(i) : NULL; }
   static CommandLineFlagRange* find(const char* name);
   static void add(CommandLineFlagRange* range) { _ranges->append(range); }
-  static void print(const char* name, outputStream* st, bool unspecified = false);
+  static void print(outputStream* st, const char* name, RangeStrFunc default_range_str_func);
   // Check the final values of all flags for ranges.
   static bool check_ranges();
 };
--- a/hotspot/src/share/vm/runtime/globals.cpp	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/runtime/globals.cpp	Sat Apr 02 05:39:25 2016 +0200
@@ -84,6 +84,56 @@
 
 MATERIALIZE_FLAGS_EXT
 
+#define DEFAULT_RANGE_STR_CHUNK_SIZE 64
+static char* create_range_str(const char *fmt, ...) {
+  static size_t string_length = DEFAULT_RANGE_STR_CHUNK_SIZE;
+  static char* range_string = NEW_C_HEAP_ARRAY(char, string_length, mtLogging);
+
+  int size_needed = 0;
+  do {
+    va_list args;
+    va_start(args, fmt);
+    size_needed = jio_vsnprintf(range_string, string_length, fmt, args);
+    va_end(args);
+
+    if (size_needed < 0) {
+      string_length += DEFAULT_RANGE_STR_CHUNK_SIZE;
+      range_string = REALLOC_C_HEAP_ARRAY(char, range_string, string_length, mtLogging);
+      guarantee(range_string != NULL, "create_range_str string should not be NULL");
+    }
+  } while (size_needed < 0);
+
+  return range_string;
+}
+
+const char* Flag::get_int_default_range_str() {
+  return create_range_str("[ " INT32_FORMAT_W(-25) " ... " INT32_FORMAT_W(25) " ]", INT_MIN, INT_MAX);
+}
+
+const char* Flag::get_uint_default_range_str() {
+  return create_range_str("[ " UINT32_FORMAT_W(-25) " ... " UINT32_FORMAT_W(25) " ]", 0, UINT_MAX);
+}
+
+const char* Flag::get_intx_default_range_str() {
+  return create_range_str("[ " INTX_FORMAT_W(-25) " ... " INTX_FORMAT_W(25) " ]", min_intx, max_intx);
+}
+
+const char* Flag::get_uintx_default_range_str() {
+  return create_range_str("[ " UINTX_FORMAT_W(-25) " ... " UINTX_FORMAT_W(25) " ]", 0, max_uintx);
+}
+
+const char* Flag::get_uint64_t_default_range_str() {
+  return create_range_str("[ " UINT64_FORMAT_W(-25) " ... " UINT64_FORMAT_W(25) " ]", 0, uint64_t(max_juint));
+}
+
+const char* Flag::get_size_t_default_range_str() {
+  return create_range_str("[ " SIZE_FORMAT_W(-25) " ... " SIZE_FORMAT_W(25) " ]", 0, SIZE_MAX);
+}
+
+const char* Flag::get_double_default_range_str() {
+  return create_range_str("[ %-25.3f ... %25.3f ]", DBL_MIN, DBL_MAX);
+}
+
 static bool is_product_build() {
 #ifdef PRODUCT
   return true;
@@ -405,7 +455,25 @@
   } else if (!is_bool() && !is_ccstr()) {
     st->print("%9s %-50s ", _type, _name);
 
-    CommandLineFlagRangeList::print(_name, st, true);
+    RangeStrFunc func = NULL;
+    if (is_int()) {
+      func = Flag::get_int_default_range_str;
+    } else if (is_uint()) {
+      func = Flag::get_uint_default_range_str;
+    } else if (is_intx()) {
+      func = Flag::get_intx_default_range_str;
+    } else if (is_uintx()) {
+      func = Flag::get_uintx_default_range_str;
+    } else if (is_uint64_t()) {
+      func = Flag::get_uint64_t_default_range_str;
+    } else if (is_size_t()) {
+      func = Flag::get_size_t_default_range_str;
+    } else if (is_double()) {
+      func = Flag::get_double_default_range_str;
+    } else {
+      ShouldNotReachHere();
+    }
+    CommandLineFlagRangeList::print(st, _name, func);
 
     st->print(" %-20s", " ");
     print_kind(st);
--- a/hotspot/src/share/vm/runtime/globals.hpp	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/runtime/globals.hpp	Sat Apr 02 05:39:25 2016 +0200
@@ -224,6 +224,9 @@
 typedef const char* ccstr;
 typedef const char* ccstrlist;   // represents string arguments which accumulate
 
+// function type that will construct default range string
+typedef const char* (*RangeStrFunc)(void);
+
 struct Flag {
   enum Flags {
     // value origin
@@ -305,6 +308,14 @@
   static Flag* find_flag(const char* name, size_t length, bool allow_locked = false, bool return_flag = false);
   static Flag* fuzzy_match(const char* name, size_t length, bool allow_locked = false);
 
+  static const char* get_int_default_range_str();
+  static const char* get_uint_default_range_str();
+  static const char* get_intx_default_range_str();
+  static const char* get_uintx_default_range_str();
+  static const char* get_uint64_t_default_range_str();
+  static const char* get_size_t_default_range_str();
+  static const char* get_double_default_range_str();
+
   void check_writable();
 
   bool is_bool() const;
@@ -951,9 +962,6 @@
   notproduct(bool, PrintMallocFree, false,                                  \
           "Trace calls to C heap malloc/free allocation")                   \
                                                                             \
-  product(bool, PrintOopAddress, false,                                     \
-          "Always print the location of the oop")                           \
-                                                                            \
   notproduct(bool, VerifyCodeCache, false,                                  \
           "Verify code cache on memory allocation/deallocation")            \
                                                                             \
@@ -990,9 +998,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 +1057,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")                \
                                                                             \
@@ -1460,9 +1462,6 @@
   develop(bool, TimeOopMap2, false,                                         \
           "Time calls to GenerateOopMap::compute_map() individually")       \
                                                                             \
-  develop(bool, TraceMonitorMismatch, false,                                \
-          "Trace monitor matching failures during OopMapGeneration")        \
-                                                                            \
   develop(bool, TraceOopMapRewrites, false,                                 \
           "Trace rewriting of method oops during oop map generation")       \
                                                                             \
@@ -1472,9 +1471,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,                                         \
@@ -1633,6 +1629,7 @@
           "The number of cards in each chunk of the parallel chunks used "  \
           "during card table scanning")                                     \
           range(1, max_intx)                                                \
+          constraint(ParGCCardsPerStrideChunkConstraintFunc,AfterMemoryInit)\
                                                                             \
   product(uintx, OldPLABWeight, 50,                                         \
           "Percentage (0-100) used to weight the current sample when "      \
@@ -1904,7 +1901,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 +2065,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 +2218,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,12 +2385,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")                                       \
-                                                                            \
   product(size_t, InitialBootClassLoaderMetaspaceSize,                      \
           NOT_LP64(2200*K) LP64_ONLY(4*M),                                  \
           "Initial size of the boot class loader data metaspace")           \
@@ -2414,18 +2403,12 @@
   manageable(bool, PrintClassHistogram, false,                              \
           "Print a histogram of class instances")                           \
                                                                             \
-  develop(bool, TraceWorkGang, false,                                       \
-          "Trace activities of work gangs")                                 \
-                                                                            \
   develop(bool, TraceGCTaskManager, false,                                  \
           "Trace actions of the GC task manager")                           \
                                                                             \
   develop(bool, TraceGCTaskQueue, false,                                    \
           "Trace actions of the GC task queues")                            \
                                                                             \
-  diagnostic(bool, TraceGCTaskThread, false,                                \
-          "Trace actions of the GC task threads")                           \
-                                                                            \
   develop(bool, TraceParallelOldGCMarkingPhase, false,                      \
           "Trace marking phase in ParallelOldGC")                           \
                                                                             \
@@ -2545,10 +2528,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 +2759,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 +3242,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 +3269,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)                                                \
@@ -3986,18 +3967,22 @@
   product(size_t, SharedReadWriteSize, DEFAULT_SHARED_READ_WRITE_SIZE,      \
           "Size of read-write space for metadata (in bytes)")               \
           range(MIN_SHARED_READ_WRITE_SIZE, MAX_SHARED_READ_WRITE_SIZE)     \
+          constraint(SharedReadWriteSizeConstraintFunc,AfterErgo)           \
                                                                             \
   product(size_t, SharedReadOnlySize, DEFAULT_SHARED_READ_ONLY_SIZE,        \
           "Size of read-only space for metadata (in bytes)")                \
           range(MIN_SHARED_READ_ONLY_SIZE, MAX_SHARED_READ_ONLY_SIZE)       \
+          constraint(SharedReadOnlySizeConstraintFunc,AfterErgo)            \
                                                                             \
   product(size_t, SharedMiscDataSize, DEFAULT_SHARED_MISC_DATA_SIZE,        \
           "Size of the shared miscellaneous data area (in bytes)")          \
           range(MIN_SHARED_MISC_DATA_SIZE, MAX_SHARED_MISC_DATA_SIZE)       \
+          constraint(SharedMiscDataSizeConstraintFunc,AfterErgo)            \
                                                                             \
   product(size_t, SharedMiscCodeSize, DEFAULT_SHARED_MISC_CODE_SIZE,        \
           "Size of the shared miscellaneous code area (in bytes)")          \
           range(MIN_SHARED_MISC_CODE_SIZE, MAX_SHARED_MISC_CODE_SIZE)       \
+          constraint(SharedMiscCodeSizeConstraintFunc,AfterErgo)            \
                                                                             \
   product(size_t, SharedBaseAddress, LP64_ONLY(32*G)                        \
           NOT_LP64(LINUX_ONLY(2*G) NOT_LINUX(0)),                           \
--- a/hotspot/src/share/vm/runtime/globals_extension.hpp	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/runtime/globals_extension.hpp	Sat Apr 02 05:39:25 2016 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -290,6 +290,12 @@
 
 #define FLAG_SET_CMDLINE(type, name, value) (CommandLineFlagsEx::type##AtPut(FLAG_MEMBER_WITH_TYPE(name,type), (type)(value), Flag::COMMAND_LINE))
 #define FLAG_SET_ERGO(type, name, value)    (CommandLineFlagsEx::type##AtPut(FLAG_MEMBER_WITH_TYPE(name,type), (type)(value), Flag::ERGONOMIC))
+#define FLAG_SET_ERGO_IF_DEFAULT(type, name, value) \
+  do {                                              \
+    if (FLAG_IS_DEFAULT(name)) {                    \
+      FLAG_SET_ERGO(type, name, value);             \
+    }                                               \
+  } while (0)
 
 // Can't put the following in CommandLineFlags because
 // of a circular dependency on the enum definition.
--- a/hotspot/src/share/vm/runtime/init.cpp	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/runtime/init.cpp	Sat Apr 02 05:39:25 2016 +0200
@@ -47,6 +47,7 @@
 void mutex_init();
 void chunkpool_init();
 void perfMemory_init();
+void SuspendibleThreadSet_init() NOT_ALL_GCS_RETURN;
 
 // Initialization done by Java thread in init_globals()
 void management_init();
@@ -93,6 +94,7 @@
   mutex_init();
   chunkpool_init();
   perfMemory_init();
+  SuspendibleThreadSet_init();
 }
 
 
--- a/hotspot/src/share/vm/runtime/jniHandles.cpp	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/runtime/jniHandles.cpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/runtime/jniHandles.hpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/runtime/mutexLocker.cpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/runtime/mutexLocker.hpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/runtime/objectMonitor.cpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/runtime/os.cpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/runtime/os.hpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/runtime/reflection.cpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/runtime/safepoint.cpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/runtime/safepoint.hpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/runtime/sharedRuntime.cpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/runtime/sharedRuntime.hpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/runtime/stubRoutines.cpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/runtime/synchronizer.cpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/runtime/thread.cpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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"
@@ -152,7 +153,6 @@
 // Current thread is maintained as a thread-local variable
 THREAD_LOCAL_DECL Thread* Thread::_thr_current = NULL;
 #endif
-
 // Class hierarchy
 // - Thread
 //   - VMThread
@@ -2887,7 +2887,9 @@
 
 // Called by Threads::print() for VM_PrintThreads operation
 void JavaThread::print_on(outputStream *st) const {
-  st->print("\"%s\" ", get_thread_name());
+  st->print_raw("\"");
+  st->print_raw(get_thread_name());
+  st->print_raw("\" ");
   oop thread_oop = threadObj();
   if (thread_oop != NULL) {
     st->print("#" INT64_FORMAT " ", java_lang_Thread::thread_id(thread_oop));
@@ -3416,7 +3418,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 +3470,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 +3541,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 +3630,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 +3705,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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/runtime/timer.cpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/runtime/timer.hpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/runtime/vmStructs.cpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/runtime/vmThread.cpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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/diagnosticCommand.cpp	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/services/diagnosticCommand.cpp	Sat Apr 02 05:39:25 2016 +0200
@@ -61,17 +61,19 @@
   DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<RunFinalizationDCmd>(full_export, true, false));
   DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<HeapInfoDCmd>(full_export, true, false));
   DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<FinalizerInfoDCmd>(full_export, true, false));
-#if INCLUDE_SERVICES // Heap dumping/inspection supported
+#if INCLUDE_SERVICES
   DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<HeapDumpDCmd>(DCmd_Source_Internal | DCmd_Source_AttachAPI, true, false));
   DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<ClassHistogramDCmd>(full_export, true, false));
   DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<ClassStatsDCmd>(full_export, true, false));
   DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<ClassHierarchyDCmd>(full_export, true, false));
   DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<SymboltableDCmd>(full_export, true, false));
   DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<StringtableDCmd>(full_export, true, false));
+#if INCLUDE_JVMTI // Both JVMTI and SERVICES have to be enabled to have this dcmd
+  DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<JVMTIAgentLoadDCmd>(full_export, true, false));
+#endif // INCLUDE_JVMTI
 #endif // INCLUDE_SERVICES
 #if INCLUDE_JVMTI
   DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<JVMTIDataDumpDCmd>(full_export, true, false));
-  DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<JVMTIAgentLoadDCmd>(full_export, true, false));
 #endif // INCLUDE_JVMTI
   DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<ThreadDumpDCmd>(full_export, true, false));
   DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<ClassLoaderStatsDCmd>(full_export, true, false));
@@ -255,6 +257,7 @@
   }
 }
 
+#if INCLUDE_SERVICES
 JVMTIAgentLoadDCmd::JVMTIAgentLoadDCmd(outputStream* output, bool heap) :
                                        DCmdWithParser(output, heap),
   _libpath("library path", "Absolute path of the JVMTI agent to load.",
@@ -314,6 +317,7 @@
     return 0;
   }
 }
+#endif // INCLUDE_SERVICES
 
 void PrintSystemPropertiesDCmd::execute(DCmdSource source, TRAPS) {
   // load sun.misc.VMSupport
--- a/hotspot/src/share/vm/services/diagnosticCommand.hpp	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/services/diagnosticCommand.hpp	Sat Apr 02 05:39:25 2016 +0200
@@ -174,6 +174,8 @@
   virtual void execute(DCmdSource source, TRAPS);
 };
 
+#if INCLUDE_SERVICES
+#if INCLUDE_JVMTI
 class JVMTIAgentLoadDCmd : public DCmdWithParser {
 protected:
   DCmdArgument<char*> _libpath;
@@ -193,6 +195,8 @@
   static int num_arguments();
   virtual void execute(DCmdSource source, TRAPS);
 };
+#endif // INCLUDE_JVMTI
+#endif // INCLUDE_SERVICES
 
 class VMDynamicLibrariesDCmd : public DCmd {
 public:
--- a/hotspot/src/share/vm/services/heapDumper.cpp	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/services/heapDumper.cpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/trace/trace.dtd	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/trace/trace.xml	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/trace/traceMacros.hpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/utilities/bitMap.cpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/utilities/bitMap.hpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/utilities/bitMap.inline.hpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/utilities/debug.cpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/utilities/debug.hpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/utilities/exceptions.cpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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;
@@ -508,12 +508,13 @@
   ResourceMark rm;
   Symbol* message = java_lang_Throwable::detail_message(exception());
   if (message != NULL) {
-    log_info(exceptions)("Exception <%s: %s> (" INTPTR_FORMAT ")\n thrown in %s",
+    log_info(exceptions)("Exception <%s: %s>\n thrown in %s",
                          exception->print_value_string(),
-                         message->as_C_string(), p2i(exception()), tempst.as_string());
+                         message->as_C_string(),
+                         tempst.as_string());
   } else {
-    log_info(exceptions)("Exception <%s> (" INTPTR_FORMAT ")\n thrown in %s",
+    log_info(exceptions)("Exception <%s>\n thrown in %s",
                          exception->print_value_string(),
-                         p2i(exception()), tempst.as_string());
+                         tempst.as_string());
   }
 }
--- a/hotspot/src/share/vm/utilities/globalDefinitions.cpp	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/utilities/globalDefinitions.cpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/utilities/globalDefinitions.hpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/utilities/globalDefinitions_gcc.hpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/utilities/globalDefinitions_sparcWorks.hpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/utilities/globalDefinitions_visCPP.hpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/utilities/globalDefinitions_xlc.hpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/utilities/internalVMTests.cpp	Sat Apr 02 05:39:25 2016 +0200
@@ -67,8 +67,11 @@
   run_unit_test(Test_linked_list);
   run_unit_test(TestChunkedList_test);
   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(Test_log_prefix);
+  run_unit_test(Test_log_big);
+  run_unit_test(Test_logtagset_duplicates);
   run_unit_test(DirectivesParser_test);
   run_unit_test(Test_TempNewSymbol);
 #if INCLUDE_VM_STRUCTS
--- a/hotspot/src/share/vm/utilities/ostream.cpp	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/utilities/ostream.cpp	Sat Apr 02 05:39:25 2016 +0200
@@ -24,8 +24,6 @@
 
 #include "precompiled.hpp"
 #include "compiler/compileLog.hpp"
-#include "gc/shared/gcId.hpp"
-#include "gc/shared/gcId.hpp"
 #include "oops/oop.inline.hpp"
 #include "runtime/arguments.hpp"
 #include "runtime/os.hpp"
@@ -504,7 +502,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 +512,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/ostream.hpp	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/utilities/ostream.hpp	Sat Apr 02 05:39:25 2016 +0200
@@ -29,7 +29,6 @@
 #include "runtime/timer.hpp"
 #include "utilities/globalDefinitions.hpp"
 
-class GCId;
 DEBUG_ONLY(class ResourceMark;)
 
 // Output streams for printing
--- a/hotspot/src/share/vm/utilities/stack.inline.hpp	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/utilities/stack.inline.hpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/utilities/vmError.cpp	Sat Apr 02 05:39:25 2016 +0200
@@ -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/TEST.groups	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/test/TEST.groups	Sat Apr 02 05:39:25 2016 +0200
@@ -52,6 +52,25 @@
 
 hotspot_all = \
   /
+  
+hotspot_compiler = \
+  compiler
+  
+hotspot_gc = \
+  gc
+
+hotspot_runtime = \
+  runtime
+  
+hotspot_serviceability = \
+  serviceability
+  
+hotspot_misc = \
+  / \
+ -:hotspot_compiler \
+ -:hotspot_gc \
+ -:hotspot_runtime \
+ -:hotspot_serviceability
 
 # Full JDK can run all tests
 #
@@ -253,7 +272,7 @@
 hotspot_native_sanity = \
   native_sanity
 
-hotspot_compiler_1 = \
+hotspot_fast_compiler_1 = \
   compiler/arraycopy/ \
   compiler/c1/ \
   compiler/c2/ \
@@ -268,7 +287,7 @@
   -compiler/c2/7070134 \
   -compiler/c2/8004867
   
-hotspot_compiler_2 = \
+hotspot_fast_compiler_2 = \
   compiler/classUnloading/ \
   compiler/codecache/ \
   compiler/codegen/ \
@@ -286,7 +305,7 @@
   -compiler/codegen/7184394 \
   -compiler/codecache/stress
   
-hotspot_compiler_3 = \
+hotspot_fast_compiler_3 = \
   compiler/intrinsics/ \
   compiler/jsr292/ \
   compiler/loopopts/ \
@@ -307,22 +326,27 @@
   -compiler/loopopts/7052494 \
   -compiler/runtime/6826736
 
-hotspot_compiler_closed = \
+hotspot_fast_compiler_closed = \
   sanity/ExecuteInternalVMTests.java
 
-hotspot_gc = \
+hotspot_fast_gc_1 = \
+  gc/g1/
+
+hotspot_fast_gc_2 = \
   sanity/ExecuteInternalVMTests.java \
   gc/ \
-  -gc/g1/TestGreyReclaimedHumongousObjects.java \
+  -gc/g1/ \
+  -gc/survivorAlignment/TestPromotionFromSurvivorToTenuredAfterMinorGC.java \
+  -gc/cms/TestMBeanCMS.java \
   -gc/metaspace/CompressedClassSpaceSizeInJmapHeap.java
 
-hotspot_gc_closed = \
+hotspot_fast_gc_closed = \
   sanity/ExecuteInternalVMTests.java
 
-hotspot_gc_gcold = \
+hotspot_fast_gc_gcold = \
   stress/gc/TestGCOld.java
 
-hotspot_runtime = \
+hotspot_fast_runtime = \
   runtime/ \
  -runtime/ErrorHandling/ErrorHandler.java \
  -runtime/RedefineObject/TestRedefineObject.java \
@@ -334,6 +358,15 @@
  -runtime/memory/ReserveMemory.java \
  -runtime/memory/RunUnitTestsConcurrently.java \
  -runtime/Unsafe/RangeCheck.java \
+ -runtime/SelectionResolution/AbstractMethodErrorTest.java \
+ -runtime/SelectionResolution/IllegalAccessErrorTest.java \
+ -runtime/SelectionResolution/InvokeInterfaceICCE.java \
+ -runtime/SelectionResolution/InvokeInterfaceSuccessTest.java \
+ -runtime/SelectionResolution/InvokeSpecialICCE.java \
+ -runtime/SelectionResolution/InvokeSpecialSuccessTest.java \
+ -runtime/SelectionResolution/InvokeStaticICCE.java \
+ -runtime/SelectionResolution/InvokeVirtualICCE.java \
+ -runtime/SelectionResolution/InvokeVirtualSuccessTest.java \
  -runtime/SharedArchiveFile/CdsSameObjectAlignment.java \
  -runtime/SharedArchiveFile/DefaultUseWithClient.java \
  -runtime/Thread/CancellableThreadTest.java \
@@ -342,21 +375,21 @@
   sanity/ \
   testlibrary_tests/TestMutuallyExclusivePlatformPredicates.java
 
-hotspot_serviceability = \
+hotspot_fast_serviceability = \
   sanity/ExecuteInternalVMTests.java \
   serviceability/dcmd/compiler \
   serviceability/logging
 
 hotspot_jprt = \
-  :hotspot_compiler_1 \
-  :hotspot_compiler_2 \
-  :hotspot_compiler_3 \
-  :hotspot_compiler_closed \
-  :hotspot_gc \
-  :hotspot_gc_closed \
-  :hotspot_gc_gcold \
-  :hotspot_runtime \
-  :hotspot_serviceability
+  :hotspot_fast_compiler_1 \
+  :hotspot_fast_compiler_2 \
+  :hotspot_fast_compiler_3 \
+  :hotspot_fast_compiler_closed \
+  :hotspot_fast_gc \
+  :hotspot_fast_gc_closed \
+  :hotspot_fast_gc_gcold \
+  :hotspot_fast_runtime \
+  :hotspot_fast_serviceability
 
 #All tests that depends on nashorn extension.
 #
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/gc/arguments/TestDisableDefaultGC.java	Sat Apr 02 05:39:25 2016 +0200
@@ -0,0 +1,51 @@
+/*
+ * 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 TestDisableDefaultGC
+ * @summary Test that the VM complains when the default GC is disabled and no other GC is specified
+ * @bug 8068579
+ * @key gc
+ * @library /testlibrary
+ * @requires vm.gc=="null"
+ * @modules java.base/sun.misc
+ *          java.management
+ * @run driver TestDisableDefaultGC
+ */
+
+import jdk.test.lib.ProcessTools;
+import jdk.test.lib.OutputAnalyzer;
+
+public class TestDisableDefaultGC {
+    public static void main(String[] args) throws Exception {
+        // Start VM, disabling all possible default GCs
+        ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-XX:-UseSerialGC",
+                                                                  "-XX:-UseParallelGC",
+                                                                  "-XX:-UseG1GC",
+                                                                  "-XX:-UseConcMarkSweepGC",
+                                                                  "-version");
+        OutputAnalyzer output = new OutputAnalyzer(pb.start());
+        output.shouldMatch("Garbage collector not selected");
+        output.shouldHaveExitValue(1);
+    }
+}
--- a/hotspot/test/gc/arguments/TestMaxHeapSizeTools.java	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/test/gc/arguments/TestMaxHeapSizeTools.java	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/test/gc/arguments/TestMaxMinHeapFreeRatioFlags.java	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/test/gc/arguments/TestSelectDefaultGC.java	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/test/gc/ergonomics/TestDynamicNumberOfGCThreads.java	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/test/gc/g1/TestStringSymbolTableStats.java	Sat Apr 02 05:39:25 2016 +0200
@@ -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());
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/gc/g1/ihop/TestIHOPErgo.java	Sat Apr 02 05:39:25 2016 +0200
@@ -0,0 +1,228 @@
+/*
+ * 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 TestIHOPErgo
+ * @bug 8148397
+ * @summary Test checks that behavior of Adaptive and Static IHOP at concurrent cycle initiation
+ * @requires vm.gc=="G1" | vm.gc=="null"
+ * @requires vm.opt.FlightRecorder != true
+ * @requires vm.opt.ExplicitGCInvokesConcurrent != true
+ * @library /testlibrary /test/lib /
+ * @modules java.management
+ * @build gc.g1.ihop.TestIHOPErgo
+ *        gc.g1.ihop.lib.IhopUtils
+ * @run driver/timeout=480 gc.g1.ihop.TestIHOPErgo
+ */
+package gc.g1.ihop;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
+
+import jdk.test.lib.OutputAnalyzer;
+import jdk.test.lib.ProcessTools;
+
+import gc.g1.ihop.lib.IhopUtils;
+
+/**
+ * The test starts the AppIHOP multiple times varying settings of MaxHeapSize.
+ * The test parses GC log from AppIHOP to check:
+ * - occupancy is not less than threshold for Adaptive and Static IHOP at
+ * concurrent cycle initiation
+ * - Adaptive IHOP prediction was started during AppIHOP executing
+ * - log contains ergonomic messages in log
+ */
+public class TestIHOPErgo {
+
+    // Common GC tune and logging options for test.
+    private final static String[] COMMON_OPTIONS = {
+        "-XX:+UnlockExperimentalVMOptions",
+        "-XX:G1MixedGCLiveThresholdPercent=100",
+        "-XX:G1HeapWastePercent=0",
+        "-XX:MaxGCPauseMillis=30000",
+        "-XX:G1MixedGCCountTarget=1",
+        "-XX:+UseG1GC",
+        "-XX:G1HeapRegionSize=1m",
+        "-XX:+G1UseAdaptiveIHOP",
+        "-Xlog:gc+ihop=debug,gc+ihop+ergo=debug,gc+ergo=debug",
+        "-XX:+AlwaysTenure",
+        "-XX:G1AdaptiveIHOPNumInitialSamples=1",
+        "-XX:InitiatingHeapOccupancyPercent=30"
+    };
+
+    public static void main(String[] args) throws Throwable {
+
+        // heap size MB, sleep time for allocator, true/false for adaptive/static
+        runTest(64, 0, false);
+        runTest(64, 100, false);
+        runTest(128, 100, false);
+        runTest(256, 50, false);
+        runTest(512, 30, false);
+        runTest(64, 50, true);
+        runTest(128, 200, true);
+        runTest(256, 100, true);
+        runTest(512, 50, true);
+    }
+
+    /**
+     * Runs AppIHOP in separate VM and checks GC log.
+     *
+     * @param heapSize       heap size
+     * @param sleepTime      sleep time between memory allocations.
+     * @param isIhopAdaptive true forAdaptive IHOP, false for Static
+     *
+     * @throws Throwable
+     */
+    private static void runTest(int heapSize, int sleepTime, boolean isIhopAdaptive) throws Throwable {
+        System.out.println("IHOP test:");
+        System.out.println("  MaxHeapSize : " + heapSize);
+
+        List<String> options = new ArrayList<>();
+        Collections.addAll(options,
+                "-Dheap.size=" + heapSize,
+                "-Dsleep.time=" + sleepTime,
+                "-XX:MaxHeapSize=" + heapSize + "M",
+                "-XX:NewSize=" + heapSize / 8 + "M",
+                "-XX:MaxNewSize=" + heapSize / 8 + "M",
+                "-XX:InitialHeapSize=" + heapSize + "M",
+                "-XX:" + (isIhopAdaptive ? "+" : "-") + "G1UseAdaptiveIHOP"
+        );
+
+        Collections.addAll(options, COMMON_OPTIONS);
+        options.add(AppIHOP.class.getName());
+        OutputAnalyzer out = executeTest(options);
+
+        // Checks that log contains message which indicates that IHOP prediction is active
+        if (isIhopAdaptive) {
+            IhopUtils.checkAdaptiveIHOPWasActivated(out);
+        }
+        // Checks that log contains messages which indicates that VM initiates/checks heap occupancy
+        // and tries to start concurrent cycle.
+        IhopUtils.checkErgoMessagesExist(out);
+
+        // Checks threshold and occupancy values
+        IhopUtils.checkIhopLogValues(out);
+    }
+
+    private static OutputAnalyzer executeTest(List<String> options) throws Throwable, RuntimeException {
+        OutputAnalyzer out;
+        out = ProcessTools.executeTestJvm(options.toArray(new String[options.size()]));
+        if (out.getExitValue() != 0) {
+            System.out.println(out.getOutput());
+            throw new RuntimeException("AppIHOP failed with exit code" + out.getExitValue());
+        }
+        return out;
+    }
+
+    /**
+     * The AppIHOP fills 60% of heap and allocates and frees 30% of existing
+     * heap 'iterations' times to achieve IHOP activation. To be executed in
+     * separate VM. Expected properties:
+     * heap.size - heap size which is used to calculate amount of memory
+     *             to be allocated and freed
+     * sleep.time - short pause between filling each MB
+     */
+    public static class AppIHOP {
+
+        public final static LinkedList<Object> GARBAGE = new LinkedList<>();
+
+        private final int ITERATIONS = 10;
+        private final int OBJECT_SIZE = 100000;
+        // 60% of the heap will be filled before test cycles.
+        // 30% of the heap will be filled and freed during test cycle.
+        private final long HEAP_PREALLOC_PCT = 60;
+        private final long HEAP_ALLOC_PCT = 30;
+        private final long HEAP_SIZE;
+        // Amount of memory to be allocated before iterations start
+        private final long HEAP_PREALLOC_SIZE;
+        // Amount of memory to be allocated and freed during iterations
+        private final long HEAP_ALLOC_SIZE;
+        private final int SLEEP_TIME;
+
+        public static void main(String[] args) throws InterruptedException {
+            new AppIHOP().start();
+        }
+
+        AppIHOP() {
+            HEAP_SIZE = Integer.getInteger("heap.size") * 1024 * 1024;
+            SLEEP_TIME = Integer.getInteger("sleep.time");
+
+            HEAP_PREALLOC_SIZE = HEAP_SIZE * HEAP_PREALLOC_PCT / 100;
+            HEAP_ALLOC_SIZE = HEAP_SIZE * HEAP_ALLOC_PCT / 100;
+        }
+
+        public void start() throws InterruptedException {
+            fill(HEAP_PREALLOC_SIZE);
+            fillAndFree(HEAP_ALLOC_SIZE, ITERATIONS);
+        }
+
+        /**
+         * Fills allocationSize bytes of garbage.
+         *
+         * @param allocationSize amount of garbage
+         */
+        private void fill(long allocationSize) {
+            long allocated = 0;
+            while (allocated < allocationSize) {
+                GARBAGE.addFirst(new byte[OBJECT_SIZE]);
+                allocated += OBJECT_SIZE;
+            }
+        }
+
+        /**
+         * Allocates allocationSize bytes of garbage. Performs a short pauses
+         * during allocation. Frees allocated garbage.
+         *
+         * @param allocationSize amount of garbage per iteration
+         * @param iterations     iteration count
+         *
+         * @throws InterruptedException
+         */
+        private void fillAndFree(long allocationSize, int iterations) throws InterruptedException {
+
+            for (int i = 0; i < iterations; ++i) {
+                System.out.println("Iteration:" + i);
+                long allocated = 0;
+                long counter = 0;
+                while (allocated < allocationSize) {
+                    GARBAGE.addFirst(new byte[OBJECT_SIZE]);
+                    allocated += OBJECT_SIZE;
+                    counter += OBJECT_SIZE;
+                    if (counter > 1024 * 1024) {
+                        counter = 0;
+                        if (SLEEP_TIME != 0) {
+                            Thread.sleep(SLEEP_TIME);
+                        }
+                    }
+                }
+                long removed = 0;
+                while (removed < allocationSize) {
+                    GARBAGE.removeLast();
+                    removed += OBJECT_SIZE;
+                }
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/gc/g1/ihop/TestIHOPStatic.java	Sat Apr 02 05:39:25 2016 +0200
@@ -0,0 +1,199 @@
+/*
+ * 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 TestIHOPStatic
+ * @bug 8148397
+ * @summary Test checks concurrent cycle initiation which depends on IHOP value.
+ * @requires vm.gc=="G1" | vm.gc=="null"
+ * @requires vm.opt.FlightRecorder != true
+ * @requires vm.opt.ExplicitGCInvokesConcurrent != true
+ * @library /testlibrary /
+ * @modules java.management
+ * @build gc.g1.ihop.TestIHOPStatic
+ *        gc.g1.ihop.lib.IhopUtils
+ * @run driver/timeout=240 gc.g1.ihop.TestIHOPStatic
+ */
+package gc.g1.ihop;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import jdk.test.lib.OutputAnalyzer;
+import jdk.test.lib.ProcessTools;
+import jdk.test.lib.Utils;
+
+import gc.g1.ihop.lib.IhopUtils;
+
+/**
+ * The test starts the AppIHOP multiple times varying setting of MaxHeapSize,
+ * IHOP and amount of memory to allocate. Then the test parses the GC log from
+ * the app to check that Concurrent Mark Cycle was initiated only if needed
+ * and at the right moment, defined by IHOP setting.
+ */
+public class TestIHOPStatic {
+
+    final static long YOUNG_SIZE = 8 * 1024 * 1024;
+
+    private final static String[] COMMON_OPTIONS = {
+        "-XX:+UseG1GC",
+        "-XX:G1HeapRegionSize=1m",
+        "-XX:-G1UseAdaptiveIHOP",
+        "-XX:NewSize=" + YOUNG_SIZE,
+        "-XX:MaxNewSize=" + YOUNG_SIZE,
+        "-Xlog:gc+ihop+ergo=debug,gc*=debug"
+    };
+
+    public static void main(String[] args) throws Throwable {
+
+        // Test case:
+        // IHOP value, heap occupancy, heap size, expectation of message
+        // Test cases for occupancy is greater than IHOP
+        runTest(30, 35, 64, true);
+        runTest(50, 55, 256, true);
+        runTest(60, 65, 64, true);
+        runTest(70, 75, 512, true);
+
+        // Test cases for big difference between occupancy and IHOP
+        runTest(30, 50, 256, true);
+        runTest(30, 70, 512, true);
+        runTest(50, 70, 256, true);
+
+        // Test cases for occupancy is less than IHOP
+        runTest(30, 25, 64, false);
+        runTest(50, 45, 256, false);
+        runTest(70, 65, 64, false);
+        runTest(70, 65, 512, false);
+
+        // Test cases for big difference between occupancy and IHOP
+        runTest(50, 30, 300, false);
+        runTest(70, 50, 160, false);
+
+        // Cases for 0 and 100 IHOP.
+        runTest(0, 50, 256, true);
+        runTest(0, 95, 512, true);
+        runTest(100, 20, 64, false);
+        runTest(100, 100, 512, false);
+    }
+
+    /**
+     * Runs the test case.
+     *
+     * @param ihop                    IHOP value
+     * @param pctToFill               heap percentage to be filled
+     * @param heapSize                heap size for test
+     * @param expectInitiationMessage
+     *                                true - concurrent cycle initiation message is expected
+     *                                false - message is not expected
+     *
+     * @throws Throwable
+     */
+    private static void runTest(int ihop, long pctToFill, long heapSize, boolean expectInitiationMessage) throws Throwable {
+        System.out.println("");
+        System.out.println("IHOP test:");
+        System.out.println("  InitiatingHeapOccupancyPercent : " + ihop);
+        System.out.println("  Part of heap to fill (percentage) : " + pctToFill);
+        System.out.println("  MaxHeapSize : " + heapSize);
+        System.out.println("  Expect for concurrent cycle initiation message : " + expectInitiationMessage);
+        List<String> options = new ArrayList<>();
+        Collections.addAll(options, Utils.getTestJavaOpts());
+        Collections.addAll(options,
+                "-XX:InitiatingHeapOccupancyPercent=" + ihop,
+                "-Dmemory.fill=" + (heapSize * 1024 * 1024 * pctToFill / 100),
+                "-XX:MaxHeapSize=" + heapSize + "M",
+                "-XX:InitialHeapSize=" + heapSize + "M"
+        );
+        Collections.addAll(options, COMMON_OPTIONS);
+        options.add(AppIHOP.class.getName());
+
+        OutputAnalyzer out = ProcessTools.executeTestJvm(options.toArray(new String[options.size()]));
+
+        if (out.getExitValue() != 0) {
+            System.out.println(out.getOutput());
+            throw new RuntimeException("IhopTest failed with exit code " + out.getExitValue());
+        }
+
+        checkResult(out, expectInitiationMessage);
+    }
+
+    /**
+     * Checks execution results to ensure that concurrent cycle was initiated or
+     * was not.
+     *
+     * @param out
+     * @param expectInitiationMessage true - test expects for concurrent cycle initiation.
+     *                                false - test does not expect for concurrent cycle initiation
+     */
+    private static void checkResult(OutputAnalyzer out, boolean expectInitiationMessage) {
+        // Find expected messages
+        List<String> logItems = IhopUtils.getErgoInitiationMessages(out);
+
+        // Concurrent cycle was not initiated but was expected.
+        if (logItems.isEmpty() && expectInitiationMessage) {
+            System.out.println(out.getOutput());
+            throw new RuntimeException("Concurrent cycle was not initiated.");
+        }
+        IhopUtils.checkIhopLogValues(out);
+    }
+
+    static class AppIHOP {
+
+        /**
+         * Simple class which fills part of memory and initiates GC.
+         * To be executed in separate VM.
+         * Expect next VM properties to be set:
+         * memory.fill - amount of garbage to be created.
+         */
+        private static final long MEMORY_TO_FILL = Integer.getInteger("memory.fill");
+        private final static int CHUNK_SIZE = 10000;
+
+        public final static ArrayList<Object> STORAGE = new ArrayList<>();
+
+        public static void main(String[] args) throws InterruptedException {
+
+            // Calculate part of heap to be filled to achieve expected occupancy.
+            System.out.println("Mem to fill:" + MEMORY_TO_FILL);
+            if (MEMORY_TO_FILL <= 0) {
+                throw new RuntimeException("Wrong memory size: " + MEMORY_TO_FILL);
+            }
+            try {
+                createGarbage(MEMORY_TO_FILL);
+            } catch (OutOfMemoryError oome) {
+                return;
+            }
+            // Concurrent cycle initiation should start at end of Young GC cycle.
+            // Will fill entire young gen with garbage to guarantee that Young GC was initiated.
+            try {
+                createGarbage(TestIHOPStatic.YOUNG_SIZE);
+            } catch (OutOfMemoryError oome) {
+            }
+        }
+
+        private static void createGarbage(long memToFill) {
+            for (long i = 0; i < memToFill / CHUNK_SIZE; i++) {
+                STORAGE.add(new byte[CHUNK_SIZE]);
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/gc/g1/ihop/lib/IhopUtils.java	Sat Apr 02 05:39:25 2016 +0200
@@ -0,0 +1,144 @@
+/*
+ * 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.
+ */
+package gc.g1.ihop.lib;
+
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+import jdk.test.lib.OutputAnalyzer;
+
+
+/**
+ * Utility class to extract IHOP related information from the GC log.
+ * The class provides a number of static method to be used from tests.
+ */
+public class IhopUtils {
+
+    // Examples of GC log for IHOP:
+    // [0.402s][debug][gc,ergo,ihop] GC(9) Do not request concurrent cycle initiation (still doing mixed collections) occupancy: 66060288B allocation request: 0B threshold: 59230757B (88.26) source: end of GC
+    // [0.466s][debug][gc,ergo,ihop] GC(18) Request concurrent cycle initiation (occupancy higher than threshold) occupancy: 52428800B allocation request: 0B threshold: 0B (0.00) source: end of GC
+
+    /**
+     * Patterns are used for extracting occupancy and threshold from GC log.
+     */
+    private final static Pattern OCCUPANCY = Pattern.compile("occupancy: (\\d+)B");
+    private final static Pattern THRESHOLD = Pattern.compile("threshold: (\\d+)B");
+
+    /**
+     * Messages related to concurrent cycle initiation.
+     */
+    private final static String CYCLE_INITIATION_MESSAGE = "Request concurrent cycle initiation (occupancy higher than threshold)";
+    private final static String CYCLE_INITIATION_MESSAGE_FALSE = "Do not request concurrent cycle initiation (still doing mixed collections)";
+    private final static String ADAPTIVE_IHOP_PREDICTION_ACTIVE_MESSAGE = "prediction active: true";
+
+    /**
+     * Finds strings which contains patterns for finding.
+     *
+     * @param outputAnalyzer List of string for IHOP messages extraction
+     * @param stringsToFind Strings which is checked for matching with OutputAnalyzer content
+     * @return List of strings which were matched.
+     */
+    private static List<String> findInLog(OutputAnalyzer outputAnalyzer, String... stringsToFind) {
+        return outputAnalyzer.asLines().stream()
+                .filter(string -> {
+                    return Stream.of(stringsToFind)
+                            .filter(find -> string.contains(find))
+                            .findAny()
+                            .isPresent();
+                })
+                .collect(Collectors.toList());
+    }
+
+    /**
+     * Checks that memory occupancy is greater or equal to the threshold.
+     * This methods searches for occupancy and threshold in the GC log corresponding Conc Mark Cycle initiation
+     * and compare their values.If no CMC initiation happens, does nothing.
+     * @param outputAnalyzer OutputAnalyzer which contains GC log to be checked
+     * @throw RuntimeException If check fails
+     */
+    public static void checkIhopLogValues(OutputAnalyzer outputAnalyzer) {
+        // Concurrent cycle was initiated but was not expected.
+        // Checks occupancy should be greater than threshold.
+        List<String> logItems = IhopUtils.getErgoMessages(outputAnalyzer);
+        logItems.stream()
+                .forEach(item -> {
+                    long occupancy = IhopUtils.getLongByPattern(item, IhopUtils.OCCUPANCY);
+                    long threshold = IhopUtils.getLongByPattern(item, IhopUtils.THRESHOLD);
+                    if (occupancy < threshold) {
+                        System.out.println(outputAnalyzer.getOutput());
+                        throw new RuntimeException("Concurrent cycle initiation is unexpected. Occupancy (" + occupancy + ") is less then threshold (" + threshold + ")");
+                    }
+                    System.out.printf("Concurrent cycle was initiated with occupancy = %d and threshold = %d%n", occupancy, threshold);
+                });
+    }
+
+    private static Long getLongByPattern(String line, Pattern pattern) {
+        Matcher number = pattern.matcher(line);
+        if (number.find()) {
+            return Long.parseLong(number.group(1));
+        }
+        System.out.println(line);
+        throw new RuntimeException("Cannot find Long in string.");
+    }
+
+    /**
+     * Finds concurrent cycle initiation messages.
+     * @param outputAnalyzer OutputAnalyzer
+     * @return List with messages which were found.
+     */
+    public static List<String> getErgoInitiationMessages(OutputAnalyzer outputAnalyzer) {
+        return IhopUtils.findInLog(outputAnalyzer, CYCLE_INITIATION_MESSAGE);
+    }
+
+    /**
+     * Gets IHOP ergo messages from GC log.
+     * @param outputAnalyzer
+     * @return List with found messages
+     */
+    private static List<String> getErgoMessages(OutputAnalyzer outputAnalyzer) {
+        return IhopUtils.findInLog(outputAnalyzer, CYCLE_INITIATION_MESSAGE, CYCLE_INITIATION_MESSAGE_FALSE);
+    }
+
+    /**
+     * Checks that GC log contains expected ergonomic messages
+     * @param outputAnalyzer OutputAnalyer with GC log for checking
+     * @throws RuntimeException If no IHOP ergo messages were not found
+     */
+    public static void checkErgoMessagesExist(OutputAnalyzer outputAnalyzer) {
+        String output = outputAnalyzer.getOutput();
+        if (!(output.contains(CYCLE_INITIATION_MESSAGE) | output.contains(CYCLE_INITIATION_MESSAGE_FALSE))) {
+            throw new RuntimeException("Cannot find expected IHOP ergonomics messages");
+        }
+    }
+
+    /**
+     * Checks that adaptive IHOP was activated
+     * @param outputAnalyzer OutputAnalyer with GC log for checking
+     * @throws RuntimeException If IHOP message was not found.
+     */
+    public static void checkAdaptiveIHOPWasActivated(OutputAnalyzer outputAnalyzer) {
+        outputAnalyzer.shouldContain(ADAPTIVE_IHOP_PREDICTION_ACTIVE_MESSAGE);
+    }
+}
--- a/hotspot/test/gc/g1/plab/TestPLABPromotion.java	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/test/gc/g1/plab/TestPLABPromotion.java	Sat Apr 02 05:39:25 2016 +0200
@@ -41,17 +41,16 @@
 package gc.g1.plab;
 
 import java.util.List;
-import java.util.Map;
 import java.util.Arrays;
 import java.io.PrintStream;
 
 import gc.g1.plab.lib.AppPLABPromotion;
 import gc.g1.plab.lib.LogParser;
 import gc.g1.plab.lib.PLABUtils;
+import gc.g1.plab.lib.PlabInfo;
 
 import jdk.test.lib.OutputAnalyzer;
 import jdk.test.lib.ProcessTools;
-import jdk.test.lib.Platform;
 
 /**
  * Test checks PLAB promotion of different size objects.
@@ -63,6 +62,12 @@
     // GC ID with old PLAB statistics
     private final static long GC_ID_OLD_STATS = 2l;
 
+    private final static String PLAB_USED_FIELD_NAME = "used";
+    private final static String PLAB_DIRECT_ALLOCATED_FIELD_NAME = "direct allocated";
+    private final static List<String> FIELDS_TO_EXTRACT = Arrays.asList(PLAB_USED_FIELD_NAME, PLAB_DIRECT_ALLOCATED_FIELD_NAME);
+
+    private static String output;
+
     // Allowable difference for memory consumption (percentage)
     private final static long MEM_DIFFERENCE_PCT = 5;
 
@@ -120,11 +125,12 @@
                 System.out.println(out.getOutput());
                 throw new RuntimeException("Expect exit code 0.");
             }
-            checkResults(out.getOutput(), testCase);
+            output = out.getOutput();
+            checkResults(testCase);
         }
     }
 
-    private static void checkResults(String output, TestCase testCase) {
+    private static void checkResults(TestCase testCase) {
         long plabAllocatedSurvivor;
         long directAllocatedSurvivor;
         long plabAllocatedOld;
@@ -132,65 +138,89 @@
         long memAllocated = testCase.getMemToFill();
         LogParser logParser = new LogParser(output);
 
-        Map<String, Long> survivorStats = getPlabStats(logParser, LogParser.ReportType.SURVIVOR_STATS, GC_ID_SURVIVOR_STATS);
-        Map<String, Long> oldStats = getPlabStats(logParser, LogParser.ReportType.OLD_STATS, GC_ID_OLD_STATS);
+        PlabInfo survivorPlabInfo = logParser.getSpecifiedStats(GC_ID_SURVIVOR_STATS, LogParser.ReportType.SURVIVOR_STATS, FIELDS_TO_EXTRACT);
+        PlabInfo oldPlabInfo = logParser.getSpecifiedStats(GC_ID_OLD_STATS, LogParser.ReportType.OLD_STATS, FIELDS_TO_EXTRACT);
 
-        plabAllocatedSurvivor = survivorStats.get("used");
-        directAllocatedSurvivor = survivorStats.get("direct allocated");
-        plabAllocatedOld = oldStats.get("used");
-        directAllocatedOld = oldStats.get("direct allocated");
+        checkFields(survivorPlabInfo);
+        checkFields(oldPlabInfo);
+
+        plabAllocatedSurvivor = survivorPlabInfo.get(PLAB_USED_FIELD_NAME);
+        directAllocatedSurvivor = survivorPlabInfo.get(PLAB_DIRECT_ALLOCATED_FIELD_NAME);
+        plabAllocatedOld = oldPlabInfo.get(PLAB_USED_FIELD_NAME);
+        directAllocatedOld = oldPlabInfo.get(PLAB_DIRECT_ALLOCATED_FIELD_NAME);
 
         System.out.printf("Survivor PLAB allocated:%17d Direct allocated: %17d Mem consumed:%17d%n", plabAllocatedSurvivor, directAllocatedSurvivor, memAllocated);
         System.out.printf("Old      PLAB allocated:%17d Direct allocated: %17d Mem consumed:%17d%n", plabAllocatedOld, directAllocatedOld, memAllocated);
 
         // Unreachable objects case
         if (testCase.isDeadObjectCase()) {
-            // No dead objects should be promoted
-            if (!(checkRatio(plabAllocatedSurvivor, memAllocated) && checkRatio(directAllocatedSurvivor, memAllocated))) {
-                System.out.println(output);
-                throw new RuntimeException("Unreachable objects should not be allocated using PLAB or direct allocated to Survivor");
-            }
-            if (!(checkRatio(plabAllocatedOld, memAllocated) && checkRatio(directAllocatedOld, memAllocated))) {
-                System.out.println(output);
-                throw new RuntimeException("Unreachable objects should not be allocated using PLAB or direct allocated to Old");
-            }
+            checkDeadObjectsPromotion(plabAllocatedSurvivor, directAllocatedSurvivor, memAllocated);
+            checkDeadObjectsPromotion(plabAllocatedOld, directAllocatedOld, memAllocated);
+
         } else {
             // Live objects case
             if (testCase.isPromotedByPLAB()) {
-                // All live small objects should be promoted using PLAB
-                if (!checkDifferenceRatio(plabAllocatedSurvivor, memAllocated)) {
-                    System.out.println(output);
-                    throw new RuntimeException("Expect that Survivor PLAB allocation are similar to all mem consumed");
-                }
-                if (!checkDifferenceRatio(plabAllocatedOld, memAllocated)) {
-                    System.out.println(output);
-                    throw new RuntimeException("Expect that Old PLAB allocation are similar to all mem consumed");
-                }
+                checkLiveObjectsPromotion(plabAllocatedSurvivor, memAllocated, "Expect that Survivor PLAB allocation are similar to all mem consumed");
+                checkLiveObjectsPromotion(plabAllocatedOld, memAllocated, "Expect that Old PLAB allocation are similar to all mem consumed");
             } else {
                 // All big objects should be directly allocated
-                if (!checkDifferenceRatio(directAllocatedSurvivor, memAllocated)) {
-                    System.out.println(output);
-                    throw new RuntimeException("Test fails. Expect that Survivor direct allocation are similar to all mem consumed");
-                }
-                if (!checkDifferenceRatio(directAllocatedOld, memAllocated)) {
-                    System.out.println(output);
-                    throw new RuntimeException("Test fails. Expect that Old direct allocation are similar to all mem consumed");
-                }
+                checkLiveObjectsPromotion(directAllocatedSurvivor, memAllocated, "Expect that Survivor direct allocation are similar to all mem consumed");
+                checkLiveObjectsPromotion(directAllocatedOld, memAllocated, "Expect that Old direct allocation are similar to all mem consumed");
             }
 
-            // All promoted objects size should be similar to all consumed memory
-            if (!checkDifferenceRatio(plabAllocatedSurvivor + directAllocatedSurvivor, memAllocated)) {
-                System.out.println(output);
-                throw new RuntimeException("Test fails. Expect that Survivor gen total allocation are similar to all mem consumed");
-            }
-            if (!checkDifferenceRatio(plabAllocatedOld + directAllocatedOld, memAllocated)) {
-                System.out.println(output);
-                throw new RuntimeException("Test fails. Expect that Old gen total allocation are similar to all mem consumed");
-            }
+            checkTotalPromotion(plabAllocatedSurvivor, directAllocatedSurvivor, memAllocated, "Expect that Survivor gen total allocation are similar to all mem consumed");
+            checkTotalPromotion(plabAllocatedOld, directAllocatedOld, memAllocated, "Expect that Old gen total allocation are similar to all mem consumed");
         }
         System.out.println("Test passed!");
     }
 
+    private static void checkTotalPromotion(long plabAllocatedSurvivor, long directAllocatedSurvivor, long memAllocated, String exceptionMessage) {
+        // All promoted objects size should be similar to all consumed memory
+        if (!checkDifferenceRatio(plabAllocatedSurvivor + directAllocatedSurvivor, memAllocated)) {
+            System.out.println(output);
+            throw new RuntimeException(exceptionMessage);
+        }
+    }
+
+    /**
+     * Checks that live objects were promoted as expected.
+     * @param plabAllocated
+     * @param totalMemAllocated
+     * @param exceptionMessage
+     */
+    private static void checkLiveObjectsPromotion(long plabAllocated, long totalMemAllocated, String exceptionMessage) {
+        // All live small objects should be promoted using PLAB
+        if (!checkDifferenceRatio(plabAllocated, totalMemAllocated)) {
+            System.out.println(output);
+            throw new RuntimeException(exceptionMessage);
+        }
+    }
+
+    /**
+     * Checks that dead objects are not promoted.
+     * @param plabPromoted promoted by PLAB
+     * @param directlyPromoted
+     * @param memoryAllocated total memory allocated
+     */
+    private static void checkDeadObjectsPromotion(long plabPromoted, long directlyPromoted, long memoryAllocated) {
+        // No dead objects should be promoted
+        if (!(checkRatio(plabPromoted, memoryAllocated) && checkRatio(directlyPromoted, memoryAllocated))) {
+            System.out.println(output);
+            throw new RuntimeException("Unreachable objects should not be allocated using PLAB or directly allocated to Survivor/Old");
+        }
+    }
+
+    /**
+     * Checks that PLAB statistics contains expected fields.
+     * @param info
+     */
+    private static void checkFields(PlabInfo info) {
+        if (!info.checkFields(FIELDS_TO_EXTRACT)) {
+            System.out.println(output);
+            throw new RuntimeException("PLAB log does not contain expected fields");
+        }
+    }
+
     /**
      * Returns true if checkedValue is less than MEM_DIFFERENCE_PCT percent of controlValue.
      *
@@ -215,14 +245,6 @@
         return (Math.abs(checkedValue - controlValue) / controlValue) * 100L < MEM_DIFFERENCE_PCT;
     }
 
-    private static Map<String, Long> getPlabStats(LogParser logParser, LogParser.ReportType type, long gc_id) {
-
-        Map<String, Long> survivorStats = logParser.getEntries()
-                .get(gc_id)
-                .get(type);
-        return survivorStats;
-    }
-
     /**
      * Description of one test case.
      */
--- a/hotspot/test/gc/g1/plab/TestPLABResize.java	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/test/gc/g1/plab/TestPLABResize.java	Sat Apr 02 05:39:25 2016 +0200
@@ -35,23 +35,21 @@
  *        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
  */
 package gc.g1.plab;
 
-import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
-import java.util.Map;
 import java.util.stream.Collectors;
 import java.io.PrintStream;
 
 import gc.g1.plab.lib.LogParser;
 import gc.g1.plab.lib.PLABUtils;
 import gc.g1.plab.lib.AppPLABResize;
+import gc.g1.plab.lib.PlabReport;
 
 import jdk.test.lib.OutputAnalyzer;
 import jdk.test.lib.ProcessTools;
@@ -75,6 +73,8 @@
     private static final int ITERATIONS_MEDIUM = 5;
     private static final int ITERATIONS_HIGH = 8;
 
+    private static final String PLAB_SIZE_FIELD_NAME = "actual";
+
     private final static TestCase[] TEST_CASES = {
         new TestCase(WASTE_PCT_SMALL, OBJECT_SIZE_SMALL, GC_NUM_SMALL, ITERATIONS_MEDIUM),
         new TestCase(WASTE_PCT_SMALL, OBJECT_SIZE_MEDIUM, GC_NUM_HIGH, ITERATIONS_SMALL),
@@ -110,41 +110,33 @@
      */
     private static void checkResults(String output, TestCase testCase) {
         final LogParser log = new LogParser(output);
-        final Map<Long, Map<LogParser.ReportType, Map<String, Long>>> entries = log.getEntries();
+        final PlabReport report = log.getEntries();
 
-        final ArrayList<Long> plabSizes = entries.entrySet()
-                .stream()
-                .map(item -> {
-                    return item.getValue()
-                            .get(LogParser.ReportType.SURVIVOR_STATS)
-                            .get("actual");
-                })
-                .collect(Collectors.toCollection(ArrayList::new));
+        final List<Long> plabSizes = report.entryStream()
+                .map(item -> item.getValue()
+                        .get(LogParser.ReportType.SURVIVOR_STATS)
+                        .get(PLAB_SIZE_FIELD_NAME)
+                )
+                .collect(Collectors.toList());
 
         // 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 +187,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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/test/gc/g1/plab/lib/AppPLABResize.java	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/test/gc/g1/plab/lib/LogParser.java	Sat Apr 02 05:39:25 2016 +0200
@@ -22,13 +22,15 @@
  */
 package gc.g1.plab.lib;
 
-import java.util.EnumMap;
+import java.util.Arrays;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 import java.util.Optional;
 import java.util.Scanner;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
+import java.util.stream.Collectors;
 
 /**
  * LogParser class parses VM output to get PLAB and ConsumptionStats values.
@@ -44,9 +46,6 @@
  */
 final public class LogParser {
 
-    // Name for GC ID field in report.
-    public final static String GC_ID = "gc_id";
-
     /**
      * Type of parsed log element.
      */
@@ -57,7 +56,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 PlabReport report;
 
     // GC ID
     private static final Pattern GC_ID_PATTERN = Pattern.compile("\\[gc,plab\\s*\\] GC\\((\\d+)\\)");
@@ -65,7 +65,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,71 +74,123 @@
             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 PlabReport getEntries() {
+        return report;
     }
 
-    private Map<Long,Map<ReportType, Map<String,Long>>> parseLines() throws NumberFormatException {
+    private PlabReport parseLines() throws NumberFormatException {
         Scanner lineScanner = new Scanner(log);
-        Map<Long,Map<ReportType, Map<String,Long>>> allocationStatistics = new HashMap<>();
+        PlabReport plabReport = new PlabReport();
         Optional<Long> gc_id;
         while (lineScanner.hasNextLine()) {
             String line = lineScanner.nextLine();
-            gc_id = getGcId(line);
-            if ( gc_id.isPresent() ) {
+            gc_id = getGcId(line, GC_ID_PATTERN);
+            if (gc_id.isPresent()) {
                 Matcher matcher = PAIRS_PATTERN.matcher(line);
                 if (matcher.find()) {
-                    Map<ReportType,Map<String, Long>> oneReportItem;
-                    ReportType reportType;
-
-                    if (!allocationStatistics.containsKey(gc_id.get())) {
-                      allocationStatistics.put(gc_id.get(), new EnumMap<>(ReportType.class));
+                    if (!plabReport.containsKey(gc_id.get())) {
+                        plabReport.put(gc_id.get(), new PlabGCStatistics());
                     }
+                    ReportType reportType = line.contains("Young") ? ReportType.SURVIVOR_STATS : ReportType.OLD_STATS;
 
-                    if ( line.contains("Young") ) {
-                        reportType = ReportType.SURVIVOR_STATS;
-                    } else {
-                        reportType = ReportType.OLD_STATS;
-                    }
-
-                    oneReportItem = allocationStatistics.get(gc_id.get());
-                    if (!oneReportItem.containsKey(reportType)) {
-                      oneReportItem.put(reportType,new HashMap<String, Long>());
+                    PlabGCStatistics gcStat = plabReport.get(gc_id.get());
+                    if (!gcStat.containsKey(reportType)) {
+                        gcStat.put(reportType, new PlabInfo());
                     }
 
                     // Extract all pairs from log.
-                    Map<String, Long> plabStats = oneReportItem.get(reportType);
+                    PlabInfo plabInfo = gcStat.get(reportType);
                     do {
                         String pair = matcher.group();
                         String[] nameValue = pair.replaceAll(": ", ":").split(":");
-                        plabStats.put(nameValue[0].trim(), Long.parseLong(nameValue[1]));
+                        plabInfo.put(nameValue[0].trim(), Long.parseLong(nameValue[1]));
                     } while (matcher.find());
                 }
             }
         }
-        return allocationStatistics;
+        return plabReport;
     }
 
-    private Optional<Long> getGcId(String line) {
-        Matcher number = GC_ID_PATTERN.matcher(line);
+    private static Optional<Long> getGcId(String line, Pattern pattern) {
+        Matcher number = pattern.matcher(line);
         if (number.find()) {
             return Optional.of(Long.parseLong(number.group(1)));
         }
         return Optional.empty();
     }
+
+    /**
+     * Extracts GC ID from log.
+     *
+     * @param line - one line of log.
+     * @return GC ID
+     */
+    public static Long getGcIdFromLine(String line, Pattern pattern) {
+        Optional<Long> gcId = getGcId(line, pattern);
+        if (!gcId.isPresent()) {
+            System.out.println(line);
+            throw new RuntimeException("Cannot find GC ID in log.");
+        }
+        return gcId.get();
+    }
+
+    /**
+     * Returns Map<Long,PlabStatistics> which contains specified statistics for specified gc ids.
+     * @param specifiedGcId gc id to get
+     * @param type PLAB type
+     * @param fieldsName name of fields in PlabStatistics
+     * @return
+     **/
+    public Map<Long, PlabInfo> getSpecifiedStats(List<Long> specifiedGcId, LogParser.ReportType type, List<String> fieldsName) {
+        return getSpecifiedStats(specifiedGcId, type, fieldsName, true);
+    }
+
+    /**
+     * Returns PlabStatistics for specified GC ID.
+     * @param specifiedGcId
+     * @param type type of statistics
+     * @param fieldsName name of fields in PlabStatistics
+     * @return
+     **/
+    public PlabInfo getSpecifiedStats(long specifiedGcId, LogParser.ReportType type, List<String> fieldsName) {
+        return getSpecifiedStats(Arrays.asList(specifiedGcId), type, fieldsName, true).get(specifiedGcId);
+    }
+
+    /**
+     * Returns Map<Long,PlabStatistics> which contains specified statistics. Filters out specified gc ids.
+     * @param specifiedGcIdForExclude
+     * @param type
+     * @param fieldsName
+     * @return
+     **/
+    public Map<Long, PlabInfo> getExcludedSpecifiedStats(List<Long> specifiedGcIdForExclude, LogParser.ReportType type, List<String> fieldsName) {
+        return getSpecifiedStats(specifiedGcIdForExclude, type, fieldsName, false);
+    }
+
+    private Map<Long, PlabInfo> getSpecifiedStats(List<Long> gcIds, LogParser.ReportType type, List<String> fieldNames, boolean extractId) {
+        return new HashMap<>(
+                getEntries().entryStream()
+                .filter(gcLogItem -> extractId == gcIds.contains(gcLogItem.getKey()))
+                .collect(Collectors.toMap(gcLogItem -> gcLogItem.getKey(),
+                                gcLogItem -> gcLogItem.getValue().get(type).filter(fieldNames)
+                        )
+                )
+        );
+    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/gc/g1/plab/lib/PlabGCStatistics.java	Sat Apr 02 05:39:25 2016 +0200
@@ -0,0 +1,68 @@
+/*
+ * 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.
+ */
+package gc.g1.plab.lib;
+
+import java.util.EnumMap;
+import java.util.Map;
+
+import gc.g1.plab.lib.LogParser.ReportType;
+
+/**
+ * Class that represents PLAB statistics for a single GC.
+ * It includes both Survivor and Old PLAB statistics.
+ */
+public class PlabGCStatistics {
+
+    private final Map<ReportType, PlabInfo> plabGCStatistics;
+
+    public PlabGCStatistics() {
+        plabGCStatistics = new EnumMap<>(ReportType.class);
+    }
+
+    /**
+     * Checks if the statistics contains the requested type.
+     * @param reportType
+     * @returns true, if contains, false otherwise
+     */
+    public boolean containsKey(ReportType reportType) {
+        return plabGCStatistics.containsKey(reportType);
+    }
+
+    /**
+     * Put pair of ReportType and PlabInfo to statistics.
+     * @param reportType
+     * @param plabInfo
+     */
+    public void put(ReportType reportType, PlabInfo plabInfo) {
+        plabGCStatistics.put(reportType, plabInfo);
+    }
+
+    /**
+     * Returns PlabInfo of specified type
+     * @param reportType
+     * @return
+     */
+    public PlabInfo get(ReportType reportType) {
+        return plabGCStatistics.get(reportType);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/gc/g1/plab/lib/PlabInfo.java	Sat Apr 02 05:39:25 2016 +0200
@@ -0,0 +1,105 @@
+/*
+ * 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.
+ */
+package gc.g1.plab.lib;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+public class PlabInfo {
+
+    private final Map<String, Long> plabInfo;
+
+    public PlabInfo() {
+        plabInfo = new HashMap<>();
+    }
+
+    private PlabInfo(Map<String, Long> map) {
+        plabInfo = new HashMap<>(map);
+    }
+
+    /**
+     * Add key and value to underlying Map.
+     * @param key   PLAB info field name
+     * @param value PLAB info value for field
+     */
+    public void put(String key, long value) {
+        plabInfo.put(key, value);
+    }
+
+    /**
+     * Get stream of Map.Entry representing underlying Map with PLAB information.
+     */
+    public Stream<Map.Entry<String, Long>> entryStream() {
+        return plabInfo.entrySet().stream();
+    }
+
+    /**
+     * Returns the PlabInfo narrowed for the given fields only
+     * @param fields
+     * @return PlabInfo
+     */
+    public PlabInfo filter(List<String> fields) {
+        return new PlabInfo(entryStream()
+                .filter(field -> fields.contains(field.getKey()))
+                .collect(Collectors.toMap(
+                        item -> item.getKey(),
+                        item -> item.getValue())
+                )
+        );
+    }
+
+    /**
+     * Checks if statistic contains expected fields.
+     * @param fields fields which should be in statistic
+     * @return true if all fields are in statistic, false otherwise
+     */
+    public boolean checkFields(List<String> fields) {
+        for (String key : fields) {
+            if (!plabInfo.containsKey(key)) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    /**
+     * Return a collection of the values.
+     * @return collection of values
+     */
+    public Collection<Long> values() {
+        return plabInfo.values();
+    }
+
+    /**
+     * Get value for specified field.
+     * @param field
+     * @return long value which is contained in specified field
+     */
+    public long get(String field) {
+        return plabInfo.get(field);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/gc/g1/plab/lib/PlabReport.java	Sat Apr 02 05:39:25 2016 +0200
@@ -0,0 +1,66 @@
+/*
+ * 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.
+ */
+package gc.g1.plab.lib;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.stream.Stream;
+
+/**
+ * Class contains representation of GC PLAB log.
+ */
+public class PlabReport {
+
+    private final Map<Long, PlabGCStatistics> report = new HashMap<>();
+
+    public PlabReport() {
+    }
+
+    /**
+     * Checks if underlying Map contains requested GC ID.
+     */
+    public boolean containsKey(Long gcId) {
+        return report.containsKey(gcId);
+    }
+
+    /**
+     * Puts GC ID and PlabGCStatistics to underlying Map.
+     */
+    public void put(Long gcId, PlabGCStatistics plabStat) {
+        report.put(gcId, plabStat);
+    }
+
+    /**
+     * Returns PlabGCStatistics for specified GC ID.
+     */
+    public PlabGCStatistics get(Long gcId) {
+        return report.get(gcId);
+    }
+
+    /**
+     * Returns Stream of Map.Entry of underlying Map.
+     */
+    public Stream<Map.Entry<Long, PlabGCStatistics>> entryStream() {
+        return report.entrySet().stream();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/gc/survivorAlignment/TestPromotionLABLargeSurvivorAlignment.java	Sat Apr 02 05:39:25 2016 +0200
@@ -0,0 +1,72 @@
+/*
+ * 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 8060463
+ * @summary Verify that objects promoted from eden space to survivor space
+ *          with large values for SurvivorAlignmentInBytes succeed.
+ * @requires vm.opt.ExplicitGCInvokesConcurrent != true
+ * @run main/othervm -Xmx128m
+ *                   -XX:+UnlockExperimentalVMOptions
+ *                   -XX:SurvivorAlignmentInBytes=8 -XX:SurvivorRatio=1
+ *                   -XX:-ExplicitGCInvokesConcurrent -XX:-ResizePLAB
+ *                   TestPromotionLABLargeSurvivorAlignment
+ * @run main/othervm -Xmx128m
+ *                   -XX:+UnlockExperimentalVMOptions
+ *                   -XX:SurvivorAlignmentInBytes=16 -XX:SurvivorRatio=1
+ *                   -XX:-ExplicitGCInvokesConcurrent -XX:-ResizePLAB
+ *                   TestPromotionLABLargeSurvivorAlignment
+ * @run main/othervm -Xmx128m
+ *                   -XX:+UnlockExperimentalVMOptions
+ *                   -XX:SurvivorAlignmentInBytes=512 -XX:SurvivorRatio=1
+ *                   -XX:-ExplicitGCInvokesConcurrent -XX:-ResizePLAB
+ *                   TestPromotionLABLargeSurvivorAlignment
+ * @run main/othervm -Xmx128m
+ *                   -XX:+UnlockExperimentalVMOptions
+ *                   -XX:SurvivorAlignmentInBytes=1k -XX:SurvivorRatio=1
+ *                   -XX:-ExplicitGCInvokesConcurrent -XX:-ResizePLAB
+ *                   TestPromotionLABLargeSurvivorAlignment
+ * @run main/othervm -Xmx128m
+ *                   -XX:+UnlockExperimentalVMOptions
+ *                   -XX:SurvivorAlignmentInBytes=4k -XX:SurvivorRatio=1
+ *                   -XX:-ExplicitGCInvokesConcurrent -XX:-ResizePLAB
+ *                   TestPromotionLABLargeSurvivorAlignment
+ * @run main/othervm -Xmx128m
+ *                   -XX:+UnlockExperimentalVMOptions
+ *                   -XX:SurvivorAlignmentInBytes=16k -XX:SurvivorRatio=1
+ *                   -XX:-ExplicitGCInvokesConcurrent -XX:-ResizePLAB
+ *                   TestPromotionLABLargeSurvivorAlignment
+ */
+public class TestPromotionLABLargeSurvivorAlignment {
+    public static void main(String args[]) {
+        Object garbage[] = new Object[1000000];
+        for (int i = 0; i < garbage.length; i++) {
+            garbage[i] = new byte[0];
+        }
+        for (int i = 0; i < 2; i++) {
+            System.gc();
+        }
+    }
+}
+
--- a/hotspot/test/runtime/CommandLine/OptionsValidation/TestOptionsWithRanges.java	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/test/runtime/CommandLine/OptionsValidation/TestOptionsWithRanges.java	Sat Apr 02 05:39:25 2016 +0200
@@ -97,15 +97,6 @@
         excludeTestRange("ThreadStackSize");
 
         /*
-         * JDK-8143958
-         * Temporarily exclude testing of max range for Shared* flags
-         */
-        excludeTestMaxRange("SharedReadWriteSize");
-        excludeTestMaxRange("SharedReadOnlySize");
-        excludeTestMaxRange("SharedMiscDataSize");
-        excludeTestMaxRange("SharedMiscCodeSize");
-
-        /*
          * Remove the flag controlling the size of the stack because the
          * flag has direct influence on the physical memory usage of
          * the VM.
--- a/hotspot/test/runtime/CommandLine/TraceExceptionsTest.java	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/test/runtime/CommandLine/TraceExceptionsTest.java	Sat Apr 02 05:39:25 2016 +0200
@@ -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
@@ -38,7 +38,7 @@
         ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
             "-Xlog:exceptions=info", "NoClassFound");
         OutputAnalyzer output = new OutputAnalyzer(pb.start());
-        output.shouldContain("<a 'java/lang/ClassNotFoundException': NoClassFound>");
+        output.shouldContain("<a 'java/lang/ClassNotFoundException'").shouldContain(": NoClassFound>");
         output.shouldNotContain("<a 'java/lang/ClassNotFoundException'>");
         output.shouldHaveExitValue(1);
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/SelectionResolution/AbstractMethodErrorTest.java	Sat Apr 02 05:39:25 2016 +0200
@@ -0,0 +1,875 @@
+/*
+ * 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
+ * @summary Test of method selection and resolution cases that
+ * generate AbstractMethodErrorTest
+ * @modules java.base/jdk.internal.org.objectweb.asm
+ * @library /runtime/SelectionResolution/classes
+ * @build selectionresolution.*
+ * @run main/othervm/timeout=300 -XX:+IgnoreUnrecognizedVMOptions -XX:-VerifyDependencies AbstractMethodErrorTest
+ */
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.EnumSet;
+import selectionresolution.ClassData;
+import selectionresolution.MethodData;
+import selectionresolution.Result;
+import selectionresolution.SelectionResolutionTest;
+import selectionresolution.SelectionResolutionTestCase;
+import selectionresolution.Template;
+
+public class AbstractMethodErrorTest extends SelectionResolutionTest {
+
+    private static final SelectionResolutionTestCase.Builder initBuilder =
+        new SelectionResolutionTestCase.Builder();
+
+    static {
+        initBuilder.setResult(Result.AME);
+    }
+
+    private static final Collection<TestGroup> testgroups =
+        Arrays.asList(
+                /* invokevirtual tests */
+                /* Group 63: callsite = methodref = expected */
+                new TestGroup.Simple(initBuilder,
+                        Template.SetInvoke(SelectionResolutionTestCase.InvokeInstruction.INVOKEVIRTUAL),
+                        Template.ResultCombo(EnumSet.of(Template.Kind.CLASS),
+                                             EnumSet.of(MethodData.Access.PUBLIC,
+                                                        MethodData.Access.PACKAGE,
+                                                        MethodData.Access.PROTECTED,
+                                                        MethodData.Access.PRIVATE),
+                                             EnumSet.of(MethodData.Context.ABSTRACT),
+                                             EnumSet.of(ClassData.Package.SAME)),
+                        Template.MethodrefEqualsExpected,
+                        Template.ReabstractExpectedClass,
+                        Template.CallsiteEqualsMethodref,
+                        Template.MethodrefSelectionResolvedIsClass),
+                /* Group 64: callsite = methodref, methodref != expected,
+                 * expected is class, expected and callsite in the same package
+                 */
+                new TestGroup.Simple(initBuilder,
+                        Template.SetInvoke(SelectionResolutionTestCase.InvokeInstruction.INVOKEVIRTUAL),
+                        Template.ResultCombo(EnumSet.of(Template.Kind.CLASS),
+                                             EnumSet.of(MethodData.Access.PUBLIC,
+                                                        MethodData.Access.PROTECTED),
+                                             EnumSet.of(MethodData.Context.ABSTRACT),
+                                             EnumSet.of(ClassData.Package.SAME)),
+                        Template.MethodrefNotEqualsExpectedClass,
+                        Template.ReabstractExpectedClass,
+                        Template.CallsiteEqualsMethodref,
+                        Template.MethodrefSelectionResolvedIsClass),
+                /* Group 65: callsite = methodref = resolved, possibly
+                 * skip different package in selection.
+                 */
+                new TestGroup.Simple(initBuilder,
+                        Template.SetInvoke(SelectionResolutionTestCase.InvokeInstruction.INVOKEVIRTUAL),
+                        Template.ResultCombo(EnumSet.of(Template.Kind.CLASS),
+                                             EnumSet.of(MethodData.Access.PACKAGE),
+                                             EnumSet.of(MethodData.Context.ABSTRACT),
+                                             EnumSet.of(ClassData.Package.SAME)),
+                        Template.MethodrefNotEqualsExpectedClass,
+                        Template.ReabstractExpectedClass,
+                        Template.CallsiteEqualsMethodref,
+                        Template.MethodrefSelectionPackageSkipNoOverride),
+                /* Group 66: callsite = methodref, methodref != expected,
+                 * expected is interface, expected and callsite in the same package
+                 */
+                new TestGroup.Simple(initBuilder,
+                        Template.SetInvoke(SelectionResolutionTestCase.InvokeInstruction.INVOKEVIRTUAL),
+                        Template.ResultCombo(EnumSet.of(Template.Kind.INTERFACE),
+                                             EnumSet.of(MethodData.Access.PUBLIC),
+                                             EnumSet.of(MethodData.Context.ABSTRACT),
+                                             EnumSet.of(ClassData.Package.SAME)),
+                        Template.MethodrefNotEqualsExpectedIface,
+                        Template.ReabstractExpectedIface,
+                        Template.CallsiteEqualsMethodref,
+                        Template.MethodrefSelectionResolvedIsIface),
+                /* Group 67: callsite :> methodref, methodref = expected,
+                 * expected is class, expected and callsite in the same package
+                 */
+                new TestGroup.Simple(initBuilder,
+                        Template.SetInvoke(SelectionResolutionTestCase.InvokeInstruction.INVOKEVIRTUAL),
+                        Template.ResultCombo(EnumSet.of(Template.Kind.CLASS),
+                                             EnumSet.of(MethodData.Access.PUBLIC,
+                                                        MethodData.Access.PROTECTED),
+                                             EnumSet.of(MethodData.Context.ABSTRACT),
+                                             EnumSet.of(ClassData.Package.SAME)),
+                        Template.MethodrefEqualsExpected,
+                        Template.ReabstractExpectedClass,
+                        Template.CallsiteSubclassMethodref,
+                        Template.MethodrefSelectionResolvedIsClass),
+                /* Group 68: callsite :> methodref, methodref = expected,
+                 * possibly skip different package in selection.
+                 */
+                new TestGroup.Simple(initBuilder,
+                        Template.SetInvoke(SelectionResolutionTestCase.InvokeInstruction.INVOKEVIRTUAL),
+                        Template.ResultCombo(EnumSet.of(Template.Kind.CLASS),
+                                             EnumSet.of(MethodData.Access.PACKAGE),
+                                             EnumSet.of(MethodData.Context.ABSTRACT),
+                                             EnumSet.of(ClassData.Package.SAME)),
+                        Template.MethodrefEqualsExpected,
+                        Template.ReabstractExpectedClass,
+                        Template.CallsiteSubclassMethodref,
+                        Template.MethodrefSelectionPackageSkipNoOverride),
+                /* Group 69: callsite :> methodref, methodref != expected,
+                 * expected is class, expected and callsite in the same package
+                 */
+                new TestGroup.Simple(initBuilder,
+                        Template.SetInvoke(SelectionResolutionTestCase.InvokeInstruction.INVOKEVIRTUAL),
+                        Template.ResultCombo(EnumSet.of(Template.Kind.CLASS),
+                                             EnumSet.of(MethodData.Access.PUBLIC,
+                                                        MethodData.Access.PACKAGE,
+                                                        MethodData.Access.PROTECTED),
+                                             EnumSet.of(MethodData.Context.ABSTRACT),
+                                             EnumSet.of(ClassData.Package.SAME)),
+                        Template.MethodrefNotEqualsExpectedClass,
+                        Template.ReabstractExpectedClass,
+                        Template.CallsiteSubclassMethodref,
+                        Template.MethodrefSelectionResolvedIsClass),
+                /* Group 70: callsite :> methodref, methodref != expected,
+                 * possibly skip different package in selection
+                 */
+                new TestGroup.Simple(initBuilder,
+                        Template.SetInvoke(SelectionResolutionTestCase.InvokeInstruction.INVOKEVIRTUAL),
+                        Template.ResultCombo(EnumSet.of(Template.Kind.CLASS),
+                                             EnumSet.of(MethodData.Access.PACKAGE),
+                                             EnumSet.of(MethodData.Context.ABSTRACT),
+                                             EnumSet.of(ClassData.Package.SAME)),
+                        Template.MethodrefNotEqualsExpectedClass,
+                        Template.ReabstractExpectedClass,
+                        Template.CallsiteSubclassMethodref,
+                        Template.MethodrefSelectionPackageSkipNoOverride),
+                /* Group 71: callsite :> methodref, methodref != expected,
+                 * expected is interface, expected and callsite in the same package
+                 */
+                new TestGroup.Simple(initBuilder,
+                        Template.SetInvoke(SelectionResolutionTestCase.InvokeInstruction.INVOKEVIRTUAL),
+                        Template.ResultCombo(EnumSet.of(Template.Kind.INTERFACE),
+                                             EnumSet.of(MethodData.Access.PUBLIC),
+                                             EnumSet.of(MethodData.Context.ABSTRACT),
+                                             EnumSet.of(ClassData.Package.SAME)),
+                        Template.MethodrefNotEqualsExpectedIface,
+                        Template.ReabstractExpectedIface,
+                        Template.CallsiteSubclassMethodref,
+                        Template.MethodrefSelectionResolvedIsIface),
+                /* Group 72: callsite unrelated to methodref, methodref = expected,
+                 * expected is class, expected and callsite in the same package
+                 */
+                new TestGroup.Simple(initBuilder,
+                        Template.SetInvoke(SelectionResolutionTestCase.InvokeInstruction.INVOKEVIRTUAL),
+                        Template.ResultCombo(EnumSet.of(Template.Kind.CLASS),
+                                             EnumSet.of(MethodData.Access.PUBLIC),
+                                             EnumSet.of(MethodData.Context.ABSTRACT),
+                                             EnumSet.of(ClassData.Package.SAME)),
+                        Template.MethodrefEqualsExpected,
+                        Template.ReabstractExpectedClass,
+                        Template.CallsiteUnrelatedToMethodref,
+                        Template.MethodrefSelectionResolvedIsClass),
+                /* Group 73: callsite unrelated to methodref, methodref = expected,
+                 * expected is class, expected and callsite in the same package
+                 */
+                new TestGroup.Simple(initBuilder,
+                        Template.SetInvoke(SelectionResolutionTestCase.InvokeInstruction.INVOKEVIRTUAL),
+                        Template.ResultCombo(EnumSet.of(Template.Kind.CLASS),
+                                             EnumSet.of(MethodData.Access.PACKAGE),
+                                             EnumSet.of(MethodData.Context.ABSTRACT),
+                                             EnumSet.of(ClassData.Package.SAME)),
+                        Template.MethodrefEqualsExpected,
+                        Template.ReabstractExpectedClass,
+                        Template.CallsiteUnrelatedToMethodref,
+                        Template.MethodrefSelectionPackageSkipNoOverride),
+                /* Group 74: callsite unrelated to methodref, methodref != expected,
+                 * expected is class, expected and callsite in the same package
+                 */
+                new TestGroup.Simple(initBuilder,
+                        Template.SetInvoke(SelectionResolutionTestCase.InvokeInstruction.INVOKEVIRTUAL),
+                        Template.ResultCombo(EnumSet.of(Template.Kind.CLASS),
+                                             EnumSet.of(MethodData.Access.PUBLIC),
+                                             EnumSet.of(MethodData.Context.ABSTRACT),
+                                             EnumSet.of(ClassData.Package.SAME)),
+                        Template.MethodrefNotEqualsExpectedClass,
+                        Template.ReabstractExpectedClass,
+                        Template.CallsiteUnrelatedToMethodref,
+                        Template.MethodrefSelectionResolvedIsClass),
+                /* Group 75: callsite unrelated to methodref, methodref != expected,
+                 * expected is class, expected and callsite in the same package
+                 */
+                new TestGroup.Simple(initBuilder,
+                        Template.SetInvoke(SelectionResolutionTestCase.InvokeInstruction.INVOKEVIRTUAL),
+                        Template.ResultCombo(EnumSet.of(Template.Kind.CLASS),
+                                             EnumSet.of(MethodData.Access.PACKAGE),
+                                             EnumSet.of(MethodData.Context.ABSTRACT),
+                                             EnumSet.of(ClassData.Package.SAME)),
+                        Template.MethodrefNotEqualsExpectedClass,
+                        Template.ReabstractExpectedClass,
+                        Template.CallsiteUnrelatedToMethodref,
+                        Template.MethodrefSelectionPackageSkipNoOverride),
+                /* Group 76: callsite unrelated to methodref, methodref != expected,
+                 * expected is interface, expected and callsite in the same package
+                 */
+                new TestGroup.Simple(initBuilder,
+                        Template.SetInvoke(SelectionResolutionTestCase.InvokeInstruction.INVOKEVIRTUAL),
+                        Template.ResultCombo(EnumSet.of(Template.Kind.INTERFACE),
+                                             EnumSet.of(MethodData.Access.PUBLIC),
+                                             EnumSet.of(MethodData.Context.ABSTRACT),
+                                             EnumSet.of(ClassData.Package.SAME)),
+                        Template.MethodrefNotEqualsExpectedIface,
+                        Template.ReabstractExpectedIface,
+                        Template.CallsiteUnrelatedToMethodref,
+                        Template.MethodrefSelectionResolvedIsIface),
+                /* Group 77: callsite = methodref, methodref != expected,
+                 * expected is class, expected and callsite not in the same package
+                 */
+                new TestGroup.Simple(initBuilder,
+                        Template.SetInvoke(SelectionResolutionTestCase.InvokeInstruction.INVOKEVIRTUAL),
+                        Template.ResultCombo(EnumSet.of(Template.Kind.CLASS),
+                                             EnumSet.of(MethodData.Access.PUBLIC),
+                                             EnumSet.of(MethodData.Context.ABSTRACT),
+                                             EnumSet.of(ClassData.Package.DIFFERENT)),
+                        Template.MethodrefNotEqualsExpectedClass,
+                        Template.ReabstractExpectedClass,
+                        Template.CallsiteEqualsMethodref,
+                        Template.MethodrefSelectionResolvedIsClass),
+                /* Group 78: callsite = methodref, methodref != expected,
+                 * expected is interface, expected and callsite not in the same package
+                 */
+                new TestGroup.Simple(initBuilder,
+                        Template.SetInvoke(SelectionResolutionTestCase.InvokeInstruction.INVOKEVIRTUAL),
+                        Template.ResultCombo(EnumSet.of(Template.Kind.INTERFACE),
+                                             EnumSet.of(MethodData.Access.PUBLIC),
+                                             EnumSet.of(MethodData.Context.ABSTRACT),
+                                             EnumSet.of(ClassData.Package.DIFFERENT)),
+                        Template.MethodrefNotEqualsExpectedIface,
+                        Template.ReabstractExpectedIface,
+                        Template.CallsiteEqualsMethodref,
+                        Template.MethodrefSelectionResolvedIsIface),
+                /* Group 79: callsite :> methodref, methodref = expected,
+                 * expected is class, expected and callsite not in the same package
+                 */
+                new TestGroup.Simple(initBuilder,
+                        Template.SetInvoke(SelectionResolutionTestCase.InvokeInstruction.INVOKEVIRTUAL),
+                        Template.ResultCombo(EnumSet.of(Template.Kind.CLASS),
+                                             EnumSet.of(MethodData.Access.PUBLIC),
+                                             EnumSet.of(MethodData.Context.ABSTRACT),
+                                             EnumSet.of(ClassData.Package.DIFFERENT)),
+                        Template.MethodrefEqualsExpected,
+                        Template.ReabstractExpectedClass,
+                        Template.CallsiteSubclassMethodref,
+                        Template.MethodrefSelectionResolvedIsClass),
+
+                /* Group 80: callsite :> methodref, methodref != expected,
+                 * expected is class, expected and callsite not in the same package
+                 */
+                new TestGroup.Simple(initBuilder,
+                        Template.SetInvoke(SelectionResolutionTestCase.InvokeInstruction.INVOKEVIRTUAL),
+                        Template.ResultCombo(EnumSet.of(Template.Kind.CLASS),
+                                             EnumSet.of(MethodData.Access.PUBLIC),
+                                             EnumSet.of(MethodData.Context.ABSTRACT),
+                                             EnumSet.of(ClassData.Package.DIFFERENT)),
+                        Template.MethodrefNotEqualsExpectedClass,
+                        Template.ReabstractExpectedClass,
+                        Template.CallsiteSubclassMethodref,
+                        Template.MethodrefSelectionResolvedIsClass),
+                /* Group 81: callsite :> methodref, methodref != expected,
+                 * expected is interface, expected and callsite not in the same package
+                 */
+                new TestGroup.Simple(initBuilder,
+                        Template.SetInvoke(SelectionResolutionTestCase.InvokeInstruction.INVOKEVIRTUAL),
+                        Template.ResultCombo(EnumSet.of(Template.Kind.INTERFACE),
+                                             EnumSet.of(MethodData.Access.PUBLIC),
+                                             EnumSet.of(MethodData.Context.ABSTRACT),
+                                             EnumSet.of(ClassData.Package.DIFFERENT)),
+                        Template.MethodrefNotEqualsExpectedIface,
+                        Template.ReabstractExpectedIface,
+                        Template.CallsiteSubclassMethodref,
+                        Template.MethodrefSelectionResolvedIsIface),
+                /* Group 82: callsite unrelated to methodref, methodref = expected,
+                 * expected is class, expected and callsite not in the same package
+                 */
+                new TestGroup.Simple(initBuilder,
+                        Template.SetInvoke(SelectionResolutionTestCase.InvokeInstruction.INVOKEVIRTUAL),
+                        Template.ResultCombo(EnumSet.of(Template.Kind.CLASS),
+                                             EnumSet.of(MethodData.Access.PUBLIC),
+                                             EnumSet.of(MethodData.Context.ABSTRACT),
+                                             EnumSet.of(ClassData.Package.DIFFERENT)),
+                        Template.MethodrefEqualsExpected,
+                        Template.ReabstractExpectedClass,
+                        Template.CallsiteUnrelatedToMethodref,
+                        Template.MethodrefSelectionResolvedIsClass),
+                /* Group 83: callsite unrelated to methodref, methodref != expected,
+                 * expected is class, expected and callsite not in the same package
+                 */
+                new TestGroup.Simple(initBuilder,
+                        Template.SetInvoke(SelectionResolutionTestCase.InvokeInstruction.INVOKEVIRTUAL),
+                        Template.ResultCombo(EnumSet.of(Template.Kind.CLASS),
+                                             EnumSet.of(MethodData.Access.PUBLIC),
+                                             EnumSet.of(MethodData.Context.ABSTRACT),
+                                             EnumSet.of(ClassData.Package.DIFFERENT)),
+                        Template.MethodrefNotEqualsExpectedClass,
+                        Template.ReabstractExpectedClass,
+                        Template.CallsiteUnrelatedToMethodref,
+                        Template.MethodrefSelectionResolvedIsClass),
+                /* Group 84: callsite unrelated to methodref, methodref != expected,
+                 * expected is interface, expected and callsite not in the same package
+                 */
+                new TestGroup.Simple(initBuilder,
+                        Template.SetInvoke(SelectionResolutionTestCase.InvokeInstruction.INVOKEVIRTUAL),
+                        Template.ResultCombo(EnumSet.of(Template.Kind.INTERFACE),
+                                             EnumSet.of(MethodData.Access.PUBLIC),
+                                             EnumSet.of(MethodData.Context.ABSTRACT),
+                                             EnumSet.of(ClassData.Package.DIFFERENT)),
+                        Template.MethodrefNotEqualsExpectedIface,
+                        Template.ReabstractExpectedIface,
+                        Template.CallsiteUnrelatedToMethodref,
+                        Template.MethodrefSelectionResolvedIsIface),
+
+                /* Reabstraction during selection */
+                /* Group 85: callsite = methodref = expected */
+                new TestGroup.Simple(initBuilder,
+                        Template.SetInvoke(SelectionResolutionTestCase.InvokeInstruction.INVOKEVIRTUAL),
+                        Template.ResultCombo(EnumSet.of(Template.Kind.CLASS),
+                                             EnumSet.of(MethodData.Access.PROTECTED,
+                                                        MethodData.Access.PACKAGE,
+                                                        MethodData.Access.PUBLIC),
+                                             EnumSet.of(MethodData.Context.INSTANCE),
+                                             EnumSet.of(ClassData.Package.SAME)),
+                        Template.MethodrefEqualsExpected,
+                        Template.CallsiteEqualsMethodref,
+                        Template.ReabstractMethodrefResolvedClass),
+                /* Group 86: callsite = methodref, methodref != expected,
+                 * expected is class, expected and callsite in the same package
+                 */
+                new TestGroup.Simple(initBuilder,
+                        Template.SetInvoke(SelectionResolutionTestCase.InvokeInstruction.INVOKEVIRTUAL),
+                        Template.ResultCombo(EnumSet.of(Template.Kind.CLASS),
+                                             EnumSet.of(MethodData.Access.PUBLIC,
+                                                        MethodData.Access.PACKAGE,
+                                                        MethodData.Access.PROTECTED),
+                                             EnumSet.of(MethodData.Context.INSTANCE),
+                                             EnumSet.of(ClassData.Package.SAME)),
+                        Template.MethodrefNotEqualsExpectedClass,
+                        Template.CallsiteEqualsMethodref,
+                        Template.ReabstractMethodrefResolvedClass),
+                /* Group 87: callsite = methodref, methodref != expected,
+                 * expected is interface, expected and callsite in the same package
+                 */
+                new TestGroup.Simple(initBuilder,
+                        Template.SetInvoke(SelectionResolutionTestCase.InvokeInstruction.INVOKEVIRTUAL),
+                        Template.ResultCombo(EnumSet.of(Template.Kind.INTERFACE),
+                                             EnumSet.of(MethodData.Access.PUBLIC),
+                                             EnumSet.of(MethodData.Context.INSTANCE),
+                                             EnumSet.of(ClassData.Package.SAME)),
+                        Template.MethodrefNotEqualsExpectedIface,
+                        Template.CallsiteEqualsMethodref,
+                        Template.ReabstractMethodrefResolvedIface),
+                /* Group 88: callsite :> methodref, methodref = expected,
+                 * expected is class, expected and callsite in the same package
+                 */
+                new TestGroup.Simple(initBuilder,
+                        Template.SetInvoke(SelectionResolutionTestCase.InvokeInstruction.INVOKEVIRTUAL),
+                        Template.ResultCombo(EnumSet.of(Template.Kind.CLASS),
+                                             EnumSet.of(MethodData.Access.PUBLIC,
+                                                        MethodData.Access.PACKAGE,
+                                                        MethodData.Access.PROTECTED),
+                                             EnumSet.of(MethodData.Context.INSTANCE),
+                                             EnumSet.of(ClassData.Package.SAME)),
+                        Template.MethodrefEqualsExpected,
+                        Template.CallsiteSubclassMethodref,
+                        Template.ReabstractMethodrefResolvedClass),
+                /* Group 89: callsite :> methodref, methodref != expected,
+                 * expected is class, expected and callsite in the same package
+                 */
+                new TestGroup.Simple(initBuilder,
+                        Template.SetInvoke(SelectionResolutionTestCase.InvokeInstruction.INVOKEVIRTUAL),
+                        Template.ResultCombo(EnumSet.of(Template.Kind.CLASS),
+                                             EnumSet.of(MethodData.Access.PUBLIC,
+                                                        MethodData.Access.PACKAGE,
+                                                        MethodData.Access.PROTECTED),
+                                             EnumSet.of(MethodData.Context.INSTANCE),
+                                             EnumSet.of(ClassData.Package.SAME)),
+                        Template.MethodrefNotEqualsExpectedClass,
+                        Template.CallsiteSubclassMethodref,
+                        Template.ReabstractMethodrefResolvedClass),
+                /* Group 90: callsite :> methodref, methodref != expected,
+                 * expected is interface, expected and callsite in the same package
+                 */
+                new TestGroup.Simple(initBuilder,
+                        Template.SetInvoke(SelectionResolutionTestCase.InvokeInstruction.INVOKEVIRTUAL),
+                        Template.ResultCombo(EnumSet.of(Template.Kind.INTERFACE),
+                                             EnumSet.of(MethodData.Access.PUBLIC),
+                                             EnumSet.of(MethodData.Context.INSTANCE),
+                                             EnumSet.of(ClassData.Package.SAME)),
+                        Template.MethodrefNotEqualsExpectedIface,
+                        Template.CallsiteSubclassMethodref,
+                        Template.ReabstractMethodrefResolvedIface),
+                /* Group 91: callsite unrelated to methodref, methodref = expected,
+                 * expected is class, expected and callsite in the same package
+                 */
+                new TestGroup.Simple(initBuilder,
+                        Template.SetInvoke(SelectionResolutionTestCase.InvokeInstruction.INVOKEVIRTUAL),
+                        Template.ResultCombo(EnumSet.of(Template.Kind.CLASS),
+                                             EnumSet.of(MethodData.Access.PUBLIC,
+                                                        MethodData.Access.PACKAGE),
+                                             EnumSet.of(MethodData.Context.INSTANCE),
+                                             EnumSet.of(ClassData.Package.SAME)),
+                        Template.MethodrefEqualsExpected,
+                        Template.CallsiteUnrelatedToMethodref,
+                        Template.ReabstractMethodrefResolvedClass),
+                /* Group 92: callsite unrelated to methodref, methodref != expected,
+                 * expected is class, expected and callsite in the same package
+                 */
+                new TestGroup.Simple(initBuilder,
+                        Template.SetInvoke(SelectionResolutionTestCase.InvokeInstruction.INVOKEVIRTUAL),
+                        Template.ResultCombo(EnumSet.of(Template.Kind.CLASS),
+                                             EnumSet.of(MethodData.Access.PUBLIC,
+                                                        MethodData.Access.PACKAGE),
+                                             EnumSet.of(MethodData.Context.INSTANCE),
+                                             EnumSet.of(ClassData.Package.SAME)),
+                        Template.MethodrefNotEqualsExpectedClass,
+                        Template.CallsiteUnrelatedToMethodref,
+                        Template.ReabstractMethodrefResolvedClass),
+                /* Group 93: callsite unrelated to methodref, methodref != expected,
+                 * expected is interface, expected and callsite in the same package
+                 */
+                new TestGroup.Simple(initBuilder,
+                        Template.SetInvoke(SelectionResolutionTestCase.InvokeInstruction.INVOKEVIRTUAL),
+                        Template.ResultCombo(EnumSet.of(Template.Kind.INTERFACE),
+                                             EnumSet.of(MethodData.Access.PUBLIC),
+                                             EnumSet.of(MethodData.Context.INSTANCE),
+                                             EnumSet.of(ClassData.Package.SAME)),
+                        Template.MethodrefNotEqualsExpectedIface,
+                        Template.CallsiteUnrelatedToMethodref,
+                        Template.ReabstractMethodrefResolvedIface),
+                /* Group 94: callsite = methodref, methodref != expected,
+                 * expected is class, expected and callsite not in the same package
+                 */
+                new TestGroup.Simple(initBuilder,
+                        Template.SetInvoke(SelectionResolutionTestCase.InvokeInstruction.INVOKEVIRTUAL),
+                        Template.ResultCombo(EnumSet.of(Template.Kind.CLASS),
+                                             EnumSet.of(MethodData.Access.PUBLIC),
+                                             EnumSet.of(MethodData.Context.INSTANCE),
+                                             EnumSet.of(ClassData.Package.DIFFERENT)),
+                        Template.MethodrefNotEqualsExpectedClass,
+                        Template.CallsiteEqualsMethodref,
+                        Template.ReabstractMethodrefResolvedClass),
+                /* Group 95: callsite = methodref, methodref != expected,
+                 * expected is interface, expected and callsite not in the same package
+                 */
+                new TestGroup.Simple(initBuilder,
+                        Template.SetInvoke(SelectionResolutionTestCase.InvokeInstruction.INVOKEVIRTUAL),
+                        Template.ResultCombo(EnumSet.of(Template.Kind.INTERFACE),
+                                             EnumSet.of(MethodData.Access.PUBLIC),
+                                             EnumSet.of(MethodData.Context.INSTANCE),
+                                             EnumSet.of(ClassData.Package.DIFFERENT)),
+                        Template.MethodrefNotEqualsExpectedIface,
+                        Template.CallsiteEqualsMethodref,
+                        Template.ReabstractMethodrefResolvedIface),
+                /* Group 96: callsite :> methodref, methodref = expected,
+                 * expected is class, expected and callsite not in the same package
+                 */
+                new TestGroup.Simple(initBuilder,
+                        Template.SetInvoke(SelectionResolutionTestCase.InvokeInstruction.INVOKEVIRTUAL),
+                        Template.ResultCombo(EnumSet.of(Template.Kind.CLASS),
+                                             EnumSet.of(MethodData.Access.PUBLIC),
+                                             EnumSet.of(MethodData.Context.INSTANCE),
+                                             EnumSet.of(ClassData.Package.DIFFERENT)),
+                        Template.MethodrefEqualsExpected,
+                        Template.CallsiteSubclassMethodref,
+                        Template.ReabstractMethodrefResolvedClass),
+
+                /* Group 97: callsite :> methodref, methodref != expected,
+                 * expected is class, expected and callsite not in the same package
+                 */
+                new TestGroup.Simple(initBuilder,
+                        Template.SetInvoke(SelectionResolutionTestCase.InvokeInstruction.INVOKEVIRTUAL),
+                        Template.ResultCombo(EnumSet.of(Template.Kind.CLASS),
+                                             EnumSet.of(MethodData.Access.PUBLIC),
+                                             EnumSet.of(MethodData.Context.INSTANCE),
+                                             EnumSet.of(ClassData.Package.DIFFERENT)),
+                        Template.MethodrefNotEqualsExpectedClass,
+                        Template.CallsiteSubclassMethodref,
+                        Template.ReabstractMethodrefResolvedClass),
+                /* Group 98: callsite :> methodref, methodref != expected,
+                 * expected is interface, expected and callsite not in the same package
+                 */
+                new TestGroup.Simple(initBuilder,
+                        Template.SetInvoke(SelectionResolutionTestCase.InvokeInstruction.INVOKEVIRTUAL),
+                        Template.ResultCombo(EnumSet.of(Template.Kind.INTERFACE),
+                                             EnumSet.of(MethodData.Access.PUBLIC),
+                                             EnumSet.of(MethodData.Context.INSTANCE),
+                                             EnumSet.of(ClassData.Package.DIFFERENT)),
+                        Template.MethodrefNotEqualsExpectedIface,
+                        Template.CallsiteSubclassMethodref,
+                        Template.ReabstractMethodrefResolvedIface),
+                /* Group 99: callsite unrelated to methodref, methodref = expected,
+                 * expected is class, expected and callsite not in the same package
+                 */
+                new TestGroup.Simple(initBuilder,
+                        Template.SetInvoke(SelectionResolutionTestCase.InvokeInstruction.INVOKEVIRTUAL),
+                        Template.ResultCombo(EnumSet.of(Template.Kind.CLASS),
+                                             EnumSet.of(MethodData.Access.PUBLIC),
+                                             EnumSet.of(MethodData.Context.INSTANCE),
+                                             EnumSet.of(ClassData.Package.DIFFERENT)),
+                        Template.MethodrefEqualsExpected,
+                        Template.CallsiteUnrelatedToMethodref,
+                        Template.ReabstractMethodrefResolvedClass),
+                /* Group 100: callsite unrelated to methodref, methodref != expected,
+                 * expected is class, expected and callsite not in the same package
+                 */
+                new TestGroup.Simple(initBuilder,
+                        Template.SetInvoke(SelectionResolutionTestCase.InvokeInstruction.INVOKEVIRTUAL),
+                        Template.ResultCombo(EnumSet.of(Template.Kind.CLASS),
+                                             EnumSet.of(MethodData.Access.PUBLIC),
+                                             EnumSet.of(MethodData.Context.INSTANCE),
+                                             EnumSet.of(ClassData.Package.DIFFERENT)),
+                        Template.MethodrefNotEqualsExpectedClass,
+                        Template.CallsiteUnrelatedToMethodref,
+                        Template.ReabstractMethodrefResolvedClass),
+                /* Group 101: callsite unrelated to methodref, methodref != expected,
+                 * expected is interface, expected and callsite not in the same package
+                 */
+                new TestGroup.Simple(initBuilder,
+                        Template.SetInvoke(SelectionResolutionTestCase.InvokeInstruction.INVOKEVIRTUAL),
+                        Template.ResultCombo(EnumSet.of(Template.Kind.INTERFACE),
+                                             EnumSet.of(MethodData.Access.PUBLIC),
+                                             EnumSet.of(MethodData.Context.INSTANCE),
+                                             EnumSet.of(ClassData.Package.DIFFERENT)),
+                        Template.MethodrefNotEqualsExpectedIface,
+                        Template.CallsiteUnrelatedToMethodref,
+                        Template.ReabstractMethodrefResolvedIface),
+
+                /* invokeinterface */
+                /* Group 102: callsite = methodref = expected */
+                new TestGroup.Simple(initBuilder,
+                        Template.SetInvoke(SelectionResolutionTestCase.InvokeInstruction.INVOKEINTERFACE),
+                        Template.ResultCombo(EnumSet.of(Template.Kind.INTERFACE),
+                                             EnumSet.of(MethodData.Access.PUBLIC),
+                                             EnumSet.of(MethodData.Context.ABSTRACT),
+                                             EnumSet.of(ClassData.Package.SAME)),
+                        Template.MethodrefEqualsExpected,
+                        Template.ReabstractExpectedIface,
+                        Template.CallsiteEqualsMethodref,
+                        Template.IfaceMethodrefSelection),
+                /* Group 103: callsite = methodref, methodref != expected,
+                 */
+                new TestGroup.Simple(initBuilder,
+                        Template.SetInvoke(SelectionResolutionTestCase.InvokeInstruction.INVOKEINTERFACE),
+                        Template.ResultCombo(EnumSet.of(Template.Kind.INTERFACE),
+                                             EnumSet.of(MethodData.Access.PUBLIC),
+                                             EnumSet.of(MethodData.Context.ABSTRACT),
+                                             EnumSet.of(ClassData.Package.SAME,
+                                                        ClassData.Package.DIFFERENT)),
+                        Template.IfaceMethodrefNotEqualsExpected,
+                        Template.ReabstractExpectedIface,
+                        Template.CallsiteEqualsMethodref,
+                        Template.IfaceMethodrefSelection),
+                /* Group 104: callsite :> methodref, methodref = expected,
+                 */
+                new TestGroup.Simple(initBuilder,
+                        Template.SetInvoke(SelectionResolutionTestCase.InvokeInstruction.INVOKEINTERFACE),
+                        Template.ResultCombo(EnumSet.of(Template.Kind.INTERFACE),
+                                             EnumSet.of(MethodData.Access.PUBLIC),
+                                             EnumSet.of(MethodData.Context.ABSTRACT),
+                                             EnumSet.of(ClassData.Package.SAME,
+                                                        ClassData.Package.DIFFERENT)),
+                        Template.MethodrefEqualsExpected,
+                        Template.ReabstractExpectedIface,
+                        Template.CallsiteSubclassMethodref,
+                        Template.IfaceMethodrefSelection),
+                /* Group 105: callsite :> methodref, methodref != expected,
+                 */
+                new TestGroup.Simple(initBuilder,
+                        Template.SetInvoke(SelectionResolutionTestCase.InvokeInstruction.INVOKEINTERFACE),
+                        Template.ResultCombo(EnumSet.of(Template.Kind.INTERFACE),
+                                             EnumSet.of(MethodData.Access.PUBLIC),
+                                             EnumSet.of(MethodData.Context.ABSTRACT),
+                                             EnumSet.of(ClassData.Package.SAME,
+                                                        ClassData.Package.DIFFERENT)),
+                        Template.IfaceMethodrefNotEqualsExpected,
+                        Template.ReabstractExpectedIface,
+                        Template.CallsiteSubclassMethodref,
+                        Template.IfaceMethodrefSelection),
+                /* Group 106: callsite unrelated to methodref, methodref = expected,
+                 */
+                new TestGroup.Simple(initBuilder,
+                        Template.SetInvoke(SelectionResolutionTestCase.InvokeInstruction.INVOKEINTERFACE),
+                        Template.ResultCombo(EnumSet.of(Template.Kind.INTERFACE),
+                                             EnumSet.of(MethodData.Access.PUBLIC),
+                                             EnumSet.of(MethodData.Context.ABSTRACT),
+                                             EnumSet.of(ClassData.Package.SAME,
+                                                        ClassData.Package.DIFFERENT)),
+                        Template.MethodrefEqualsExpected,
+                        Template.ReabstractExpectedIface,
+                        Template.CallsiteUnrelatedToMethodref,
+                        Template.IfaceMethodrefSelection),
+                /* Group 107: callsite unrelated to methodref, methodref != expected,
+                 */
+                new TestGroup.Simple(initBuilder,
+                        Template.SetInvoke(SelectionResolutionTestCase.InvokeInstruction.INVOKEINTERFACE),
+                        Template.ResultCombo(EnumSet.of(Template.Kind.INTERFACE),
+                                             EnumSet.of(MethodData.Access.PUBLIC),
+                                             EnumSet.of(MethodData.Context.ABSTRACT),
+                                             EnumSet.of(ClassData.Package.SAME,
+                                                        ClassData.Package.DIFFERENT)),
+                        Template.IfaceMethodrefNotEqualsExpected,
+                        Template.ReabstractExpectedIface,
+                        Template.CallsiteUnrelatedToMethodref,
+                        Template.IfaceMethodrefSelection),
+
+                /* Reabstraction during selection */
+                /* Group 108: callsite = methodref = expected */
+                new TestGroup.Simple(initBuilder,
+                        Template.SetInvoke(SelectionResolutionTestCase.InvokeInstruction.INVOKEINTERFACE),
+                        Template.ResultCombo(EnumSet.of(Template.Kind.INTERFACE),
+                                             EnumSet.of(MethodData.Access.PUBLIC),
+                                             EnumSet.of(MethodData.Context.INSTANCE),
+                                             EnumSet.of(ClassData.Package.SAME)),
+                        Template.MethodrefEqualsExpected,
+                        Template.CallsiteEqualsMethodref,
+                        Template.ReabstractIfaceMethodrefResolved),
+                /* Group 109: callsite = methodref, methodref != expected,
+                 */
+                new TestGroup.Simple(initBuilder,
+                        Template.SetInvoke(SelectionResolutionTestCase.InvokeInstruction.INVOKEINTERFACE),
+                        Template.ResultCombo(EnumSet.of(Template.Kind.INTERFACE),
+                                             EnumSet.of(MethodData.Access.PUBLIC),
+                                             EnumSet.of(MethodData.Context.INSTANCE),
+                                             EnumSet.of(ClassData.Package.SAME,
+                                                        ClassData.Package.DIFFERENT)),
+                        Template.IfaceMethodrefNotEqualsExpected,
+                        Template.CallsiteEqualsMethodref,
+                        Template.ReabstractIfaceMethodrefResolved),
+                /* Group 110: callsite :> methodref, methodref = expected,
+                 */
+                new TestGroup.Simple(initBuilder,
+                        Template.SetInvoke(SelectionResolutionTestCase.InvokeInstruction.INVOKEINTERFACE),
+                        Template.ResultCombo(EnumSet.of(Template.Kind.INTERFACE),
+                                             EnumSet.of(MethodData.Access.PUBLIC),
+                                             EnumSet.of(MethodData.Context.INSTANCE),
+                                             EnumSet.of(ClassData.Package.SAME,
+                                                        ClassData.Package.DIFFERENT)),
+                        Template.MethodrefEqualsExpected,
+                        Template.CallsiteSubclassMethodref,
+                        Template.ReabstractIfaceMethodrefResolved),
+                /* Group 111: callsite :> methodref, methodref != expected,
+                 */
+                new TestGroup.Simple(initBuilder,
+                        Template.SetInvoke(SelectionResolutionTestCase.InvokeInstruction.INVOKEINTERFACE),
+                        Template.ResultCombo(EnumSet.of(Template.Kind.INTERFACE),
+                                             EnumSet.of(MethodData.Access.PUBLIC),
+                                             EnumSet.of(MethodData.Context.INSTANCE),
+                                             EnumSet.of(ClassData.Package.SAME,
+                                                        ClassData.Package.DIFFERENT)),
+                        Template.IfaceMethodrefNotEqualsExpected,
+                        Template.CallsiteSubclassMethodref,
+                        Template.ReabstractIfaceMethodrefResolved),
+                /* Group 112: callsite unrelated to methodref, methodref = expected,
+                 */
+                new TestGroup.Simple(initBuilder,
+                        Template.SetInvoke(SelectionResolutionTestCase.InvokeInstruction.INVOKEINTERFACE),
+                        Template.ResultCombo(EnumSet.of(Template.Kind.INTERFACE),
+                                             EnumSet.of(MethodData.Access.PUBLIC),
+                                             EnumSet.of(MethodData.Context.INSTANCE),
+                                             EnumSet.of(ClassData.Package.SAME,
+                                                        ClassData.Package.DIFFERENT)),
+                        Template.MethodrefEqualsExpected,
+                        Template.CallsiteUnrelatedToMethodref,
+                        Template.ReabstractIfaceMethodrefResolved),
+                /* Group 113: callsite unrelated to methodref, methodref != expected,
+                 */
+                new TestGroup.Simple(initBuilder,
+                        Template.SetInvoke(SelectionResolutionTestCase.InvokeInstruction.INVOKEINTERFACE),
+                        Template.ResultCombo(EnumSet.of(Template.Kind.INTERFACE),
+                                             EnumSet.of(MethodData.Access.PUBLIC),
+                                             EnumSet.of(MethodData.Context.INSTANCE),
+                                             EnumSet.of(ClassData.Package.SAME,
+                                                        ClassData.Package.DIFFERENT)),
+                        Template.IfaceMethodrefNotEqualsExpected,
+                        Template.CallsiteUnrelatedToMethodref,
+                        Template.ReabstractIfaceMethodrefResolved),
+
+                /* invokespecial tests */
+                /* Group 114: callsite = methodref = expected */
+                new TestGroup.Simple(initBuilder,
+                        Template.SetInvoke(SelectionResolutionTestCase.InvokeInstruction.INVOKESPECIAL),
+                        Template.ResultCombo(EnumSet.of(Template.Kind.CLASS),
+                                             EnumSet.of(MethodData.Access.PUBLIC,
+                                                        MethodData.Access.PACKAGE,
+                                                        MethodData.Access.PROTECTED,
+                                                        MethodData.Access.PRIVATE),
+                                             EnumSet.of(MethodData.Context.ABSTRACT),
+                                             EnumSet.of(ClassData.Package.SAME)),
+                        Template.MethodrefEqualsExpected,
+                        Template.ReabstractExpectedClass,
+                        Template.CallsiteEqualsMethodref,
+                        Template.ObjectrefExactSubclassOfCallsite),
+                /* Group 115: callsite = methodref, methodref != expected,
+                 * expected is class, expected and callsite in the same package
+                 */
+                new TestGroup.Simple(initBuilder,
+                        Template.SetInvoke(SelectionResolutionTestCase.InvokeInstruction.INVOKESPECIAL),
+                        Template.ResultCombo(EnumSet.of(Template.Kind.CLASS),
+                                             EnumSet.of(MethodData.Access.PUBLIC,
+                                                        MethodData.Access.PACKAGE,
+                                                        MethodData.Access.PROTECTED),
+                                             EnumSet.of(MethodData.Context.ABSTRACT),
+                                             EnumSet.of(ClassData.Package.SAME)),
+                        Template.MethodrefNotEqualsExpectedClass,
+                        Template.ReabstractExpectedClass,
+                        Template.CallsiteEqualsMethodref,
+                        Template.ObjectrefExactSubclassOfCallsite),
+                /* Group 116: callsite = methodref, methodref != expected,
+                 * expected is interface, expected and callsite in the same package
+                 */
+                new TestGroup.Simple(initBuilder,
+                        Template.SetInvoke(SelectionResolutionTestCase.InvokeInstruction.INVOKESPECIAL),
+                        Template.ResultCombo(EnumSet.of(Template.Kind.INTERFACE),
+                                             EnumSet.of(MethodData.Access.PUBLIC),
+                                             EnumSet.of(MethodData.Context.ABSTRACT),
+                                             EnumSet.of(ClassData.Package.SAME)),
+                        Template.MethodrefNotEqualsExpectedIface,
+                        Template.ReabstractExpectedIface,
+                        Template.CallsiteEqualsMethodref,
+                        Template.ObjectrefExactSubclassOfCallsite),
+                /* Group 117: callsite :> methodref, methodref = expected,
+                 * expected is class, expected and callsite in the same package
+                 */
+                new TestGroup.Simple(initBuilder,
+                        Template.SetInvoke(SelectionResolutionTestCase.InvokeInstruction.INVOKESPECIAL),
+                        Template.ResultCombo(EnumSet.of(Template.Kind.CLASS),
+                                             EnumSet.of(MethodData.Access.PUBLIC,
+                                                        MethodData.Access.PACKAGE,
+                                                        MethodData.Access.PROTECTED),
+                                             EnumSet.of(MethodData.Context.ABSTRACT),
+                                             EnumSet.of(ClassData.Package.SAME)),
+                        Template.MethodrefEqualsExpected,
+                        Template.ReabstractExpectedClass,
+                        Template.CallsiteSubclassMethodref,
+                        Template.ObjectrefExactSubclassOfCallsite),
+                /* Group 118: callsite :> methodref, methodref != expected,
+                 * expected is class, expected and callsite in the same package
+                 */
+                new TestGroup.Simple(initBuilder,
+                        Template.SetInvoke(SelectionResolutionTestCase.InvokeInstruction.INVOKESPECIAL),
+                        Template.ResultCombo(EnumSet.of(Template.Kind.CLASS),
+                                             EnumSet.of(MethodData.Access.PUBLIC,
+                                                        MethodData.Access.PACKAGE,
+                                                        MethodData.Access.PROTECTED),
+                                             EnumSet.of(MethodData.Context.ABSTRACT),
+                                             EnumSet.of(ClassData.Package.SAME)),
+                        Template.MethodrefNotEqualsExpectedClass,
+                        Template.ReabstractExpectedClass,
+                        Template.CallsiteSubclassMethodref,
+                        Template.ObjectrefExactSubclassOfCallsite),
+                /* Group 119: callsite :> methodref, methodref != expected,
+                 * expected is interface, expected and callsite in the same package
+                 */
+                new TestGroup.Simple(initBuilder,
+                        Template.SetInvoke(SelectionResolutionTestCase.InvokeInstruction.INVOKESPECIAL),
+                        Template.ResultCombo(EnumSet.of(Template.Kind.INTERFACE),
+                                             EnumSet.of(MethodData.Access.PUBLIC),
+                                             EnumSet.of(MethodData.Context.ABSTRACT),
+                                             EnumSet.of(ClassData.Package.SAME)),
+                        Template.MethodrefNotEqualsExpectedIface,
+                        Template.ReabstractExpectedIface,
+                        Template.CallsiteSubclassMethodref,
+                        Template.ObjectrefExactSubclassOfCallsite),
+                /* Group 120: callsite = methodref, methodref != expected,
+                 * expected is class, expected and callsite not in the same package
+                 */
+                new TestGroup.Simple(initBuilder,
+                        Template.SetInvoke(SelectionResolutionTestCase.InvokeInstruction.INVOKESPECIAL),
+                        Template.ResultCombo(EnumSet.of(Template.Kind.CLASS),
+                                             EnumSet.of(MethodData.Access.PUBLIC),
+                                             EnumSet.of(MethodData.Context.ABSTRACT),
+                                             EnumSet.of(ClassData.Package.DIFFERENT)),
+                        Template.MethodrefNotEqualsExpectedClass,
+                        Template.ReabstractExpectedClass,
+                        Template.CallsiteEqualsMethodref,
+                        Template.ObjectrefExactSubclassOfCallsite),
+                /* Group 121: callsite = methodref, methodref != expected,
+                 * expected is interface, expected and callsite not in the same package
+                 */
+                new TestGroup.Simple(initBuilder,
+                        Template.SetInvoke(SelectionResolutionTestCase.InvokeInstruction.INVOKESPECIAL),
+                        Template.ResultCombo(EnumSet.of(Template.Kind.INTERFACE),
+                                             EnumSet.of(MethodData.Access.PUBLIC),
+                                             EnumSet.of(MethodData.Context.ABSTRACT),
+                                             EnumSet.of(ClassData.Package.DIFFERENT)),
+                        Template.MethodrefNotEqualsExpectedIface,
+                        Template.ReabstractExpectedIface,
+                        Template.CallsiteEqualsMethodref,
+                        Template.ObjectrefExactSubclassOfCallsite),
+                /* Group 122: callsite :> methodref, methodref = expected,
+                 * expected is class, expected and callsite not in the same package
+                 */
+                new TestGroup.Simple(initBuilder,
+                        Template.SetInvoke(SelectionResolutionTestCase.InvokeInstruction.INVOKESPECIAL),
+                        Template.ResultCombo(EnumSet.of(Template.Kind.CLASS),
+                                             EnumSet.of(MethodData.Access.PUBLIC),
+                                             EnumSet.of(MethodData.Context.ABSTRACT),
+                                             EnumSet.of(ClassData.Package.DIFFERENT)),
+                        Template.MethodrefEqualsExpected,
+                        Template.ReabstractExpectedClass,
+                        Template.CallsiteSubclassMethodref,
+                        Template.ObjectrefExactSubclassOfCallsite),
+
+                /* Group 123: callsite :> methodref, methodref != expected,
+                 * expected is class, expected and callsite not in the same package
+                 */
+                new TestGroup.Simple(initBuilder,
+                        Template.SetInvoke(SelectionResolutionTestCase.InvokeInstruction.INVOKESPECIAL),
+                        Template.ResultCombo(EnumSet.of(Template.Kind.CLASS),
+                                             EnumSet.of(MethodData.Access.PUBLIC),
+                                             EnumSet.of(MethodData.Context.ABSTRACT),
+                                             EnumSet.of(ClassData.Package.DIFFERENT)),
+                        Template.MethodrefNotEqualsExpectedClass,
+                        Template.ReabstractExpectedClass,
+                        Template.CallsiteSubclassMethodref,
+                        Template.ObjectrefExactSubclassOfCallsite),
+                /* Group 124: callsite :> methodref, methodref != expected,
+                 * expected is interface, expected and callsite not in the same package
+                 */
+                new TestGroup.Simple(initBuilder,
+                        Template.SetInvoke(SelectionResolutionTestCase.InvokeInstruction.INVOKESPECIAL),
+                        Template.ResultCombo(EnumSet.of(Template.Kind.INTERFACE),
+                                             EnumSet.of(MethodData.Access.PUBLIC),
+                                             EnumSet.of(MethodData.Context.ABSTRACT),
+                                             EnumSet.of(ClassData.Package.DIFFERENT)),
+                        Template.MethodrefNotEqualsExpectedIface,
+                        Template.ReabstractExpectedIface,
+                        Template.CallsiteSubclassMethodref,
+                        Template.ObjectrefExactSubclassOfCallsite)
+            );
+
+    private AbstractMethodErrorTest() {
+        super(testgroups);
+    }
+
+    public static void main(final String... args) {
+        new AbstractMethodErrorTest().run();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/SelectionResolution/IllegalAccessErrorTest.java	Sat Apr 02 05:39:25 2016 +0200
@@ -0,0 +1,517 @@
+/*
+ * 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
+ * @summary Test of method selection and resolution cases that
+ * generate IllegalAccessErrorTest
+ * @modules java.base/jdk.internal.org.objectweb.asm
+ * @library /runtime/SelectionResolution/classes
+ * @build selectionresolution.*
+ * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:-VerifyDependencies IllegalAccessErrorTest
+ */
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.EnumSet;
+import selectionresolution.ClassData;
+import selectionresolution.MethodData;
+import selectionresolution.Result;
+import selectionresolution.SelectionResolutionTest;
+import selectionresolution.SelectionResolutionTestCase;
+import selectionresolution.Template;
+
+public class IllegalAccessErrorTest extends SelectionResolutionTest {
+
+    private static final SelectionResolutionTestCase.Builder initBuilder =
+        new SelectionResolutionTestCase.Builder();
+
+    static {
+        initBuilder.setResult(Result.IAE);
+    }
+
+    private static final Collection<TestGroup> testgroups =
+        Arrays.asList(
+                /* invokestatic tests */
+                /* Group 125 : callsite = methodref, methodref !=
+                 * expected, expected is class
+                 */
+                new TestGroup.Simple(initBuilder,
+                        Template.SetInvoke(SelectionResolutionTestCase.InvokeInstruction.INVOKESTATIC),
+                        Template.ResultCombo(EnumSet.of(Template.Kind.CLASS),
+                                             EnumSet.of(MethodData.Access.PRIVATE),
+                                             EnumSet.of(MethodData.Context.STATIC),
+                                             EnumSet.of(ClassData.Package.SAME)),
+                        Template.MethodrefNotEqualsExpectedClass,
+                        Template.CallsiteEqualsMethodref,
+                        Template.TrivialObjectref),
+                /* Group 126: callsite :> methodref, methodref = expected,
+                 * expected is class, expected and callsite in the same package
+                 */
+                new TestGroup.Simple(initBuilder,
+                        Template.SetInvoke(SelectionResolutionTestCase.InvokeInstruction.INVOKESTATIC),
+                        Template.ResultCombo(EnumSet.of(Template.Kind.CLASS),
+                                             EnumSet.of(MethodData.Access.PRIVATE),
+                                             EnumSet.of(MethodData.Context.STATIC),
+                                             EnumSet.of(ClassData.Package.SAME)),
+                        Template.MethodrefEqualsExpected,
+                        Template.CallsiteSubclassMethodref,
+                        Template.TrivialObjectref),
+                /* Group 127: callsite :> methodref, methodref != expected,
+                 * expected is class, expected and callsite in the same package
+                 */
+                new TestGroup.Simple(initBuilder,
+                        Template.SetInvoke(SelectionResolutionTestCase.InvokeInstruction.INVOKESTATIC),
+                        Template.ResultCombo(EnumSet.of(Template.Kind.CLASS),
+                                             EnumSet.of(MethodData.Access.PRIVATE),
+                                             EnumSet.of(MethodData.Context.STATIC),
+                                             EnumSet.of(ClassData.Package.SAME)),
+                        Template.MethodrefNotEqualsExpectedClass,
+                        Template.CallsiteSubclassMethodref,
+                        Template.TrivialObjectref),
+                /* Group 128: callsite unrelated to methodref, methodref = expected,
+                 * expected is class, expected and callsite in the same package
+                 */
+                new TestGroup.Simple(initBuilder,
+                        Template.SetInvoke(SelectionResolutionTestCase.InvokeInstruction.INVOKESTATIC),
+                        Template.ResultCombo(EnumSet.of(Template.Kind.CLASS),
+                                             EnumSet.of(MethodData.Access.PRIVATE),
+                                             EnumSet.of(MethodData.Context.STATIC),
+                                             EnumSet.of(ClassData.Package.SAME)),
+                        Template.MethodrefEqualsExpected,
+                        Template.CallsiteUnrelatedToMethodref,
+                        Template.TrivialObjectref),
+                /* Group 129: callsite unrelated to methodref, methodref != expected,
+                 * expected is class, expected and callsite in the same package
+                 */
+                new TestGroup.Simple(initBuilder,
+                        Template.SetInvoke(SelectionResolutionTestCase.InvokeInstruction.INVOKESTATIC),
+                        Template.ResultCombo(EnumSet.of(Template.Kind.CLASS),
+                                             EnumSet.of(MethodData.Access.PRIVATE),
+                                             EnumSet.of(MethodData.Context.STATIC),
+                                             EnumSet.of(ClassData.Package.SAME)),
+                        Template.MethodrefNotEqualsExpectedClass,
+                        Template.CallsiteUnrelatedToMethodref,
+                        Template.TrivialObjectref),
+                /* Group 130: callsite = methodref, methodref != expected,
+                 * expected is class, expected and callsite not in the same package
+                 */
+                new TestGroup.Simple(initBuilder,
+                        Template.SetInvoke(SelectionResolutionTestCase.InvokeInstruction.INVOKESTATIC),
+                        Template.ResultCombo(EnumSet.of(Template.Kind.CLASS),
+                                             EnumSet.of(MethodData.Access.PRIVATE,
+                                                        MethodData.Access.PACKAGE),
+                                             EnumSet.of(MethodData.Context.STATIC),
+                                             EnumSet.of(ClassData.Package.DIFFERENT)),
+                        Template.MethodrefNotEqualsExpectedClass,
+                        Template.CallsiteEqualsMethodref,
+                        Template.TrivialObjectref),
+                /* Group 131: callsite :> methodref, methodref = expected,
+                 * expected is class, expected and callsite not in the same package
+                 */
+                new TestGroup.Simple(initBuilder,
+                        Template.SetInvoke(SelectionResolutionTestCase.InvokeInstruction.INVOKESTATIC),
+                        Template.ResultCombo(EnumSet.of(Template.Kind.CLASS),
+                                             EnumSet.of(MethodData.Access.PRIVATE,
+                                                        MethodData.Access.PACKAGE),
+                                             EnumSet.of(MethodData.Context.STATIC),
+                                             EnumSet.of(ClassData.Package.DIFFERENT)),
+                        Template.MethodrefEqualsExpected,
+                        Template.CallsiteSubclassMethodref,
+                        Template.TrivialObjectref),
+                /* Group 132: callsite :> methodref, methodref != expected,
+                 * expected is class, expected and callsite not in the same package
+                 */
+                new TestGroup.Simple(initBuilder,
+                        Template.SetInvoke(SelectionResolutionTestCase.InvokeInstruction.INVOKESTATIC),
+                        Template.ResultCombo(EnumSet.of(Template.Kind.CLASS),
+                                             EnumSet.of(MethodData.Access.PRIVATE,
+                                                        MethodData.Access.PACKAGE),
+                                             EnumSet.of(MethodData.Context.STATIC),
+                                             EnumSet.of(ClassData.Package.DIFFERENT)),
+                        Template.MethodrefNotEqualsExpectedClass,
+                        Template.CallsiteSubclassMethodref,
+                        Template.TrivialObjectref),
+                /* Group 133: callsite unrelated to methodref, methodref = expected,
+                 * expected is class, expected and callsite not in the same package
+                 */
+                new TestGroup.Simple(initBuilder,
+                        Template.SetInvoke(SelectionResolutionTestCase.InvokeInstruction.INVOKESTATIC),
+                        Template.ResultCombo(EnumSet.of(Template.Kind.CLASS),
+                                             EnumSet.of(MethodData.Access.PRIVATE,
+                                                        MethodData.Access.PROTECTED,
+                                                        MethodData.Access.PACKAGE),
+                                             EnumSet.of(MethodData.Context.STATIC),
+                                             EnumSet.of(ClassData.Package.DIFFERENT)),
+                        Template.MethodrefEqualsExpected,
+                        Template.CallsiteUnrelatedToMethodref,
+                        Template.TrivialObjectref),
+                /* Group 134: callsite unrelated to methodref, methodref != expected,
+                 * expected is class, expected and callsite not in the same package
+                 */
+                new TestGroup.Simple(initBuilder,
+                        Template.SetInvoke(SelectionResolutionTestCase.InvokeInstruction.INVOKESTATIC),
+                        Template.ResultCombo(EnumSet.of(Template.Kind.CLASS),
+                                             EnumSet.of(MethodData.Access.PRIVATE,
+                                                        MethodData.Access.PROTECTED,
+                                                        MethodData.Access.PACKAGE),
+                                             EnumSet.of(MethodData.Context.STATIC),
+                                             EnumSet.of(ClassData.Package.DIFFERENT)),
+                        Template.MethodrefNotEqualsExpectedClass,
+                        Template.CallsiteUnrelatedToMethodref,
+                        Template.TrivialObjectref),
+
+                /* invokevirtual tests */
+                /* Group 135: callsite = methodref, methodref != expected,
+                 * expected is class, expected and callsite in the same package
+                 */
+                new TestGroup.Simple(initBuilder,
+                        Template.SetInvoke(SelectionResolutionTestCase.InvokeInstruction.INVOKEVIRTUAL),
+                        Template.ResultCombo(EnumSet.of(Template.Kind.CLASS),
+                                             EnumSet.of(MethodData.Access.PRIVATE),
+                                             EnumSet.of(MethodData.Context.INSTANCE),
+                                             EnumSet.of(ClassData.Package.SAME)),
+                        Template.OverrideAbstractExpectedClass,
+                        Template.MethodrefNotEqualsExpectedClass,
+                        Template.IgnoredAbstract,
+                        Template.CallsiteEqualsMethodref,
+                        Template.MethodrefSelectionResolvedIsClass),
+                /* Group 136: callsite :> methodref, methodref = expected,
+                 * expected is class, expected and callsite in the same package
+                 */
+                new TestGroup.Simple(initBuilder,
+                        Template.SetInvoke(SelectionResolutionTestCase.InvokeInstruction.INVOKEVIRTUAL),
+                        Template.ResultCombo(EnumSet.of(Template.Kind.CLASS),
+                                             EnumSet.of(MethodData.Access.PRIVATE),
+                                             EnumSet.of(MethodData.Context.INSTANCE),
+                                             EnumSet.of(ClassData.Package.SAME)),
+                        Template.OverrideAbstractExpectedClass,
+                        Template.MethodrefEqualsExpected,
+                        Template.IgnoredAbstract,
+                        Template.CallsiteSubclassMethodref,
+                        Template.MethodrefSelectionResolvedIsClass),
+                /* Group 137: callsite :> methodref, methodref != expected,
+                 * expected is class, expected and callsite in the same package
+                 */
+                new TestGroup.Simple(initBuilder,
+                        Template.SetInvoke(SelectionResolutionTestCase.InvokeInstruction.INVOKEVIRTUAL),
+                        Template.ResultCombo(EnumSet.of(Template.Kind.CLASS),
+                                             EnumSet.of(MethodData.Access.PRIVATE),
+                                             EnumSet.of(MethodData.Context.INSTANCE),
+                                             EnumSet.of(ClassData.Package.SAME)),
+                        Template.OverrideAbstractExpectedClass,
+                        Template.MethodrefNotEqualsExpectedClass,
+                        Template.IgnoredAbstract,
+                        Template.CallsiteSubclassMethodref,
+                        Template.MethodrefSelectionResolvedIsClass),
+                /* Group 138: callsite unrelated to methodref, methodref = expected,
+                 * expected is class, expected and callsite in the same package
+                 */
+                new TestGroup.Simple(initBuilder,
+                        Template.SetInvoke(SelectionResolutionTestCase.InvokeInstruction.INVOKEVIRTUAL),
+                        Template.ResultCombo(EnumSet.of(Template.Kind.CLASS),
+                                             EnumSet.of(MethodData.Access.PRIVATE),
+                                             EnumSet.of(MethodData.Context.INSTANCE),
+                                             EnumSet.of(ClassData.Package.SAME)),
+                        Template.OverrideAbstractExpectedClass,
+                        Template.MethodrefEqualsExpected,
+                        Template.IgnoredAbstract,
+                        Template.CallsiteUnrelatedToMethodref,
+                        Template.MethodrefSelectionResolvedIsClass),
+                /* Group 139: callsite unrelated to methodref, methodref != expected,
+                 * expected is class, expected and callsite in the same package
+                 */
+                new TestGroup.Simple(initBuilder,
+                        Template.SetInvoke(SelectionResolutionTestCase.InvokeInstruction.INVOKEVIRTUAL),
+                        Template.ResultCombo(EnumSet.of(Template.Kind.CLASS),
+                                             EnumSet.of(MethodData.Access.PRIVATE),
+                                             EnumSet.of(MethodData.Context.INSTANCE),
+                                             EnumSet.of(ClassData.Package.SAME)),
+                        Template.OverrideAbstractExpectedClass,
+                        Template.MethodrefNotEqualsExpectedClass,
+                        Template.IgnoredAbstract,
+                        Template.CallsiteUnrelatedToMethodref,
+                        Template.MethodrefSelectionResolvedIsClass),
+                /* Group 140: callsite = methodref, methodref != expected,
+                 * expected is class, expected and callsite not in the same package
+                 */
+                new TestGroup.Simple(initBuilder,
+                        Template.SetInvoke(SelectionResolutionTestCase.InvokeInstruction.INVOKEVIRTUAL),
+                        Template.ResultCombo(EnumSet.of(Template.Kind.CLASS),
+                                             EnumSet.of(MethodData.Access.PACKAGE,
+                                                        MethodData.Access.PRIVATE),
+                                             EnumSet.of(MethodData.Context.INSTANCE),
+                                             EnumSet.of(ClassData.Package.DIFFERENT)),
+                        Template.OverrideAbstractExpectedClass,
+                        Template.MethodrefNotEqualsExpectedClass,
+                        Template.IgnoredAbstract,
+                        Template.CallsiteEqualsMethodref,
+                        Template.MethodrefSelectionResolvedIsClass),
+                /* Group 141: callsite :> methodref, methodref = expected,
+                 * expected is class, expected and callsite not in the same package
+                 */
+                new TestGroup.Simple(initBuilder,
+                        Template.SetInvoke(SelectionResolutionTestCase.InvokeInstruction.INVOKEVIRTUAL),
+                        Template.ResultCombo(EnumSet.of(Template.Kind.CLASS),
+                                             EnumSet.of(MethodData.Access.PACKAGE,
+                                                        MethodData.Access.PRIVATE),
+                                             EnumSet.of(MethodData.Context.INSTANCE,
+                                                        MethodData.Context.ABSTRACT),
+                                             EnumSet.of(ClassData.Package.DIFFERENT)),
+                        Template.OverrideAbstractExpectedClass,
+                        Template.MethodrefEqualsExpected,
+                        Template.IgnoredAbstract,
+                        Template.CallsiteSubclassMethodref,
+                        Template.MethodrefSelectionResolvedIsClass),
+                /* Group 142: callsite :> methodref, methodref = expected,
+                 * expected is class, expected and callsite not in the same package
+                 */
+                new TestGroup.Simple(initBuilder,
+                        Template.SetInvoke(SelectionResolutionTestCase.InvokeInstruction.INVOKEVIRTUAL),
+                        Template.ResultCombo(EnumSet.of(Template.Kind.CLASS),
+                                             EnumSet.of(MethodData.Access.PACKAGE,
+                                                        MethodData.Access.PRIVATE),
+                                             EnumSet.of(MethodData.Context.INSTANCE,
+                                                        MethodData.Context.ABSTRACT),
+                                             EnumSet.of(ClassData.Package.DIFFERENT)),
+                        Template.OverrideAbstractExpectedClass,
+                        Template.MethodrefNotEqualsExpectedClass,
+                        Template.IgnoredAbstract,
+                        Template.CallsiteSubclassMethodref,
+                        Template.MethodrefSelectionResolvedIsClass),
+                /* Group 143: callsite unrelated to methodref, methodref = expected,
+                 * expected is class, expected and callsite not in the same package
+                 */
+                new TestGroup.Simple(initBuilder,
+                        Template.SetInvoke(SelectionResolutionTestCase.InvokeInstruction.INVOKEVIRTUAL),
+                        Template.ResultCombo(EnumSet.of(Template.Kind.CLASS),
+                                             EnumSet.of(MethodData.Access.PACKAGE,
+                                                        // protected causes verifier error.
+                                                        MethodData.Access.PRIVATE),
+                                             EnumSet.of(MethodData.Context.INSTANCE,
+                                                        MethodData.Context.ABSTRACT),
+                                             EnumSet.of(ClassData.Package.DIFFERENT)),
+                        Template.OverrideAbstractExpectedClass,
+                        Template.MethodrefEqualsExpected,
+                        Template.IgnoredAbstract,
+                        Template.CallsiteUnrelatedToMethodref,
+                        Template.MethodrefSelectionResolvedIsClass),
+                /* Group 144: callsite unrelated to methodref, methodref != expected,
+                 * expected is class, expected and callsite not in the same package
+                 */
+                new TestGroup.Simple(initBuilder,
+                        Template.SetInvoke(SelectionResolutionTestCase.InvokeInstruction.INVOKEVIRTUAL),
+                        Template.ResultCombo(EnumSet.of(Template.Kind.CLASS),
+                                             EnumSet.of(MethodData.Access.PACKAGE,
+                                                        // protected causes verifier error.
+                                                        MethodData.Access.PRIVATE),
+                                             EnumSet.of(MethodData.Context.INSTANCE,
+                                                        MethodData.Context.ABSTRACT),
+                                             EnumSet.of(ClassData.Package.DIFFERENT)),
+                        Template.OverrideAbstractExpectedClass,
+                        Template.MethodrefNotEqualsExpectedClass,
+                        Template.IgnoredAbstract,
+                        Template.CallsiteUnrelatedToMethodref,
+                        Template.MethodrefSelectionResolvedIsClass),
+
+                /* invokeinterface tests */
+                /* Group 145: callsite = methodref = expected */
+                new TestGroup.Simple(initBuilder,
+                        Template.SetInvoke(SelectionResolutionTestCase.InvokeInstruction.INVOKEINTERFACE),
+                        Template.ResultCombo(EnumSet.of(Template.Kind.INTERFACE),
+                                             EnumSet.of(MethodData.Access.PUBLIC),
+                                             EnumSet.of(MethodData.Context.INSTANCE),
+                                             EnumSet.of(ClassData.Package.SAME)),
+                        Template.OverrideAbstractExpectedIface,
+                        Template.MethodrefEqualsExpected,
+                        Template.IgnoredAbstract,
+                        Template.CallsiteEqualsMethodref,
+                        Template.IfaceMethodrefSelectionOverrideNonPublic),
+                /* Group 146: callsite = methodref, methodref != expected */
+                new TestGroup.Simple(initBuilder,
+                        Template.SetInvoke(SelectionResolutionTestCase.InvokeInstruction.INVOKEINTERFACE),
+                        Template.ResultCombo(EnumSet.of(Template.Kind.INTERFACE),
+                                             EnumSet.of(MethodData.Access.PUBLIC),
+                                             EnumSet.of(MethodData.Context.INSTANCE),
+                                             EnumSet.of(ClassData.Package.SAME,
+                                                        ClassData.Package.DIFFERENT)),
+                        Template.OverrideAbstractExpectedIface,
+                        Template.IfaceMethodrefNotEqualsExpected,
+                        Template.IgnoredAbstract,
+                        Template.CallsiteEqualsMethodref,
+                        Template.IfaceMethodrefSelectionOverrideNonPublic),
+                /* Group 147: callsite :> methodref, methodref = expected */
+                new TestGroup.Simple(initBuilder,
+                        Template.SetInvoke(SelectionResolutionTestCase.InvokeInstruction.INVOKEINTERFACE),
+                        Template.ResultCombo(EnumSet.of(Template.Kind.INTERFACE),
+                                             EnumSet.of(MethodData.Access.PUBLIC),
+                                             EnumSet.of(MethodData.Context.INSTANCE),
+                                             EnumSet.of(ClassData.Package.SAME,
+                                                        ClassData.Package.DIFFERENT)),
+                        Template.OverrideAbstractExpectedIface,
+                        Template.MethodrefEqualsExpected,
+                        Template.IgnoredAbstract,
+                        Template.CallsiteSubclassMethodref,
+                        Template.IfaceMethodrefSelectionOverrideNonPublic),
+                /* Group 148: callsite :> methodref, methodref != expected */
+                new TestGroup.Simple(initBuilder,
+                        Template.SetInvoke(SelectionResolutionTestCase.InvokeInstruction.INVOKEINTERFACE),
+                        Template.ResultCombo(EnumSet.of(Template.Kind.INTERFACE),
+                                             EnumSet.of(MethodData.Access.PUBLIC),
+                                             EnumSet.of(MethodData.Context.INSTANCE),
+                                             EnumSet.of(ClassData.Package.SAME,
+                                                        ClassData.Package.DIFFERENT)),
+                        Template.OverrideAbstractExpectedIface,
+                        Template.IfaceMethodrefNotEqualsExpected,
+                        Template.IgnoredAbstract,
+                        Template.CallsiteSubclassMethodref,
+                        Template.IfaceMethodrefSelectionOverrideNonPublic),
+                /* Group 149: callsite unrelated to methodref, methodref = expected */
+                new TestGroup.Simple(initBuilder,
+                        Template.SetInvoke(SelectionResolutionTestCase.InvokeInstruction.INVOKEINTERFACE),
+                        Template.ResultCombo(EnumSet.of(Template.Kind.INTERFACE),
+                                             EnumSet.of(MethodData.Access.PUBLIC),
+                                             EnumSet.of(MethodData.Context.INSTANCE),
+                                             EnumSet.of(ClassData.Package.SAME,
+                                                        ClassData.Package.DIFFERENT)),
+                        Template.OverrideAbstractExpectedIface,
+                        Template.MethodrefEqualsExpected,
+                        Template.IgnoredAbstract,
+                        Template.CallsiteUnrelatedToMethodref,
+                        Template.IfaceMethodrefSelectionOverrideNonPublic),
+                /* Group 150: callsite unrelated to methodref, methodref != expected */
+                new TestGroup.Simple(initBuilder,
+                        Template.SetInvoke(SelectionResolutionTestCase.InvokeInstruction.INVOKEINTERFACE),
+                        Template.ResultCombo(EnumSet.of(Template.Kind.INTERFACE),
+                                             EnumSet.of(MethodData.Access.PUBLIC),
+                                             EnumSet.of(MethodData.Context.INSTANCE),
+                                             EnumSet.of(ClassData.Package.SAME,
+                                                        ClassData.Package.DIFFERENT)),
+                        Template.OverrideAbstractExpectedIface,
+                        Template.IfaceMethodrefNotEqualsExpected,
+                        Template.IgnoredAbstract,
+                        Template.CallsiteUnrelatedToMethodref,
+                        Template.IfaceMethodrefSelectionOverrideNonPublic),
+
+                /* invokespecial tests */
+                /* Group 151: callsite = methodref, methodref != expected,
+                 * expected is class, expected and callsite in the same package
+                 */
+                new TestGroup.Simple(initBuilder,
+                        Template.SetInvoke(SelectionResolutionTestCase.InvokeInstruction.INVOKESPECIAL),
+                        Template.ResultCombo(EnumSet.of(Template.Kind.CLASS),
+                                             EnumSet.of(MethodData.Access.PRIVATE),
+                                             EnumSet.of(MethodData.Context.INSTANCE,
+                                                        MethodData.Context.ABSTRACT),
+                                             EnumSet.of(ClassData.Package.SAME)),
+                        Template.OverrideAbstractExpectedClass,
+                        Template.MethodrefNotEqualsExpectedClass,
+                        Template.IgnoredAbstract,
+                        Template.CallsiteEqualsMethodref,
+                        Template.ObjectrefAssignableToCallsite),
+                /* Group 152: callsite :> methodref, methodref = expected,
+                 * expected is class, expected and callsite in the same package
+                 */
+                new TestGroup.Simple(initBuilder,
+                        Template.SetInvoke(SelectionResolutionTestCase.InvokeInstruction.INVOKESPECIAL),
+                        Template.ResultCombo(EnumSet.of(Template.Kind.CLASS),
+                                             EnumSet.of(MethodData.Access.PRIVATE),
+                                             EnumSet.of(MethodData.Context.INSTANCE,
+                                                        MethodData.Context.ABSTRACT),
+                                             EnumSet.of(ClassData.Package.SAME)),
+                        Template.OverrideAbstractExpectedClass,
+                        Template.MethodrefEqualsExpected,
+                        Template.IgnoredAbstract,
+                        Template.CallsiteSubclassMethodref,
+                        Template.ObjectrefAssignableToCallsite),
+                /* Group 153: callsite :> methodref, methodref != expected,
+                 * expected is class, expected and callsite in the same package
+                 */
+                new TestGroup.Simple(initBuilder,
+                        Template.SetInvoke(SelectionResolutionTestCase.InvokeInstruction.INVOKESPECIAL),
+                        Template.ResultCombo(EnumSet.of(Template.Kind.CLASS),
+                                             EnumSet.of(MethodData.Access.PRIVATE),
+                                             EnumSet.of(MethodData.Context.INSTANCE,
+                                                        MethodData.Context.ABSTRACT),
+                                             EnumSet.of(ClassData.Package.SAME)),
+                        Template.OverrideAbstractExpectedClass,
+                        Template.MethodrefNotEqualsExpectedClass,
+                        Template.IgnoredAbstract,
+                        Template.CallsiteSubclassMethodref,
+                        Template.ObjectrefAssignableToCallsite),
+                /* Group 154: callsite = methodref, methodref != expected,
+                 * expected is class, expected and callsite not in the same package
+                 */
+                new TestGroup.Simple(initBuilder,
+                        Template.SetInvoke(SelectionResolutionTestCase.InvokeInstruction.INVOKESPECIAL),
+                        Template.ResultCombo(EnumSet.of(Template.Kind.CLASS),
+                                             EnumSet.of(MethodData.Access.PACKAGE,
+                                                        MethodData.Access.PRIVATE),
+                                             EnumSet.of(MethodData.Context.INSTANCE),
+                                             EnumSet.of(ClassData.Package.DIFFERENT)),
+                        Template.OverrideAbstractExpectedClass,
+                        Template.MethodrefNotEqualsExpectedClass,
+                        Template.IgnoredAbstract,
+                        Template.CallsiteEqualsMethodref,
+                        Template.ObjectrefExactSubclassOfCallsite),
+                /* Group 155: callsite :> methodref, methodref = expected,
+                 * expected is class, expected and callsite not in the same package
+                 */
+                new TestGroup.Simple(initBuilder,
+                        Template.SetInvoke(SelectionResolutionTestCase.InvokeInstruction.INVOKESPECIAL),
+                        Template.ResultCombo(EnumSet.of(Template.Kind.CLASS),
+                                             EnumSet.of(MethodData.Access.PACKAGE,
+                                                        MethodData.Access.PRIVATE),
+                                             EnumSet.of(MethodData.Context.INSTANCE),
+                                             EnumSet.of(ClassData.Package.DIFFERENT)),
+                        Template.OverrideAbstractExpectedClass,
+                        Template.MethodrefEqualsExpected,
+                        Template.IgnoredAbstract,
+                        Template.CallsiteSubclassMethodref,
+                        Template.ObjectrefExactSubclassOfCallsite),
+                /* Group 156: callsite :> methodref, methodref != expected,
+                 * expected is class, expected and callsite not in the same package
+                 */
+                new TestGroup.Simple(initBuilder,
+                        Template.SetInvoke(SelectionResolutionTestCase.InvokeInstruction.INVOKESPECIAL),
+                        Template.ResultCombo(EnumSet.of(Template.Kind.CLASS),
+                                             EnumSet.of(MethodData.Access.PACKAGE,
+                                                        MethodData.Access.PRIVATE),
+                                             EnumSet.of(MethodData.Context.INSTANCE,
+                                                        MethodData.Context.ABSTRACT),
+                                             EnumSet.of(ClassData.Package.DIFFERENT)),
+                        Template.OverrideAbstractExpectedClass,
+                        Template.MethodrefNotEqualsExpectedClass,
+                        Template.IgnoredAbstract,
+                        Template.CallsiteSubclassMethodref,
+                        Template.ObjectrefExactSubclassOfCallsite)
+            );
+
+    private IllegalAccessErrorTest() {
+        super(testgroups);
+    }
+
+    public static void main(final String... args) {
+        new IllegalAccessErrorTest().run();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/SelectionResolution/InvokeInterfaceICCE.java	Sat Apr 02 05:39:25 2016 +0200
@@ -0,0 +1,180 @@
+/*
+ * 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
+ * @summary Test of method selection and resolution cases that
+ * generate IncompatibleClassChangeError
+ * @modules java.base/jdk.internal.org.objectweb.asm
+ * @library /runtime/SelectionResolution/classes
+ * @build selectionresolution.*
+ * @run main/othervm/timeout=500 -XX:+IgnoreUnrecognizedVMOptions -XX:-VerifyDependencies InvokeInterfaceICCE
+ */
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.EnumSet;
+import selectionresolution.ClassData;
+import selectionresolution.MethodData;
+import selectionresolution.Result;
+import selectionresolution.SelectionResolutionTest;
+import selectionresolution.SelectionResolutionTestCase;
+import selectionresolution.Template;
+
+public class InvokeInterfaceICCE extends SelectionResolutionTest {
+
+    private static final SelectionResolutionTestCase.Builder initBuilder =
+        new SelectionResolutionTestCase.Builder();
+
+    static {
+        initBuilder.setResult(Result.ICCE);
+    }
+
+    private static final Collection<TestGroup> testgroups =
+        Arrays.asList(
+                /* invokeinterface tests */
+
+                /* resolved method is static*/
+                /* Group 168: methodref = expected */
+                new TestGroup.Simple(initBuilder,
+                        Template.SetInvoke(SelectionResolutionTestCase.InvokeInstruction.INVOKEINTERFACE),
+                        Template.ResultCombo(EnumSet.of(Template.Kind.INTERFACE),
+                                             EnumSet.of(MethodData.Access.PUBLIC),
+                                             EnumSet.of(MethodData.Context.STATIC),
+                                             EnumSet.of(ClassData.Package.SAME,
+                                                        ClassData.Package.DIFFERENT)),
+                        Template.OverrideAbstractExpectedIface,
+                        Template.MethodrefEqualsExpected,
+                        Template.IgnoredAbstract,
+                        Template.AllCallsiteCases,
+                        Template.IfaceMethodrefSelection),
+                /* Group 169: methodref != expected */
+                new TestGroup.Simple(initBuilder,
+                        Template.SetInvoke(SelectionResolutionTestCase.InvokeInstruction.INVOKEINTERFACE),
+                        Template.ResultCombo(EnumSet.of(Template.Kind.INTERFACE),
+                                             EnumSet.of(MethodData.Access.PUBLIC),
+                                             EnumSet.of(MethodData.Context.STATIC),
+                                             EnumSet.of(ClassData.Package.SAME,
+                                                        ClassData.Package.DIFFERENT)),
+                        Template.OverrideAbstractExpectedIface,
+                        Template.IfaceMethodrefNotEqualsExpected,
+                        Template.IgnoredAbstract,
+                        Template.AllCallsiteCases,
+                        Template.IfaceMethodrefSelection),
+
+                /* methodref is a class */
+                /* Group 170: methodref = expected */
+                new TestGroup.Simple(initBuilder,
+                        Template.SetInvoke(SelectionResolutionTestCase.InvokeInstruction.INVOKEINTERFACE),
+                        Template.ResultCombo(EnumSet.of(Template.Kind.CLASS),
+                                             EnumSet.of(MethodData.Access.PUBLIC,
+                                                        MethodData.Access.PACKAGE,
+                                                        MethodData.Access.PROTECTED,
+                                                        MethodData.Access.PRIVATE),
+                                             EnumSet.of(MethodData.Context.STATIC),
+                                             EnumSet.of(ClassData.Package.SAME,
+                                                        ClassData.Package.DIFFERENT)),
+                        Template.OverrideAbstractExpectedClass,
+                        Template.MethodrefEqualsExpected,
+                        Template.IgnoredAbstract,
+                        Template.AllCallsiteCases,
+                        Template.MethodrefSelectionResolvedIsClass),
+                /* Group 171: methodref != expected, expected is class */
+                new TestGroup.Simple(initBuilder,
+                        Template.SetInvoke(SelectionResolutionTestCase.InvokeInstruction.INVOKEINTERFACE),
+                        Template.ResultCombo(EnumSet.of(Template.Kind.CLASS),
+                                             EnumSet.of(MethodData.Access.PUBLIC,
+                                                        MethodData.Access.PACKAGE,
+                                                        MethodData.Access.PROTECTED,
+                                                        MethodData.Access.PRIVATE),
+                                             EnumSet.of(MethodData.Context.STATIC),
+                                             EnumSet.of(ClassData.Package.SAME,
+                                                        ClassData.Package.DIFFERENT)),
+                        Template.OverrideAbstractExpectedClass,
+                        Template.MethodrefNotEqualsExpectedClass,
+                        Template.IgnoredAbstract,
+                        Template.AllCallsiteCases,
+                        Template.MethodrefSelectionResolvedIsClass),
+                /* Group 172: methodref != expected expected is interface */
+                new TestGroup.Simple(initBuilder,
+                        Template.SetInvoke(SelectionResolutionTestCase.InvokeInstruction.INVOKEINTERFACE),
+                        Template.ResultCombo(EnumSet.of(Template.Kind.INTERFACE),
+                                             EnumSet.of(MethodData.Access.PUBLIC,
+                                                        MethodData.Access.PRIVATE),
+                                             EnumSet.of(MethodData.Context.STATIC),
+                                             EnumSet.of(ClassData.Package.SAME,
+                                                        ClassData.Package.DIFFERENT)),
+                        Template.OverrideAbstractExpectedIface,
+                        Template.MethodrefNotEqualsExpectedIface,
+                        Template.IgnoredAbstract,
+                        Template.AllCallsiteCases,
+                        Template.MethodrefSelectionResolvedIsIface),
+                /* Group 173: ambiguous resolution */
+                new TestGroup.Simple(initBuilder,
+                        Template.SetInvoke(SelectionResolutionTestCase.InvokeInstruction.INVOKEINTERFACE),
+                        Template.ResultCombo(EnumSet.of(Template.Kind.INTERFACE),
+                                             EnumSet.of(MethodData.Access.PUBLIC),
+                                             EnumSet.of(MethodData.Context.INSTANCE),
+                                             EnumSet.of(ClassData.Package.SAME,
+                                                        ClassData.Package.DIFFERENT)),
+                        Template.OverrideAbstractExpectedIface,
+                        Template.IfaceMethodrefAmbiguous,
+                        Template.IgnoredAbstract,
+                        Template.AllCallsiteCases,
+                        Template.IfaceMethodrefSelectionNoOverride),
+                /* Group 174: ambiguous selection */
+                new TestGroup.Simple(initBuilder,
+                        Template.SetInvoke(SelectionResolutionTestCase.InvokeInstruction.INVOKEINTERFACE),
+                        Template.ResultCombo(EnumSet.of(Template.Kind.INTERFACE),
+                                             EnumSet.of(MethodData.Access.PUBLIC),
+                                             EnumSet.of(MethodData.Context.INSTANCE),
+                                             EnumSet.of(ClassData.Package.SAME,
+                                                        ClassData.Package.DIFFERENT)),
+                        Template.OverrideAbstractExpectedIface,
+                        Template.IfaceMethodrefNotEqualsExpected,
+                        Template.IgnoredAbstract,
+                        Template.AllCallsiteCases,
+                        Template.IfaceMethodrefAmbiguousResolvedIsIface),
+
+                /* Group 175: private method in interface */
+                new TestGroup.Simple(initBuilder,
+                        Template.SetInvoke(SelectionResolutionTestCase.InvokeInstruction.INVOKEINTERFACE),
+                        Template.ResultCombo(EnumSet.of(Template.Kind.INTERFACE),
+                                             EnumSet.of(MethodData.Access.PRIVATE),
+                                             EnumSet.of(MethodData.Context.INSTANCE),
+                                             EnumSet.of(ClassData.Package.SAME)),
+                        Template.OverrideAbstractExpectedIface,
+                        Template.MethodrefEqualsExpected,
+                        Template.IgnoredAbstract,
+                        Template.CallsiteEqualsMethodref,
+                        Template.IfaceMethodrefSelection)
+            );
+
+    private InvokeInterfaceICCE() {
+        super(testgroups);
+    }
+
+    public static void main(final String... args) {
+        new InvokeInterfaceICCE().run();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/SelectionResolution/InvokeInterfaceSuccessTest.java	Sat Apr 02 05:39:25 2016 +0200
@@ -0,0 +1,148 @@
+/*
+ * 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
+ * @summary Test of method selection and resolution cases that
+ * generate InvokeInterfaceSuccessTest
+ * @modules java.base/jdk.internal.org.objectweb.asm
+ * @library /runtime/SelectionResolution/classes
+ * @build selectionresolution.*
+ * @run main/othervm/timeout=300 -XX:+IgnoreUnrecognizedVMOptions -XX:-VerifyDependencies InvokeInterfaceSuccessTest
+ */
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.EnumSet;
+import selectionresolution.ClassData;
+import selectionresolution.MethodData;
+import selectionresolution.SelectionResolutionTest;
+import selectionresolution.SelectionResolutionTestCase;
+import selectionresolution.Template;
+
+public class InvokeInterfaceSuccessTest extends SelectionResolutionTest {
+
+    private static final SelectionResolutionTestCase.Builder initBuilder =
+        new SelectionResolutionTestCase.Builder();
+
+    static {
+        initBuilder.invoke = SelectionResolutionTestCase.InvokeInstruction.INVOKEINTERFACE;
+    }
+
+    private static final Collection<TestGroup> testgroups =
+        Arrays.asList(
+                /* invokeinterface tests */
+
+                /* Group 40: callsite = methodref = expected */
+                new TestGroup.Simple(initBuilder,
+                        Template.ResultCombo(EnumSet.of(Template.Kind.INTERFACE),
+                                             EnumSet.of(MethodData.Access.PUBLIC),
+                                             EnumSet.of(MethodData.Context.INSTANCE,
+                                                        MethodData.Context.ABSTRACT),
+                                             EnumSet.of(ClassData.Package.SAME)),
+                        Template.OverrideAbstractExpectedIface,
+                        Template.MethodrefEqualsExpected,
+                        Template.IgnoredAbstract,
+                        Template.CallsiteEqualsMethodref,
+                        Template.IfaceMethodrefSelection,
+                        Template.SelectionOverrideAbstract),
+                /* Group 41: callsite = methodref, methodref != expected */
+                new TestGroup.Simple(initBuilder,
+                        Template.ResultCombo(EnumSet.of(Template.Kind.INTERFACE),
+                                             EnumSet.of(MethodData.Access.PUBLIC),
+                                             EnumSet.of(MethodData.Context.INSTANCE,
+                                                        MethodData.Context.ABSTRACT),
+                                             EnumSet.of(ClassData.Package.SAME,
+                                                        ClassData.Package.DIFFERENT)),
+                        Template.OverrideAbstractExpectedIface,
+                        Template.IfaceMethodrefNotEqualsExpected,
+                        Template.IgnoredAbstract,
+                        Template.CallsiteEqualsMethodref,
+                        Template.IfaceMethodrefSelection,
+                        Template.SelectionOverrideAbstract),
+                /* Group 42: callsite :> methodref, methodref = expected */
+                new TestGroup.Simple(initBuilder,
+                        Template.ResultCombo(EnumSet.of(Template.Kind.INTERFACE),
+                                             EnumSet.of(MethodData.Access.PUBLIC),
+                                             EnumSet.of(MethodData.Context.INSTANCE,
+                                                        MethodData.Context.ABSTRACT),
+                                             EnumSet.of(ClassData.Package.SAME,
+                                                        ClassData.Package.DIFFERENT)),
+                        Template.OverrideAbstractExpectedIface,
+                        Template.MethodrefEqualsExpected,
+                        Template.IgnoredAbstract,
+                        Template.CallsiteSubclassMethodref,
+                        Template.IfaceMethodrefSelection,
+                        Template.SelectionOverrideAbstract),
+                /* Group 43: callsite :> methodref, methodref != expected */
+                new TestGroup.Simple(initBuilder,
+                        Template.ResultCombo(EnumSet.of(Template.Kind.INTERFACE),
+                                             EnumSet.of(MethodData.Access.PUBLIC),
+                                             EnumSet.of(MethodData.Context.INSTANCE,
+                                                        MethodData.Context.ABSTRACT),
+                                             EnumSet.of(ClassData.Package.SAME,
+                                                        ClassData.Package.DIFFERENT)),
+                        Template.OverrideAbstractExpectedIface,
+                        Template.IfaceMethodrefNotEqualsExpected,
+                        Template.IgnoredAbstract,
+                        Template.CallsiteSubclassMethodref,
+                        Template.IfaceMethodrefSelection,
+                        Template.SelectionOverrideAbstract),
+                /* Group 44: callsite unrelated to methodref, methodref = expected */
+                new TestGroup.Simple(initBuilder,
+                        Template.ResultCombo(EnumSet.of(Template.Kind.INTERFACE),
+                                             EnumSet.of(MethodData.Access.PUBLIC),
+                                             EnumSet.of(MethodData.Context.INSTANCE,
+                                                        MethodData.Context.ABSTRACT),
+                                             EnumSet.of(ClassData.Package.SAME,
+                                                        ClassData.Package.DIFFERENT)),
+                        Template.OverrideAbstractExpectedIface,
+                        Template.MethodrefEqualsExpected,
+                        Template.IgnoredAbstract,
+                        Template.CallsiteUnrelatedToMethodref,
+                        Template.IfaceMethodrefSelection,
+                        Template.SelectionOverrideAbstract),
+                /* Group 45: callsite unrelated to methodref, methodref != expected */
+                new TestGroup.Simple(initBuilder,
+                        Template.ResultCombo(EnumSet.of(Template.Kind.INTERFACE),
+                                             EnumSet.of(MethodData.Access.PUBLIC),
+                                             EnumSet.of(MethodData.Context.INSTANCE,
+                                                        MethodData.Context.ABSTRACT),
+                                             EnumSet.of(ClassData.Package.SAME,
+                                                        ClassData.Package.DIFFERENT)),
+                        Template.OverrideAbstractExpectedIface,
+                        Template.IfaceMethodrefNotEqualsExpected,
+                        Template.IgnoredAbstract,
+                        Template.CallsiteUnrelatedToMethodref,
+                        Template.IfaceMethodrefSelection,
+                        Template.SelectionOverrideAbstract)
+            );
+
+    private InvokeInterfaceSuccessTest() {
+        super(testgroups);
+    }
+
+    public static void main(final String... args) {
+        new InvokeInterfaceSuccessTest().run();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/SelectionResolution/InvokeSpecialICCE.java	Sat Apr 02 05:39:25 2016 +0200
@@ -0,0 +1,126 @@
+/*
+ * 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
+ * @summary Test of method selection and resolution cases that
+ * generate IncompatibleClassChangeError
+ * @modules java.base/jdk.internal.org.objectweb.asm
+ * @library /runtime/SelectionResolution/classes
+ * @build selectionresolution.*
+ * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:-VerifyDependencies InvokeSpecialICCE
+ */
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.EnumSet;
+import selectionresolution.ClassData;
+import selectionresolution.MethodData;
+import selectionresolution.Result;
+import selectionresolution.SelectionResolutionTest;
+import selectionresolution.SelectionResolutionTestCase;
+import selectionresolution.Template;
+
+public class InvokeSpecialICCE extends SelectionResolutionTest {
+
+    private static final SelectionResolutionTestCase.Builder initBuilder =
+        new SelectionResolutionTestCase.Builder();
+
+    static {
+        initBuilder.setResult(Result.ICCE);
+    }
+
+    private static final Collection<TestGroup> testgroups =
+        Arrays.asList(
+                /* invokespecial tests */
+                /* resolved method is static*/
+                /* Group 170: methodref = expected */
+                new TestGroup.Simple(initBuilder,
+                        Template.SetInvoke(SelectionResolutionTestCase.InvokeInstruction.INVOKESPECIAL),
+                        Template.ResultCombo(EnumSet.of(Template.Kind.CLASS),
+                                             EnumSet.of(MethodData.Access.PUBLIC,
+                                                        MethodData.Access.PACKAGE,
+                                                        MethodData.Access.PROTECTED,
+                                                        MethodData.Access.PRIVATE),
+                                             EnumSet.of(MethodData.Context.STATIC),
+                                             EnumSet.of(ClassData.Package.SAME)),
+                        Template.OverrideAbstractExpectedClass,
+                        Template.MethodrefEqualsExpected,
+                        Template.IgnoredAbstract,
+                        Template.InvokespecialCallsiteCases,
+                        Template.ObjectrefAssignableToCallsite),
+                /* Group 171: methodref != expected, expected is class */
+                new TestGroup.Simple(initBuilder,
+                        Template.SetInvoke(SelectionResolutionTestCase.InvokeInstruction.INVOKESPECIAL),
+                        Template.ResultCombo(EnumSet.of(Template.Kind.CLASS),
+                                             EnumSet.of(MethodData.Access.PUBLIC,
+                                                        MethodData.Access.PACKAGE,
+                                                        MethodData.Access.PROTECTED,
+                                                        MethodData.Access.PRIVATE),
+                                             EnumSet.of(MethodData.Context.STATIC),
+                                             EnumSet.of(ClassData.Package.SAME,
+                                                        ClassData.Package.DIFFERENT)),
+                        Template.OverrideAbstractExpectedClass,
+                        Template.MethodrefNotEqualsExpectedClass,
+                        Template.IgnoredAbstract,
+                        Template.InvokespecialCallsiteCases,
+                        Template.ObjectrefAssignableToCallsite),
+                /* Group 172: methodref != expected, expected is interface */
+                new TestGroup.Simple(initBuilder,
+                        Template.SetInvoke(SelectionResolutionTestCase.InvokeInstruction.INVOKESPECIAL),
+                        Template.ResultCombo(EnumSet.of(Template.Kind.INTERFACE),
+                                             EnumSet.of(MethodData.Access.PUBLIC,
+                                                        MethodData.Access.PRIVATE),
+                                             EnumSet.of(MethodData.Context.STATIC),
+                                             EnumSet.of(ClassData.Package.SAME,
+                                                        ClassData.Package.DIFFERENT)),
+                        Template.OverrideAbstractExpectedIface,
+                        Template.MethodrefNotEqualsExpectedIface,
+                        Template.IgnoredAbstract,
+                        Template.InvokespecialCallsiteCases,
+                        Template.ObjectrefAssignableToCallsite),
+
+                /* Group 173: Ambiguous resolution */
+                new TestGroup.Simple(initBuilder,
+                        Template.SetInvoke(SelectionResolutionTestCase.InvokeInstruction.INVOKESPECIAL),
+                        Template.ResultCombo(EnumSet.of(Template.Kind.INTERFACE),
+                                             EnumSet.of(MethodData.Access.PUBLIC,
+                                                        MethodData.Access.PRIVATE),
+                                             EnumSet.allOf(MethodData.Context.class),
+                                             EnumSet.of(ClassData.Package.SAME,
+                                                        ClassData.Package.DIFFERENT)),
+                        Template.OverrideAbstractExpectedIface,
+                        Template.MethodrefAmbiguous,
+                        Template.IgnoredAbstract,
+                        Template.InvokespecialCallsiteCases,
+                        Template.ObjectrefAssignableToCallsite)
+            );
+
+    private InvokeSpecialICCE() {
+        super(testgroups);
+    }
+
+    public static void main(final String... args) {
+        new InvokeSpecialICCE().run();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/SelectionResolution/InvokeSpecialSuccessTest.java	Sat Apr 02 05:39:25 2016 +0200
@@ -0,0 +1,301 @@
+/*
+ * 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
+ * @summary Test of method selection and resolution cases that
+ * generate InvokeSpecialSuccessTest
+ * @modules java.base/jdk.internal.org.objectweb.asm
+ * @library /runtime/SelectionResolution/classes
+ * @build selectionresolution.*
+ * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:-VerifyDependencies InvokeSpecialSuccessTest
+ */
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.EnumSet;
+import selectionresolution.ClassData;
+import selectionresolution.MethodData;
+import selectionresolution.SelectionResolutionTest;
+import selectionresolution.SelectionResolutionTestCase;
+import selectionresolution.Template;
+
+public class InvokeSpecialSuccessTest extends SelectionResolutionTest {
+
+    private static final SelectionResolutionTestCase.Builder initBuilder =
+        new SelectionResolutionTestCase.Builder();
+
+    static {
+        initBuilder.invoke = SelectionResolutionTestCase.InvokeInstruction.INVOKESPECIAL;
+    }
+
+    private static final Collection<TestGroup> testgroups =
+        Arrays.asList(
+                /* Group 46: callsite = methodref = expected */
+                new TestGroup.Simple(initBuilder,
+                        Template.ResultCombo(EnumSet.of(Template.Kind.CLASS),
+                                             EnumSet.of(MethodData.Access.PUBLIC,
+                                                        MethodData.Access.PACKAGE,
+                                                        MethodData.Access.PROTECTED,
+                                                        MethodData.Access.PRIVATE),
+                                             EnumSet.of(MethodData.Context.INSTANCE),
+                                             EnumSet.of(ClassData.Package.SAME)),
+                        Template.OverrideAbstractExpectedClass,
+                        Template.MethodrefEqualsExpected,
+                        Template.IgnoredAbstract,
+                        Template.CallsiteEqualsMethodref,
+                        Template.ObjectrefAssignableToCallsite),
+                /* Group 47: callsite = methodref, methodref != expected,
+                 * expected is class, expected and callsite in the same package
+                 */
+                new TestGroup.Simple(initBuilder,
+                        Template.ResultCombo(EnumSet.of(Template.Kind.CLASS),
+                                             EnumSet.of(MethodData.Access.PUBLIC,
+                                                        MethodData.Access.PACKAGE,
+                                                        MethodData.Access.PROTECTED),
+                                             EnumSet.of(MethodData.Context.INSTANCE),
+                                             EnumSet.of(ClassData.Package.SAME)),
+                        Template.OverrideAbstractExpectedClass,
+                        Template.MethodrefNotEqualsExpectedClass,
+                        Template.IgnoredAbstract,
+                        Template.CallsiteEqualsMethodref,
+                        Template.ObjectrefAssignableToCallsite),
+                /* Group 48: callsite = methodref, methodref != expected,
+                 * expected is interface, expected and callsite in the same package
+                 */
+                new TestGroup.Simple(initBuilder,
+                        Template.ResultCombo(EnumSet.of(Template.Kind.INTERFACE),
+                                             EnumSet.of(MethodData.Access.PUBLIC),
+                                             EnumSet.of(MethodData.Context.INSTANCE),
+                                             EnumSet.of(ClassData.Package.SAME)),
+                        Template.OverrideAbstractExpectedIface,
+                        Template.MethodrefNotEqualsExpectedIface,
+                        Template.IgnoredAbstract,
+                        Template.CallsiteEqualsMethodref,
+                        Template.ObjectrefAssignableToCallsite),
+                /* Group 49: callsite :> methodref, methodref = expected,
+                 * expected is class, expected and callsite in the same package
+                 */
+                new TestGroup.Simple(initBuilder,
+                        Template.ResultCombo(EnumSet.of(Template.Kind.CLASS),
+                                             EnumSet.of(MethodData.Access.PUBLIC,
+                                                        MethodData.Access.PACKAGE,
+                                                        MethodData.Access.PROTECTED),
+                                             EnumSet.of(MethodData.Context.INSTANCE),
+                                             EnumSet.of(ClassData.Package.SAME)),
+                        Template.OverrideAbstractExpectedClass,
+                        Template.MethodrefEqualsExpected,
+                        Template.IgnoredAbstract,
+                        Template.CallsiteSubclassMethodref,
+                        Template.ObjectrefAssignableToCallsite),
+                /* Group 50: callsite :> methodref, methodref != expected,
+                 * expected is class, expected and callsite in the same package
+                 */
+                new TestGroup.Simple(initBuilder,
+                        Template.ResultCombo(EnumSet.of(Template.Kind.CLASS),
+                                             EnumSet.of(MethodData.Access.PUBLIC,
+                                                        MethodData.Access.PACKAGE,
+                                                        MethodData.Access.PROTECTED),
+                                             EnumSet.of(MethodData.Context.INSTANCE),
+                                             EnumSet.of(ClassData.Package.SAME)),
+                        Template.OverrideAbstractExpectedClass,
+                        Template.MethodrefNotEqualsExpectedClass,
+                        Template.IgnoredAbstract,
+                        Template.CallsiteSubclassMethodref,
+                        Template.ObjectrefAssignableToCallsite),
+                /* Group 51: callsite :> methodref, methodref != expected,
+                 * expected is interface, expected and callsite in the same package
+                 */
+                new TestGroup.Simple(initBuilder,
+                        Template.ResultCombo(EnumSet.of(Template.Kind.INTERFACE),
+                                             EnumSet.of(MethodData.Access.PUBLIC),
+                                             EnumSet.of(MethodData.Context.INSTANCE),
+                                             EnumSet.of(ClassData.Package.SAME)),
+                        Template.OverrideAbstractExpectedIface,
+                        Template.MethodrefNotEqualsExpectedIface,
+                        Template.IgnoredAbstract,
+                        Template.CallsiteSubclassMethodref,
+                        Template.ObjectrefAssignableToCallsite),
+                /* Group 52: callsite = methodref, methodref != expected,
+                 * expected is class, expected and callsite not in the same package
+                 */
+                new TestGroup.Simple(initBuilder,
+                        Template.ResultCombo(EnumSet.of(Template.Kind.CLASS),
+                                             EnumSet.of(MethodData.Access.PUBLIC,
+                                                        MethodData.Access.PROTECTED),
+                                             EnumSet.of(MethodData.Context.INSTANCE),
+                                             EnumSet.of(ClassData.Package.DIFFERENT)),
+                        Template.OverrideAbstractExpectedClass,
+                        Template.MethodrefNotEqualsExpectedClass,
+                        Template.IgnoredAbstract,
+                        Template.CallsiteEqualsMethodref,
+                        Template.ObjectrefAssignableToCallsite),
+                /* Group 53: callsite = methodref, methodref != expected,
+                 * expected is interface, expected and callsite not in the same package
+                 */
+                new TestGroup.Simple(initBuilder,
+                        Template.ResultCombo(EnumSet.of(Template.Kind.INTERFACE),
+                                             EnumSet.of(MethodData.Access.PUBLIC),
+                                             EnumSet.of(MethodData.Context.INSTANCE),
+                                             EnumSet.of(ClassData.Package.DIFFERENT)),
+                        Template.OverrideAbstractExpectedIface,
+                        Template.MethodrefNotEqualsExpectedIface,
+                        Template.IgnoredAbstract,
+                        Template.CallsiteEqualsMethodref,
+                        Template.ObjectrefAssignableToCallsite),
+                /* Group 54: callsite :> methodref, methodref = expected,
+                 * expected is class, expected and callsite not in the same package
+                 */
+                new TestGroup.Simple(initBuilder,
+                        Template.ResultCombo(EnumSet.of(Template.Kind.CLASS),
+                                             EnumSet.of(MethodData.Access.PUBLIC,
+                                                        MethodData.Access.PROTECTED),
+                                             EnumSet.of(MethodData.Context.INSTANCE),
+                                             EnumSet.of(ClassData.Package.DIFFERENT)),
+                        Template.OverrideAbstractExpectedClass,
+                        Template.MethodrefEqualsExpected,
+                        Template.IgnoredAbstract,
+                        Template.CallsiteSubclassMethodref,
+                        Template.ObjectrefAssignableToCallsite),
+
+                /* Group 55: callsite :> methodref, methodref != expected,
+                 * expected is class, expected and callsite not in the same package
+                 */
+                new TestGroup.Simple(initBuilder,
+                        Template.ResultCombo(EnumSet.of(Template.Kind.CLASS),
+                                             EnumSet.of(MethodData.Access.PUBLIC,
+                                                        MethodData.Access.PROTECTED),
+                                             EnumSet.of(MethodData.Context.INSTANCE),
+                                             EnumSet.of(ClassData.Package.DIFFERENT)),
+                        Template.OverrideAbstractExpectedClass,
+                        Template.MethodrefNotEqualsExpectedClass,
+                        Template.IgnoredAbstract,
+                        Template.CallsiteSubclassMethodref,
+                        Template.ObjectrefAssignableToCallsite),
+                /* Group 56: callsite :> methodref, methodref != expected,
+                 * expected is interface, expected and callsite not in the same package
+                 */
+                new TestGroup.Simple(initBuilder,
+                        Template.ResultCombo(EnumSet.of(Template.Kind.INTERFACE),
+                                             EnumSet.of(MethodData.Access.PUBLIC),
+                                             EnumSet.of(MethodData.Context.INSTANCE),
+                                             EnumSet.of(ClassData.Package.DIFFERENT)),
+                        Template.OverrideAbstractExpectedIface,
+                        Template.MethodrefNotEqualsExpectedIface,
+                        Template.IgnoredAbstract,
+                        Template.CallsiteSubclassMethodref,
+                        Template.ObjectrefAssignableToCallsite),
+
+                /* Funny cases */
+                /* Group 57: callsite = methodref, methodref =
+                 * expected expected is interface, expected and
+                 * callsite in a different package
+                 */
+                new TestGroup.Simple(initBuilder,
+                        Template.ResultCombo(EnumSet.of(Template.Kind.CLASS),
+                                             EnumSet.of(MethodData.Access.PROTECTED),
+                                             EnumSet.of(MethodData.Context.INSTANCE),
+                                             EnumSet.of(ClassData.Package.DIFFERENT)),
+                        Template.OverrideAbstractExpectedClass,
+                        Template.MethodrefEqualsExpected,
+                        Template.IgnoredAbstract,
+                        Template.CallsiteEqualsMethodref,
+                        Template.ObjectrefEqualsOrExactSubclassOfCallsite),
+                /* Group 58: callsite = methodref, methodref \!=
+                 * expected expected is interface, expected and
+                 * callsite in a different package */
+                new TestGroup.Simple(initBuilder,
+                        Template.ResultCombo(EnumSet.of(Template.Kind.CLASS),
+                                             EnumSet.of(MethodData.Access.PROTECTED),
+                                             EnumSet.of(MethodData.Context.INSTANCE),
+                                             EnumSet.of(ClassData.Package.DIFFERENT)),
+                        Template.MethodrefNotEqualsExpectedClass,
+                        Template.IgnoredAbstract,
+                        Template.CallsiteEqualsMethodref,
+                        Template.ObjectrefEqualsOrExactSubclassOfCallsite),
+                /* Group 59: callsite subclass methodref, methodref =
+                 * expected expected is interface, expected and
+                 * callsite in a different package */
+                new TestGroup.Simple(initBuilder,
+                        Template.ResultCombo(EnumSet.of(Template.Kind.CLASS),
+                                             EnumSet.of(MethodData.Access.PROTECTED),
+                                             EnumSet.of(MethodData.Context.INSTANCE),
+                                             EnumSet.of(ClassData.Package.DIFFERENT)),
+                        Template.OverrideAbstractExpectedClass,
+                        Template.MethodrefEqualsExpected,
+                        Template.IgnoredAbstract,
+                        Template.CallsiteSubclassMethodref,
+                        Template.ObjectrefEqualsOrExactSubclassOfCallsite),
+                /* Group 60: callsite subclass methodref, methodref
+                 * \!= expected expected is interface, expected and
+                 * callsite in a different package */
+                new TestGroup.Simple(initBuilder,
+                        Template.ResultCombo(EnumSet.of(Template.Kind.CLASS),
+                                             EnumSet.of(MethodData.Access.PROTECTED),
+                                             EnumSet.of(MethodData.Context.INSTANCE),
+                                             EnumSet.of(ClassData.Package.DIFFERENT)),
+                        Template.OverrideAbstractExpectedClass,
+                        Template.MethodrefNotEqualsExpectedClass,
+                        Template.IgnoredAbstract,
+                        Template.CallsiteSubclassMethodref,
+                        Template.ObjectrefEqualsOrExactSubclassOfCallsite),
+
+                /* Methodref is an interface */
+                /* Group 61: callsite :> methodref, methodref = expected,
+                 * expected is interface, expected and callsite in the same package
+                 */
+                new TestGroup.Simple(initBuilder,
+                        Template.ResultCombo(EnumSet.of(Template.Kind.INTERFACE),
+                                             EnumSet.of(MethodData.Access.PUBLIC),
+                                             EnumSet.of(MethodData.Context.INSTANCE),
+                                             EnumSet.of(ClassData.Package.SAME,
+                                                        ClassData.Package.DIFFERENT)),
+                        Template.OverrideAbstractExpectedIface,
+                        Template.MethodrefEqualsExpected,
+                        Template.IgnoredAbstract,
+                        Template.CallsiteSubclassMethodref,
+                        Template.ObjectrefAssignableToCallsite),
+                /* Group 62: callsite :> methodref, methodref != expected,
+                 * expected is interface, expected and callsite in the same package
+                 */
+                new TestGroup.Simple(initBuilder,
+                        Template.ResultCombo(EnumSet.of(Template.Kind.INTERFACE),
+                                             EnumSet.of(MethodData.Access.PUBLIC),
+                                             EnumSet.of(MethodData.Context.INSTANCE),
+                                             EnumSet.of(ClassData.Package.SAME,
+                                                        ClassData.Package.DIFFERENT)),
+                        Template.OverrideAbstractExpectedIface,
+                        Template.IfaceMethodrefNotEqualsExpected,
+                        Template.IgnoredAbstract,
+                        Template.CallsiteSubclassMethodref,
+                        Template.ObjectrefAssignableToCallsite)
+            );
+
+    private InvokeSpecialSuccessTest() {
+        super(testgroups);
+    }
+
+    public static void main(final String... args) {
+        new InvokeSpecialSuccessTest().run();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/SelectionResolution/InvokeStaticICCE.java	Sat Apr 02 05:39:25 2016 +0200
@@ -0,0 +1,126 @@
+/*
+ * 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
+ * @summary Test of invokestatic method selection and resolution cases that
+ * generate IncompatibleClassChangeError
+ * @modules java.base/jdk.internal.org.objectweb.asm
+ * @library /runtime/SelectionResolution/classes
+ * @build selectionresolution.*
+ * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:-VerifyDependencies InvokeStaticICCE
+ */
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.EnumSet;
+import selectionresolution.ClassData;
+import selectionresolution.MethodData;
+import selectionresolution.Result;
+import selectionresolution.SelectionResolutionTest;
+import selectionresolution.SelectionResolutionTestCase;
+import selectionresolution.Template;
+
+public class InvokeStaticICCE extends SelectionResolutionTest {
+
+    private static final SelectionResolutionTestCase.Builder initBuilder =
+        new SelectionResolutionTestCase.Builder();
+
+    static {
+        initBuilder.setResult(Result.ICCE);
+    }
+
+    private static final Collection<TestGroup> testgroups =
+        Arrays.asList(
+                /* invokestatic tests */
+                /* Group 157: methodref = expected */
+                new TestGroup.Simple(initBuilder,
+                        Template.SetInvoke(SelectionResolutionTestCase.InvokeInstruction.INVOKESTATIC),
+                        Template.ResultCombo(EnumSet.of(Template.Kind.CLASS),
+                                             EnumSet.of(MethodData.Access.PUBLIC,
+                                                        MethodData.Access.PACKAGE,
+                                                        MethodData.Access.PROTECTED,
+                                                        MethodData.Access.PRIVATE),
+                                             EnumSet.of(MethodData.Context.INSTANCE,
+                                                        MethodData.Context.ABSTRACT),
+                                             EnumSet.of(ClassData.Package.SAME,
+                                                        ClassData.Package.DIFFERENT)),
+                        Template.OverrideAbstractExpectedClass,
+                        Template.MethodrefEqualsExpected,
+                        Template.AllCallsiteCases,
+                        Template.TrivialObjectref),
+                /* Group 158: methodref = expected, expected is interface */
+                new TestGroup.Simple(initBuilder,
+                        Template.SetInvoke(SelectionResolutionTestCase.InvokeInstruction.INVOKESTATIC),
+                        Template.ResultCombo(EnumSet.of(Template.Kind.INTERFACE),
+                                             EnumSet.of(MethodData.Access.PUBLIC,
+                                                        MethodData.Access.PRIVATE),
+                                             EnumSet.of(MethodData.Context.INSTANCE,
+                                                        MethodData.Context.ABSTRACT),
+                                             EnumSet.of(ClassData.Package.SAME,
+                                                        ClassData.Package.DIFFERENT)),
+                        Template.OverrideAbstractExpectedIface,
+                        Template.MethodrefEqualsExpected,
+                        Template.AllCallsiteCases,
+                        Template.TrivialObjectref),
+                /* Group 159: methodref != expected, expected is class
+                 */
+                new TestGroup.Simple(initBuilder,
+                        Template.SetInvoke(SelectionResolutionTestCase.InvokeInstruction.INVOKESTATIC),
+                        Template.ResultCombo(EnumSet.of(Template.Kind.CLASS),
+                                             EnumSet.of(MethodData.Access.PUBLIC,
+                                                        MethodData.Access.PACKAGE,
+                                                        MethodData.Access.PROTECTED,
+                                                        MethodData.Access.PRIVATE),
+                                             EnumSet.of(MethodData.Context.INSTANCE,
+                                                        MethodData.Context.ABSTRACT),
+                                             EnumSet.of(ClassData.Package.SAME,
+                                                        ClassData.Package.DIFFERENT)),
+                        Template.OverrideAbstractExpectedClass,
+                        Template.MethodrefNotEqualsExpectedClass,
+                        Template.AllCallsiteCases,
+                        Template.TrivialObjectref),
+                /* Group 160: methodref = expected, expected is interface */
+                new TestGroup.Simple(initBuilder,
+                        Template.SetInvoke(SelectionResolutionTestCase.InvokeInstruction.INVOKESTATIC),
+                        Template.ResultCombo(EnumSet.of(Template.Kind.INTERFACE),
+                                             EnumSet.of(MethodData.Access.PUBLIC,
+                                                        MethodData.Access.PRIVATE),
+                                             EnumSet.of(MethodData.Context.INSTANCE,
+                                                        MethodData.Context.ABSTRACT),
+                                             EnumSet.of(ClassData.Package.SAME,
+                                                        ClassData.Package.DIFFERENT)),
+                        Template.OverrideAbstractExpectedIface,
+                        Template.MethodrefNotEqualsExpectedIface,
+                        Template.AllCallsiteCases,
+                        Template.TrivialObjectref)
+            );
+
+    private InvokeStaticICCE() {
+        super(testgroups);
+    }
+
+    public static void main(final String... args) {
+        new InvokeStaticICCE().run();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/SelectionResolution/InvokeStaticSuccessTest.java	Sat Apr 02 05:39:25 2016 +0200
@@ -0,0 +1,243 @@
+/*
+ * 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
+ * @summary Test of method selection and resolution cases that
+ * generate InvokeStaticSuccessTest
+ * @modules java.base/jdk.internal.org.objectweb.asm
+ * @library /runtime/SelectionResolution/classes
+ * @build selectionresolution.*
+ * @run main InvokeStaticSuccessTest
+ */
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.EnumSet;
+import selectionresolution.ClassData;
+import selectionresolution.MethodData;
+import selectionresolution.SelectionResolutionTest;
+import selectionresolution.SelectionResolutionTestCase;
+import selectionresolution.Template;
+
+public class InvokeStaticSuccessTest extends SelectionResolutionTest {
+
+    private static final SelectionResolutionTestCase.Builder initBuilder =
+        new SelectionResolutionTestCase.Builder();
+
+    static {
+        initBuilder.invoke = SelectionResolutionTestCase.InvokeInstruction.INVOKESTATIC;
+    }
+
+    private static final Collection<TestGroup> testgroups =
+        Arrays.asList(
+                /* invokestatic tests */
+                /* Group 1: callsite = methodref = expected */
+                new TestGroup.Simple(initBuilder,
+                        Template.ResultCombo(EnumSet.of(Template.Kind.CLASS),
+                                             EnumSet.of(MethodData.Access.PUBLIC,
+                                                        MethodData.Access.PACKAGE,
+                                                        MethodData.Access.PROTECTED,
+                                                        MethodData.Access.PRIVATE),
+                                             EnumSet.of(MethodData.Context.STATIC),
+                                             EnumSet.of(ClassData.Package.SAME)),
+                        Template.MethodrefEqualsExpected,
+                        Template.CallsiteEqualsMethodref,
+                        Template.TrivialObjectref),
+                /* Group 2: callsite = methodref, methodref != expected,
+                 * expected is class, expected and callsite in the same package
+                 */
+                new TestGroup.Simple(initBuilder,
+                        Template.ResultCombo(EnumSet.of(Template.Kind.CLASS),
+                                             EnumSet.of(MethodData.Access.PUBLIC,
+                                                        MethodData.Access.PACKAGE,
+                                                        MethodData.Access.PROTECTED),
+                                             EnumSet.of(MethodData.Context.STATIC),
+                                             EnumSet.of(ClassData.Package.SAME)),
+                        Template.MethodrefNotEqualsExpectedClass,
+                        Template.CallsiteEqualsMethodref,
+                        Template.TrivialObjectref),
+                /* Group 3: callsite :> methodref, methodref = expected,
+                 * expected is class, expected and callsite in the same package
+                 */
+                new TestGroup.Simple(initBuilder,
+                        Template.ResultCombo(EnumSet.of(Template.Kind.CLASS),
+                                             EnumSet.of(MethodData.Access.PUBLIC,
+                                                        MethodData.Access.PACKAGE,
+                                                        MethodData.Access.PROTECTED),
+                                             EnumSet.of(MethodData.Context.STATIC),
+                                             EnumSet.of(ClassData.Package.SAME)),
+                        Template.MethodrefEqualsExpected,
+                        Template.CallsiteSubclassMethodref,
+                        Template.TrivialObjectref),
+                /* Group 4: callsite :> methodref, methodref = expected,
+                 * expected is interface, expected and callsite in the same package
+                 */
+                new TestGroup.Simple(initBuilder,
+                        Template.ResultCombo(EnumSet.of(Template.Kind.INTERFACE),
+                                             EnumSet.of(MethodData.Access.PUBLIC),
+                                             EnumSet.of(MethodData.Context.STATIC),
+                                             EnumSet.of(ClassData.Package.SAME)),
+                        Template.MethodrefEqualsExpected,
+                        Template.CallsiteSubclassMethodref,
+                        Template.TrivialObjectref),
+                /* Group 5: callsite :> methodref, methodref != expected,
+                 * expected is class, expected and callsite in the same package
+                 */
+                new TestGroup.Simple(initBuilder,
+                        Template.ResultCombo(EnumSet.of(Template.Kind.CLASS),
+                                             EnumSet.of(MethodData.Access.PUBLIC,
+                                                        MethodData.Access.PACKAGE,
+                                                        MethodData.Access.PROTECTED),
+                                             EnumSet.of(MethodData.Context.STATIC),
+                                             EnumSet.of(ClassData.Package.SAME)),
+                        Template.MethodrefNotEqualsExpectedClass,
+                        Template.CallsiteSubclassMethodref,
+                        Template.TrivialObjectref),
+                /* Group 6: callsite unrelated to methodref, methodref = expected,
+                 * expected is class, expected and callsite in the same package
+                 */
+                new TestGroup.Simple(initBuilder,
+                        Template.ResultCombo(EnumSet.of(Template.Kind.CLASS),
+                                             EnumSet.of(MethodData.Access.PUBLIC,
+                                                        MethodData.Access.PACKAGE,
+                                                        MethodData.Access.PROTECTED),
+                                             EnumSet.of(MethodData.Context.STATIC),
+                                             EnumSet.of(ClassData.Package.SAME)),
+                        Template.MethodrefEqualsExpected,
+                        Template.CallsiteUnrelatedToMethodref,
+                        Template.TrivialObjectref),
+                /* Group 7: callsite unrelated to methodref, methodref = expected,
+                 * expected is interface, expected and callsite in the same package
+                 */
+                new TestGroup.Simple(initBuilder,
+                        Template.ResultCombo(EnumSet.of(Template.Kind.INTERFACE),
+                                             EnumSet.of(MethodData.Access.PUBLIC),
+                                             EnumSet.of(MethodData.Context.STATIC),
+                                             EnumSet.of(ClassData.Package.SAME)),
+                        Template.MethodrefEqualsExpected,
+                        Template.CallsiteUnrelatedToMethodref,
+                        Template.TrivialObjectref),
+                /* Group 8: callsite unrelated to methodref, methodref != expected,
+                 * expected is class, expected and callsite in the same package
+                 */
+                new TestGroup.Simple(initBuilder,
+                        Template.ResultCombo(EnumSet.of(Template.Kind.CLASS),
+                                             EnumSet.of(MethodData.Access.PUBLIC,
+                                                        MethodData.Access.PACKAGE,
+                                                        MethodData.Access.PROTECTED),
+                                             EnumSet.of(MethodData.Context.STATIC),
+                                             EnumSet.of(ClassData.Package.SAME)),
+                        Template.MethodrefNotEqualsExpectedClass,
+                        Template.CallsiteUnrelatedToMethodref,
+                        Template.TrivialObjectref),
+                /* Group 9: callsite = methodref, methodref != expected,
+                 * expected is class, expected and callsite not in the same package
+                 */
+                new TestGroup.Simple(initBuilder,
+                        Template.ResultCombo(EnumSet.of(Template.Kind.CLASS),
+                                             EnumSet.of(MethodData.Access.PUBLIC,
+                                                        MethodData.Access.PROTECTED),
+                                             EnumSet.of(MethodData.Context.STATIC),
+                                             EnumSet.of(ClassData.Package.DIFFERENT)),
+                        Template.MethodrefNotEqualsExpectedClass,
+                        Template.CallsiteEqualsMethodref,
+                        Template.TrivialObjectref),
+                /* Group 10: callsite :> methodref, methodref = expected,
+                 * expected is class, expected and callsite not in the same package
+                 */
+                new TestGroup.Simple(initBuilder,
+                        Template.ResultCombo(EnumSet.of(Template.Kind.CLASS),
+                                             EnumSet.of(MethodData.Access.PUBLIC,
+                                                        MethodData.Access.PROTECTED),
+                                             EnumSet.of(MethodData.Context.STATIC),
+                                             EnumSet.of(ClassData.Package.DIFFERENT)),
+                        Template.MethodrefEqualsExpected,
+                        Template.CallsiteSubclassMethodref,
+                        Template.TrivialObjectref),
+                /* Group 11: callsite :> methodref, methodref = expected,
+                 * expected is interface, expected and callsite not in the same package
+                 */
+                new TestGroup.Simple(initBuilder,
+                        Template.ResultCombo(EnumSet.of(Template.Kind.INTERFACE),
+                                             EnumSet.of(MethodData.Access.PUBLIC),
+                                             EnumSet.of(MethodData.Context.STATIC),
+                                             EnumSet.of(ClassData.Package.DIFFERENT)),
+                        Template.MethodrefEqualsExpected,
+                        Template.CallsiteSubclassMethodref,
+                        Template.TrivialObjectref),
+                /* Group 12: callsite :> methodref, methodref != expected,
+                 * expected is class, expected and callsite not in the same package
+                 */
+                new TestGroup.Simple(initBuilder,
+                        Template.ResultCombo(EnumSet.of(Template.Kind.CLASS),
+                                             EnumSet.of(MethodData.Access.PUBLIC,
+                                                        MethodData.Access.PROTECTED),
+                                             EnumSet.of(MethodData.Context.STATIC),
+                                             EnumSet.of(ClassData.Package.DIFFERENT)),
+                        Template.MethodrefNotEqualsExpectedClass,
+                        Template.CallsiteSubclassMethodref,
+                        Template.TrivialObjectref),
+                /* Group 13: callsite unrelated to methodref, methodref = expected,
+                 * expected is class, expected and callsite not in the same package
+                 */
+                new TestGroup.Simple(initBuilder,
+                        Template.ResultCombo(EnumSet.of(Template.Kind.CLASS),
+                                             EnumSet.of(MethodData.Access.PUBLIC),
+                                             EnumSet.of(MethodData.Context.STATIC),
+                                             EnumSet.of(ClassData.Package.DIFFERENT)),
+                        Template.MethodrefEqualsExpected,
+                        Template.CallsiteUnrelatedToMethodref,
+                        Template.TrivialObjectref),
+                /* Group 14: callsite unrelated to methodref, methodref = expected,
+                 * expected is interface, expected and callsite not in the same package
+                 */
+                new TestGroup.Simple(initBuilder,
+                        Template.ResultCombo(EnumSet.of(Template.Kind.INTERFACE),
+                                             EnumSet.of(MethodData.Access.PUBLIC),
+                                             EnumSet.of(MethodData.Context.STATIC),
+                                             EnumSet.of(ClassData.Package.DIFFERENT)),
+                        Template.MethodrefEqualsExpected,
+                        Template.CallsiteUnrelatedToMethodref,
+                        Template.TrivialObjectref),
+                /* Group 15: callsite unrelated to methodref, methodref != expected,
+                 * expected is class, expected and callsite not in the same package
+                 */
+                new TestGroup.Simple(initBuilder,
+                        Template.ResultCombo(EnumSet.of(Template.Kind.CLASS),
+                                             EnumSet.of(MethodData.Access.PUBLIC),
+                                             EnumSet.of(MethodData.Context.STATIC),
+                                             EnumSet.of(ClassData.Package.DIFFERENT)),
+                        Template.MethodrefNotEqualsExpectedClass,
+                        Template.CallsiteUnrelatedToMethodref,
+                        Template.TrivialObjectref)
+            );
+
+    private InvokeStaticSuccessTest() {
+        super(testgroups);
+    }
+
+    public static void main(final String... args) {
+        new InvokeStaticSuccessTest().run();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/SelectionResolution/InvokeVirtualICCE.java	Sat Apr 02 05:39:25 2016 +0200
@@ -0,0 +1,174 @@
+/*
+ * 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
+ * @summary Test of method selection and resolution cases that
+ * generate IncompatibleClassChangeError
+ * @modules java.base/jdk.internal.org.objectweb.asm
+ * @library /runtime/SelectionResolution/classes
+ * @build selectionresolution.*
+ * @run main/othervm/timeout=1200 -XX:+IgnoreUnrecognizedVMOptions -XX:-VerifyDependencies InvokeVirtualICCE
+ */
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.EnumSet;
+import selectionresolution.ClassData;
+import selectionresolution.MethodData;
+import selectionresolution.Result;
+import selectionresolution.SelectionResolutionTest;
+import selectionresolution.SelectionResolutionTestCase;
+import selectionresolution.Template;
+
+public class InvokeVirtualICCE extends SelectionResolutionTest {
+
+    private static final SelectionResolutionTestCase.Builder initBuilder =
+        new SelectionResolutionTestCase.Builder();
+
+    static {
+        initBuilder.setResult(Result.ICCE);
+    }
+
+    private static final Collection<TestGroup> testgroups =
+        Arrays.asList(
+                /* invokevirtual tests */
+
+                /* resolved method is static*/
+                /* Group 161: callsite = methodref = expected */
+                new TestGroup.Simple(initBuilder,
+                        Template.SetInvoke(SelectionResolutionTestCase.InvokeInstruction.INVOKEVIRTUAL),
+                        Template.ResultCombo(EnumSet.of(Template.Kind.CLASS),
+                                             EnumSet.of(MethodData.Access.PUBLIC,
+                                                        MethodData.Access.PACKAGE,
+                                                        MethodData.Access.PRIVATE),
+                                             EnumSet.of(MethodData.Context.STATIC),
+                                             EnumSet.of(ClassData.Package.SAME,
+                                                        ClassData.Package.DIFFERENT)),
+                        Template.OverrideAbstractExpectedClass,
+                        Template.MethodrefEqualsExpected,
+                        Template.IgnoredAbstract,
+                        Template.AllCallsiteCases,
+                        Template.MethodrefSelectionResolvedIsClass),
+                /* Group 162: callsite = methodref, methodref != expected,
+                 * expected is class, expected and callsite in the same package
+                 */
+                new TestGroup.Simple(initBuilder,
+                        Template.SetInvoke(SelectionResolutionTestCase.InvokeInstruction.INVOKEVIRTUAL),
+                        Template.ResultCombo(EnumSet.of(Template.Kind.CLASS),
+                                             EnumSet.of(MethodData.Access.PUBLIC,
+                                                        MethodData.Access.PACKAGE,
+                                                        MethodData.Access.PRIVATE),
+                                             EnumSet.of(MethodData.Context.STATIC),
+                                             EnumSet.of(ClassData.Package.SAME,
+                                                        ClassData.Package.DIFFERENT)),
+                        Template.OverrideAbstractExpectedClass,
+                        Template.MethodrefNotEqualsExpectedClass,
+                        Template.IgnoredAbstract,
+                        Template.AllCallsiteCases,
+                        Template.MethodrefSelectionResolvedIsClass),
+                /* Group 163: callsite = methodref, methodref != expected,
+                 * expected is interface, expected and callsite in the same package
+                 */
+                new TestGroup.Simple(initBuilder,
+                        Template.SetInvoke(SelectionResolutionTestCase.InvokeInstruction.INVOKEVIRTUAL),
+                        Template.ResultCombo(EnumSet.of(Template.Kind.INTERFACE),
+                                             EnumSet.of(MethodData.Access.PUBLIC,
+                                                        MethodData.Access.PRIVATE),
+                                             EnumSet.of(MethodData.Context.STATIC),
+                                             EnumSet.of(ClassData.Package.SAME,
+                                                        ClassData.Package.DIFFERENT)),
+                        Template.OverrideAbstractExpectedIface,
+                        Template.MethodrefNotEqualsExpectedIface,
+                        Template.IgnoredAbstract,
+                        Template.AllCallsiteCases,
+                        Template.MethodrefSelectionResolvedIsIface),
+
+                /* methodref is an interface */
+                /* Group 164: callsite = methodref = expected */
+                new TestGroup.Simple(initBuilder,
+                        Template.SetInvoke(SelectionResolutionTestCase.InvokeInstruction.INVOKEVIRTUAL),
+                        Template.ResultCombo(EnumSet.of(Template.Kind.INTERFACE),
+                                             EnumSet.of(MethodData.Access.PUBLIC,
+                                                        MethodData.Access.PRIVATE),
+                                             EnumSet.allOf(MethodData.Context.class),
+                                             EnumSet.of(ClassData.Package.SAME,
+                                                        ClassData.Package.DIFFERENT)),
+                        Template.OverrideAbstractExpectedIface,
+                        Template.MethodrefEqualsExpected,
+                        Template.IgnoredAbstract,
+                        Template.AllCallsiteCases,
+                        Template.IfaceMethodrefSelection),
+                /* Group 165: callsite = methodref, methodref != expected,
+                 * expected and callsite in the same package
+                 */
+                new TestGroup.Simple(initBuilder,
+                        Template.SetInvoke(SelectionResolutionTestCase.InvokeInstruction.INVOKEVIRTUAL),
+                        Template.ResultCombo(EnumSet.of(Template.Kind.INTERFACE),
+                                             EnumSet.of(MethodData.Access.PUBLIC,
+                                                        MethodData.Access.PRIVATE),
+                                             EnumSet.allOf(MethodData.Context.class),
+                                             EnumSet.of(ClassData.Package.SAME,
+                                                        ClassData.Package.DIFFERENT)),
+                        Template.OverrideAbstractExpectedIface,
+                        Template.IfaceMethodrefNotEqualsExpected,
+                        Template.IgnoredAbstract,
+                        Template.AllCallsiteCases,
+                        Template.IfaceMethodrefSelection),
+
+                /* Group 166: Ambiguous resolution tests */
+                new TestGroup.Simple(initBuilder,
+                        Template.SetInvoke(SelectionResolutionTestCase.InvokeInstruction.INVOKEVIRTUAL),
+                        Template.ResultCombo(EnumSet.of(Template.Kind.INTERFACE),
+                                             EnumSet.of(MethodData.Access.PUBLIC),
+                                             EnumSet.allOf(MethodData.Context.class),
+                                             EnumSet.of(ClassData.Package.SAME,
+                                                        ClassData.Package.DIFFERENT)),
+                        Template.OverrideAbstractExpectedIface,
+                        Template.MethodrefAmbiguous,
+                        Template.IgnoredAbstract,
+                        Template.AllCallsiteCases,
+                        Template.MethodrefSelectionResolvedIsIfaceNoOverride),
+                /* Group 167: ambiguous selection */
+                new TestGroup.Simple(initBuilder,
+                        Template.SetInvoke(SelectionResolutionTestCase.InvokeInstruction.INVOKEVIRTUAL),
+                        Template.ResultCombo(EnumSet.of(Template.Kind.INTERFACE),
+                                             EnumSet.of(MethodData.Access.PUBLIC),
+                                             EnumSet.of(MethodData.Context.INSTANCE),
+                                             EnumSet.of(ClassData.Package.SAME,
+                                                        ClassData.Package.DIFFERENT)),
+                        Template.OverrideAbstractExpectedIface,
+                        Template.MethodrefNotEqualsExpectedIface,
+                        Template.IgnoredAbstract,
+                        Template.AllCallsiteCases,
+                        Template.MethodrefAmbiguousResolvedIsIface)
+                );
+
+    private InvokeVirtualICCE() {
+        super(testgroups);
+    }
+
+    public static void main(final String... args) {
+        new InvokeVirtualICCE().run();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/SelectionResolution/InvokeVirtualSuccessTest.java	Sat Apr 02 05:39:25 2016 +0200
@@ -0,0 +1,429 @@
+/*
+ * 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
+ * @summary Test of method selection and resolution cases that
+ * generate InvokeVirtualSuccessTest
+ * @modules java.base/jdk.internal.org.objectweb.asm
+ * @library /runtime/SelectionResolution/classes
+ * @build selectionresolution.*
+ * @run main/othervm/timeout=400 -XX:+IgnoreUnrecognizedVMOptions -XX:-VerifyDependencies InvokeVirtualSuccessTest
+ */
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.EnumSet;
+import selectionresolution.ClassData;
+import selectionresolution.MethodData;
+import selectionresolution.SelectionResolutionTest;
+import selectionresolution.SelectionResolutionTestCase;
+import selectionresolution.Template;
+
+public class InvokeVirtualSuccessTest extends SelectionResolutionTest {
+
+    private static final SelectionResolutionTestCase.Builder initBuilder =
+        new SelectionResolutionTestCase.Builder();
+
+    static {
+        initBuilder.invoke = SelectionResolutionTestCase.InvokeInstruction.INVOKEVIRTUAL;
+    }
+
+    private static final Collection<TestGroup> testgroups =
+        Arrays.asList(
+                /* invokevirtual tests */
+                /* Group 16: callsite = methodref = expected, no override */
+                new TestGroup.Simple(initBuilder,
+                        Template.ResultCombo(EnumSet.of(Template.Kind.CLASS),
+                                             EnumSet.of(MethodData.Access.PRIVATE),
+                                             EnumSet.of(MethodData.Context.INSTANCE),
+                                             EnumSet.of(ClassData.Package.SAME)),
+                        Template.OverrideAbstractExpectedClass,
+                        Template.MethodrefEqualsExpected,
+                        Template.IgnoredAbstract,
+                        Template.CallsiteEqualsMethodref,
+                        Template.MethodrefSelectionResolvedIsClassNoOverride),
+                /* Group 17: callsite = methodref = expected, override allowed */
+                new TestGroup.Simple(initBuilder,
+                        Template.ResultCombo(EnumSet.of(Template.Kind.CLASS),
+                                             EnumSet.of(MethodData.Access.PROTECTED,
+                                                        MethodData.Access.PUBLIC),
+                                             EnumSet.of(MethodData.Context.INSTANCE,
+                                                        MethodData.Context.ABSTRACT),
+                                             EnumSet.of(ClassData.Package.SAME)),
+                        Template.OverrideAbstractExpectedClass,
+                        Template.MethodrefEqualsExpected,
+                        Template.IgnoredAbstract,
+                        Template.CallsiteEqualsMethodref,
+                        Template.MethodrefSelectionResolvedIsClass,
+                        Template.SelectionOverrideAbstract),
+                /* Group 18: callsite = methodref = resolved, possibly
+                 * skip different package in selection.
+                 */
+                new TestGroup.Simple(initBuilder,
+                        Template.ResultCombo(EnumSet.of(Template.Kind.CLASS),
+                                             EnumSet.of(MethodData.Access.PACKAGE),
+                                             EnumSet.of(MethodData.Context.INSTANCE,
+                                                        MethodData.Context.ABSTRACT),
+                                             EnumSet.of(ClassData.Package.SAME)),
+                        Template.OverrideAbstractExpectedClass,
+                        Template.MethodrefEqualsExpected,
+                        Template.IgnoredAbstract,
+                        Template.CallsiteEqualsMethodref,
+                        Template.MethodrefSelectionPackageSkip,
+                        Template.SelectionOverrideAbstract),
+                /* Group 19: callsite = methodref, methodref != expected,
+                 * expected is class, expected and callsite in the same package
+                 */
+                new TestGroup.Simple(initBuilder,
+                        Template.ResultCombo(EnumSet.of(Template.Kind.CLASS),
+                                             EnumSet.of(MethodData.Access.PUBLIC,
+                                                        MethodData.Access.PROTECTED),
+                                             EnumSet.of(MethodData.Context.INSTANCE,
+                                                        MethodData.Context.ABSTRACT),
+                                             EnumSet.of(ClassData.Package.SAME)),
+                        Template.OverrideAbstractExpectedClass,
+                        Template.MethodrefNotEqualsExpectedClass,
+                        Template.IgnoredAbstract,
+                        Template.CallsiteEqualsMethodref,
+                        Template.MethodrefSelectionResolvedIsClass,
+                        Template.SelectionOverrideAbstract),
+                /* Group 20: callsite = methodref, methodref \!=
+                 * expected, possibly skip different package in
+                 * selection.
+                 */
+                new TestGroup.Simple(initBuilder,
+                        Template.ResultCombo(EnumSet.of(Template.Kind.CLASS),
+                                             EnumSet.of(MethodData.Access.PACKAGE),
+                                             EnumSet.of(MethodData.Context.INSTANCE,
+                                                        MethodData.Context.ABSTRACT),
+                                             EnumSet.of(ClassData.Package.SAME)),
+                        Template.OverrideAbstractExpectedClass,
+                        Template.MethodrefNotEqualsExpectedClass,
+                        Template.IgnoredAbstract,
+                        Template.CallsiteEqualsMethodref,
+                        Template.MethodrefSelectionPackageSkip,
+                        Template.SelectionOverrideAbstract),
+                /* Group 21: callsite = methodref, methodref != expected,
+                 * expected is interface, expected and callsite in the same package
+                 */
+                new TestGroup.Simple(initBuilder,
+                        Template.ResultCombo(EnumSet.of(Template.Kind.INTERFACE),
+                                             EnumSet.of(MethodData.Access.PUBLIC),
+                                             EnumSet.of(MethodData.Context.INSTANCE,
+                                                        MethodData.Context.ABSTRACT),
+                                             EnumSet.of(ClassData.Package.SAME)),
+                        Template.OverrideAbstractExpectedIface,
+                        Template.MethodrefNotEqualsExpectedIface,
+                        Template.IgnoredAbstract,
+                        Template.CallsiteEqualsMethodref,
+                        Template.MethodrefSelectionResolvedIsIface,
+                        Template.SelectionOverrideAbstract),
+                /* Group 22: callsite :> methodref, methodref = expected,
+                 * expected is class, expected and callsite in the same package
+                 */
+                new TestGroup.Simple(initBuilder,
+                        Template.ResultCombo(EnumSet.of(Template.Kind.CLASS),
+                                             EnumSet.of(MethodData.Access.PUBLIC,
+                                                        MethodData.Access.PROTECTED),
+                                             EnumSet.of(MethodData.Context.INSTANCE,
+                                                        MethodData.Context.ABSTRACT),
+                                             EnumSet.of(ClassData.Package.SAME)),
+                        Template.OverrideAbstractExpectedClass,
+                        Template.MethodrefEqualsExpected,
+                        Template.IgnoredAbstract,
+                        Template.CallsiteSubclassMethodref,
+                        Template.MethodrefSelectionResolvedIsClass,
+                        Template.SelectionOverrideAbstract),
+                /* Group 23: callsite :>, methodref = expected,
+                 * possibly skip different package in selection
+                 */
+                new TestGroup.Simple(initBuilder,
+                        Template.ResultCombo(EnumSet.of(Template.Kind.CLASS),
+                                             EnumSet.of(MethodData.Access.PACKAGE),
+                                             EnumSet.of(MethodData.Context.INSTANCE,
+                                                        MethodData.Context.ABSTRACT),
+                                             EnumSet.of(ClassData.Package.SAME)),
+                        Template.OverrideAbstractExpectedClass,
+                        Template.MethodrefEqualsExpected,
+                        Template.IgnoredAbstract,
+                        Template.CallsiteSubclassMethodref,
+                        Template.MethodrefSelectionPackageSkip,
+                        Template.SelectionOverrideAbstract),
+                /* Group 24: callsite :> methodref, methodref != expected,
+                 * expected is class, expected and callsite in the same package
+                 */
+                new TestGroup.Simple(initBuilder,
+                        Template.ResultCombo(EnumSet.of(Template.Kind.CLASS),
+                                             EnumSet.of(MethodData.Access.PUBLIC,
+                                                        MethodData.Access.PROTECTED),
+                                             EnumSet.of(MethodData.Context.INSTANCE,
+                                                        MethodData.Context.ABSTRACT),
+                                             EnumSet.of(ClassData.Package.SAME)),
+                        Template.OverrideAbstractExpectedClass,
+                        Template.MethodrefNotEqualsExpectedClass,
+                        Template.IgnoredAbstract,
+                        Template.CallsiteSubclassMethodref,
+                        Template.MethodrefSelectionResolvedIsClass,
+                        Template.SelectionOverrideAbstract),
+                /* Group 25: callsite :>, methodref = expected,
+                 * possibly skip different package in selection
+                 */
+                new TestGroup.Simple(initBuilder,
+                        Template.ResultCombo(EnumSet.of(Template.Kind.CLASS),
+                                             EnumSet.of(MethodData.Access.PACKAGE),
+                                             EnumSet.of(MethodData.Context.INSTANCE,
+                                                        MethodData.Context.ABSTRACT),
+                                             EnumSet.of(ClassData.Package.SAME)),
+                        Template.OverrideAbstractExpectedClass,
+                        Template.MethodrefNotEqualsExpectedClass,
+                        Template.IgnoredAbstract,
+                        Template.CallsiteSubclassMethodref,
+                        Template.MethodrefSelectionPackageSkip,
+                        Template.SelectionOverrideAbstract),
+                /* Group 26: callsite :> methodref, methodref != expected,
+                 * expected is interface, expected and callsite in the same package
+                 */
+                new TestGroup.Simple(initBuilder,
+                        Template.ResultCombo(EnumSet.of(Template.Kind.INTERFACE),
+                                             EnumSet.of(MethodData.Access.PUBLIC),
+                                             EnumSet.of(MethodData.Context.INSTANCE,
+                                                        MethodData.Context.ABSTRACT),
+                                             EnumSet.of(ClassData.Package.SAME)),
+                        Template.OverrideAbstractExpectedIface,
+                        Template.MethodrefNotEqualsExpectedIface,
+                        Template.IgnoredAbstract,
+                        Template.CallsiteSubclassMethodref,
+                        Template.MethodrefSelectionResolvedIsIface,
+                        Template.SelectionOverrideAbstract),
+                /* Group 27: callsite unrelated to methodref, methodref = expected,
+                 * expected is class, expected and callsite in the same package
+                 */
+                new TestGroup.Simple(initBuilder,
+                        Template.ResultCombo(EnumSet.of(Template.Kind.CLASS),
+                                             EnumSet.of(MethodData.Access.PUBLIC,
+                                                        MethodData.Access.PROTECTED),
+                                             EnumSet.of(MethodData.Context.INSTANCE,
+                                                        MethodData.Context.ABSTRACT),
+                                             EnumSet.of(ClassData.Package.SAME)),
+                        Template.OverrideAbstractExpectedClass,
+                        Template.MethodrefEqualsExpected,
+                        Template.IgnoredAbstract,
+                        Template.CallsiteUnrelatedToMethodref,
+                        Template.MethodrefSelectionResolvedIsClass,
+                        Template.SelectionOverrideAbstract),
+                /* Group 28: callsite unrelated to methodref,
+                 * methodref = expected, possibly skip different
+                 * package in selection
+                 */
+                new TestGroup.Simple(initBuilder,
+                        Template.ResultCombo(EnumSet.of(Template.Kind.CLASS),
+                                             EnumSet.of(MethodData.Access.PACKAGE),
+                                             EnumSet.of(MethodData.Context.INSTANCE,
+                                                        MethodData.Context.ABSTRACT),
+                                             EnumSet.of(ClassData.Package.SAME)),
+                        Template.OverrideAbstractExpectedClass,
+                        Template.MethodrefEqualsExpected,
+                        Template.IgnoredAbstract,
+                        Template.CallsiteUnrelatedToMethodref,
+                        Template.MethodrefSelectionPackageSkip,
+                        Template.SelectionOverrideAbstract),
+                /* Group 29: callsite unrelated to methodref, methodref != expected,
+                 * expected is class, expected and callsite in the same package
+                 */
+                new TestGroup.Simple(initBuilder,
+                        Template.ResultCombo(EnumSet.of(Template.Kind.CLASS),
+                                             EnumSet.of(MethodData.Access.PUBLIC,
+                                                        MethodData.Access.PROTECTED),
+                                             EnumSet.of(MethodData.Context.INSTANCE,
+                                                        MethodData.Context.ABSTRACT),
+                                             EnumSet.of(ClassData.Package.SAME)),
+                        Template.OverrideAbstractExpectedClass,
+                        Template.MethodrefNotEqualsExpectedClass,
+                        Template.IgnoredAbstract,
+                        Template.CallsiteUnrelatedToMethodref,
+                        Template.MethodrefSelectionResolvedIsClass,
+                        Template.SelectionOverrideAbstract),
+                /* Group 30: callsite unrelated to methodref,
+                 * methodref \!= expected, possibly skip different
+                 * package in selection
+                 */
+                new TestGroup.Simple(initBuilder,
+                        Template.ResultCombo(EnumSet.of(Template.Kind.CLASS),
+                                             EnumSet.of(MethodData.Access.PACKAGE),
+                                             EnumSet.of(MethodData.Context.INSTANCE,
+                                                        MethodData.Context.ABSTRACT),
+                                             EnumSet.of(ClassData.Package.SAME)),
+                        Template.OverrideAbstractExpectedClass,
+                        Template.MethodrefNotEqualsExpectedClass,
+                        Template.IgnoredAbstract,
+                        Template.CallsiteUnrelatedToMethodref,
+                        Template.MethodrefSelectionPackageSkip,
+                        Template.SelectionOverrideAbstract),
+                /* Group 31: callsite unrelated to methodref, methodref != expected,
+                 * expected is interface, expected and callsite in the same package
+                 */
+                new TestGroup.Simple(initBuilder,
+                        Template.ResultCombo(EnumSet.of(Template.Kind.INTERFACE),
+                                             EnumSet.of(MethodData.Access.PUBLIC),
+                                             EnumSet.of(MethodData.Context.INSTANCE,
+                                                        MethodData.Context.ABSTRACT),
+                                             EnumSet.of(ClassData.Package.SAME)),
+                        Template.OverrideAbstractExpectedIface,
+                        Template.MethodrefNotEqualsExpectedIface,
+                        Template.IgnoredAbstract,
+                        Template.CallsiteUnrelatedToMethodref,
+                        Template.MethodrefSelectionResolvedIsIface,
+                        Template.SelectionOverrideAbstract),
+                /* Group 32: callsite = methodref, methodref != expected,
+                 * expected is class, expected and callsite not in the same package
+                 */
+                new TestGroup.Simple(initBuilder,
+                        Template.ResultCombo(EnumSet.of(Template.Kind.CLASS),
+                                             EnumSet.of(MethodData.Access.PUBLIC,
+                                                        MethodData.Access.PROTECTED),
+                                             EnumSet.of(MethodData.Context.INSTANCE,
+                                                        MethodData.Context.ABSTRACT),
+                                             EnumSet.of(ClassData.Package.DIFFERENT)),
+                        Template.OverrideAbstractExpectedClass,
+                        Template.MethodrefNotEqualsExpectedClass,
+                        Template.IgnoredAbstract,
+                        Template.CallsiteEqualsMethodref,
+                        Template.MethodrefSelectionResolvedIsClass,
+                        Template.SelectionOverrideAbstract),
+                /* Group 33: callsite = methodref, methodref != expected,
+                 * expected is interface, expected and callsite not in the same package
+                 */
+                new TestGroup.Simple(initBuilder,
+                        Template.ResultCombo(EnumSet.of(Template.Kind.INTERFACE),
+                                             EnumSet.of(MethodData.Access.PUBLIC),
+                                             EnumSet.of(MethodData.Context.INSTANCE,
+                                                        MethodData.Context.ABSTRACT),
+                                             EnumSet.of(ClassData.Package.DIFFERENT)),
+                        Template.OverrideAbstractExpectedIface,
+                        Template.MethodrefNotEqualsExpectedIface,
+                        Template.IgnoredAbstract,
+                        Template.CallsiteEqualsMethodref,
+                        Template.MethodrefSelectionResolvedIsIface,
+                        Template.SelectionOverrideAbstract),
+                /* Group 34: callsite :> methodref, methodref = expected,
+                 * expected is class, expected and callsite not in the same package
+                 */
+                new TestGroup.Simple(initBuilder,
+                        Template.ResultCombo(EnumSet.of(Template.Kind.CLASS),
+                                             EnumSet.of(MethodData.Access.PUBLIC),
+                                             EnumSet.of(MethodData.Context.INSTANCE,
+                                                        MethodData.Context.ABSTRACT),
+                                             EnumSet.of(ClassData.Package.DIFFERENT)),
+                        Template.OverrideAbstractExpectedClass,
+                        Template.MethodrefEqualsExpected,
+                        Template.IgnoredAbstract,
+                        Template.CallsiteSubclassMethodref,
+                        Template.MethodrefSelectionResolvedIsClass,
+                        Template.SelectionOverrideAbstract),
+
+                /* Group 35: callsite :> methodref, methodref != expected,
+                 * expected is class, expected and callsite not in the same package
+                 */
+                new TestGroup.Simple(initBuilder,
+                        Template.ResultCombo(EnumSet.of(Template.Kind.CLASS),
+                                             EnumSet.of(MethodData.Access.PUBLIC),
+                                             EnumSet.of(MethodData.Context.INSTANCE,
+                                                        MethodData.Context.ABSTRACT),
+                                             EnumSet.of(ClassData.Package.DIFFERENT)),
+                        Template.OverrideAbstractExpectedClass,
+                        Template.MethodrefNotEqualsExpectedClass,
+                        Template.IgnoredAbstract,
+                        Template.CallsiteSubclassMethodref,
+                        Template.MethodrefSelectionResolvedIsClass,
+                        Template.SelectionOverrideAbstract),
+                /* Group 36: callsite :> methodref, methodref != expected,
+                 * expected is interface, expected and callsite not in the same package
+                 */
+                new TestGroup.Simple(initBuilder,
+                        Template.ResultCombo(EnumSet.of(Template.Kind.INTERFACE),
+                                             EnumSet.of(MethodData.Access.PUBLIC),
+                                             EnumSet.of(MethodData.Context.INSTANCE,
+                                                        MethodData.Context.ABSTRACT),
+                                             EnumSet.of(ClassData.Package.DIFFERENT)),
+                        Template.OverrideAbstractExpectedIface,
+                        Template.MethodrefNotEqualsExpectedIface,
+                        Template.IgnoredAbstract,
+                        Template.CallsiteSubclassMethodref,
+                        Template.MethodrefSelectionResolvedIsIface,
+                        Template.SelectionOverrideAbstract),
+                /* Group 37: callsite unrelated to methodref, methodref = expected,
+                 * expected is class, expected and callsite not in the same package
+                 */
+                new TestGroup.Simple(initBuilder,
+                        Template.ResultCombo(EnumSet.of(Template.Kind.CLASS),
+                                             EnumSet.of(MethodData.Access.PUBLIC),
+                                             EnumSet.of(MethodData.Context.INSTANCE,
+                                                        MethodData.Context.ABSTRACT),
+                                             EnumSet.of(ClassData.Package.DIFFERENT)),
+                        Template.OverrideAbstractExpectedClass,
+                        Template.MethodrefEqualsExpected,
+                        Template.IgnoredAbstract,
+                        Template.CallsiteUnrelatedToMethodref,
+                        Template.MethodrefSelectionResolvedIsClass,
+                        Template.SelectionOverrideAbstract),
+                /* Group 38: callsite unrelated to methodref, methodref != expected,
+                 * expected is class, expected and callsite not in the same package
+                 */
+                new TestGroup.Simple(initBuilder,
+                        Template.ResultCombo(EnumSet.of(Template.Kind.CLASS),
+                                             EnumSet.of(MethodData.Access.PUBLIC),
+                                             EnumSet.of(MethodData.Context.INSTANCE,
+                                                        MethodData.Context.ABSTRACT),
+                                             EnumSet.of(ClassData.Package.DIFFERENT)),
+                        Template.OverrideAbstractExpectedClass,
+                        Template.MethodrefNotEqualsExpectedClass,
+                        Template.IgnoredAbstract,
+                        Template.CallsiteUnrelatedToMethodref,
+                        Template.MethodrefSelectionResolvedIsClass,
+                        Template.SelectionOverrideAbstract),
+                /* Group 39: callsite unrelated to methodref, methodref != expected,
+                 * expected is interface, expected and callsite not in the same package
+                 */
+                new TestGroup.Simple(initBuilder,
+                        Template.ResultCombo(EnumSet.of(Template.Kind.INTERFACE),
+                                             EnumSet.of(MethodData.Access.PUBLIC),
+                                             EnumSet.of(MethodData.Context.INSTANCE,
+                                                        MethodData.Context.ABSTRACT),
+                                             EnumSet.of(ClassData.Package.DIFFERENT)),
+                        Template.OverrideAbstractExpectedIface,
+                        Template.MethodrefNotEqualsExpectedIface,
+                        Template.IgnoredAbstract,
+                        Template.CallsiteUnrelatedToMethodref,
+                        Template.MethodrefSelectionResolvedIsIface,
+                        Template.SelectionOverrideAbstract)
+            );
+
+    private InvokeVirtualSuccessTest() {
+        super(testgroups);
+    }
+
+    public static void main(final String... args) {
+        new InvokeVirtualSuccessTest().run();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/SelectionResolution/NoSuchMethodErrorTest.java	Sat Apr 02 05:39:25 2016 +0200
@@ -0,0 +1,450 @@
+/*
+ * 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
+ * @summary Test of method selection and resolution cases that
+ * generate NoSuchMethodError
+ * @modules java.base/jdk.internal.org.objectweb.asm
+ * @library /runtime/SelectionResolution/classes
+ * @build selectionresolution.*
+ * @run main NoSuchMethodErrorTest
+ */
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.EnumSet;
+import selectionresolution.ClassData;
+import selectionresolution.MethodData;
+import selectionresolution.Result;
+import selectionresolution.SelectionResolutionTest;
+import selectionresolution.SelectionResolutionTestCase;
+import selectionresolution.Template;
+
+public class NoSuchMethodErrorTest extends SelectionResolutionTest {
+
+    private static final SelectionResolutionTestCase.Builder initBuilder =
+        new SelectionResolutionTestCase.Builder();
+
+    static {
+        initBuilder.setResult(Result.NSME);
+    }
+
+    private static final MethodData concreteMethod =
+        new MethodData(MethodData.Access.PUBLIC, MethodData.Context.INSTANCE);
+
+    private static final MethodData staticMethod =
+        new MethodData(MethodData.Access.PUBLIC, MethodData.Context.STATIC);
+
+    private static final MethodData privateMethod =
+        new MethodData(MethodData.Access.PRIVATE, MethodData.Context.INSTANCE);
+
+    private static final ClassData withDef =
+        new ClassData(ClassData.Package.SAME, concreteMethod);
+
+    private static final ClassData withStaticDef =
+        new ClassData(ClassData.Package.SAME, staticMethod);
+
+    private static final ClassData withPrivateDef =
+        new ClassData(ClassData.Package.SAME, staticMethod);
+
+    private static final Template NoMethodResolutionTemplateClassBottom =
+        new Template("NoMethodResolutionTemplate",
+                    /* Empty single class
+                     *
+                     * C[]() = mref
+                     */
+                    (final SelectionResolutionTestCase.Builder builder) -> {
+                        final int C = builder.addClass(Template.emptyClass(ClassData.Package.SAME));
+                        builder.methodref = C;
+                    },
+                    /* Class bottom, inherit empty class
+                     *
+                     * C2[]()
+                     * C1[C2]() = mref
+                     */
+                    (final SelectionResolutionTestCase.Builder builder) -> {
+                        final int C1 = builder.addClass(Template.emptyClass(ClassData.Package.SAME));
+                        final int C2 = builder.addClass(Template.emptyClass(ClassData.Package.SAME));
+                        builder.hier.addInherit(C1, C2);
+                        builder.methodref = C1;
+                    },
+                    /* Class bottom, inherit empty interface
+                     *
+                     * I[]()
+                     * C[I]() = mref
+                     */
+                    (final SelectionResolutionTestCase.Builder builder) -> {
+                        final int C = builder.addClass(Template.emptyClass(ClassData.Package.SAME));
+                        final int I = builder.addInterface(Template.emptyClass(ClassData.Package.SAME));
+                        builder.hier.addInherit(C, I);
+                        builder.methodref = C;
+                    },
+                    /* Class bottom, inherit empty class and interface
+                     *
+                     * C2[](), I[]()
+                     * C1[C2,I]() = mref
+                     */
+                    (final SelectionResolutionTestCase.Builder builder) -> {
+                        final int C1 = builder.addClass(Template.emptyClass(ClassData.Package.SAME));
+                        final int C2 = builder.addClass(Template.emptyClass(ClassData.Package.SAME));
+                        final int I = builder.addInterface(Template.emptyClass(ClassData.Package.SAME));
+                        builder.hier.addInherit(C1, C2);
+                        builder.hier.addInherit(C1, I);
+                        builder.methodref = C1;
+                    },
+                    /* Class bottom, unrelated class defines
+                     *
+                     * C20[](con)
+                     * C1[]()
+                     */
+                    (final SelectionResolutionTestCase.Builder builder) -> {
+                        final int C = builder.addClass(Template.emptyClass(ClassData.Package.SAME));
+                        builder.addClass(withDef);
+                        builder.methodref = C;
+                    },
+                    /* Class bottom, interface defines static
+                     *
+                     * I[](stat)
+                     * C[]()
+                     */
+                    (final SelectionResolutionTestCase.Builder builder) -> {
+                        final int C = builder.addClass(Template.emptyClass(ClassData.Package.SAME));
+                        final int I = builder.addInterface(withStaticDef);
+                        builder.hier.addInherit(C, I);
+                        builder.methodref = C;
+                    },
+                    /* Class bottom, interface defines private
+                     *
+                     * I[](priv)
+                     * C[]()
+                     */
+                    (final SelectionResolutionTestCase.Builder builder) -> {
+                        final int C = builder.addClass(Template.emptyClass(ClassData.Package.SAME));
+                        final int I = builder.addInterface(withPrivateDef);
+                        builder.hier.addInherit(C, I);
+                        builder.methodref = C;
+                    });
+
+    private static final Template NoMethodResolutionTemplateIfaceBottom =
+        new Template("NoMethodResolutionTemplate",
+                    /* Empty single interface
+                     *
+                     * I[]() = mref
+                     */
+                    (final SelectionResolutionTestCase.Builder builder) -> {
+                        final int I = builder.addInterface(Template.emptyClass(ClassData.Package.SAME));
+                        builder.methodref = I;
+                    },
+                    /* Interface bottom, inherit empty interface
+                     *
+                     * I2[]()
+                     * I1[I2]() = mref
+                     */
+                    (final SelectionResolutionTestCase.Builder builder) -> {
+                        final int I1 = builder.addInterface(Template.emptyClass(ClassData.Package.SAME));
+                        final int I2 = builder.addInterface(Template.emptyClass(ClassData.Package.SAME));
+                        builder.hier.addInherit(I1, I2);
+                        builder.methodref = I1;
+                    },
+                    /* Interface bottom, unrelated class defines
+                     *
+                     * C0[](con)
+                     * I[]() = mref
+                     */
+                    (final SelectionResolutionTestCase.Builder builder) -> {
+                        final int I = builder.addInterface(Template.emptyClass(ClassData.Package.SAME));
+                        builder.addClass(withDef);
+                        builder.methodref = I;
+                    },
+                    /* Interface bottom, interface defines static
+                     *
+                     * I2[](stat)
+                     * I1[I2]() = mref
+                     */
+                    (final SelectionResolutionTestCase.Builder builder) -> {
+                        final int I1 = builder.addInterface(Template.emptyClass(ClassData.Package.SAME));
+                        final int I2 = builder.addInterface(withStaticDef);
+                        builder.hier.addInherit(I1, I2);
+                        builder.methodref = I1;
+                    },
+                    /* Interface bottom, interface defines private
+                     *
+                     * I2[](stat)
+                     * I1[I2]() = mref
+                     */
+                    (final SelectionResolutionTestCase.Builder builder) -> {
+                        final int I1 = builder.addInterface(Template.emptyClass(ClassData.Package.SAME));
+                        final int I2 = builder.addInterface(withPrivateDef);
+                        builder.hier.addInherit(I1, I2);
+                        builder.methodref = I1;
+                    });
+
+    private static final Template NoMethodSelectionTemplateClassMethodref =
+        new Template("NoMethodSelectionTemplate",
+                    /* objectref = methodref
+                     *
+                     * C[]() = mref = oref
+                     */
+                    (final SelectionResolutionTestCase.Builder builder) -> {
+                        builder.objectref = builder.methodref;
+                    },
+                    /* Inherit methodref
+                     *
+                     * C2[]() = mref
+                     * C1[C2]() = oref
+                     */
+                    (final SelectionResolutionTestCase.Builder builder) -> {
+                        final int C1 = builder.addClass(Template.emptyClass(ClassData.Package.SAME));
+                        final int C2 = builder.methodref;
+                        builder.hier.addInherit(C1, C2);
+                        builder.objectref = C1;
+                    },
+                    /* Inherit methodref and interface
+                     *
+                     * C2[]() = mref, I[]()
+                     * C1[C2,I]() = oref
+                     */
+                    (final SelectionResolutionTestCase.Builder builder) -> {
+                        final int C2 = builder.methodref;
+                        final int C1 = builder.addClass(Template.emptyClass(ClassData.Package.SAME));
+                        final int I = builder.addInterface(Template.emptyClass(ClassData.Package.SAME));
+                        builder.hier.addInherit(C1, C2);
+                        builder.hier.addInherit(C1, I);
+                        builder.objectref = C1;
+                    },
+                    /* objectref = methodref, unrelated class defines
+                     *
+                     * C0[](def)
+                     * C[]() = mref = oref
+                     */
+                    (final SelectionResolutionTestCase.Builder builder) -> {
+                        builder.addClass(withDef);
+                        builder.objectref = builder.methodref;
+                    },
+                    /* Inherit methodref, unrelated class defines
+                     *
+                     * C0[](def)
+                     * C2[]() = mref
+                     * C1[C2]() = oref
+                     */
+                    (final SelectionResolutionTestCase.Builder builder) -> {
+                        final int C1 = builder.addClass(Template.emptyClass(ClassData.Package.SAME));
+                        final int C2 = builder.methodref;
+                        builder.addClass(withDef);
+                        builder.hier.addInherit(C1, C2);
+                        builder.objectref = C1;
+                    },
+                    /* Inherit methodref and interface, unrelated class defines.
+                     *
+                     * C0[](def)
+                     * C2[]() = mref, I[]()
+                     * C1[C2,I]() = oref
+                     */
+                    (final SelectionResolutionTestCase.Builder builder) -> {
+                        final int C2 = builder.methodref;
+                        final int C1 = builder.addClass(Template.emptyClass(ClassData.Package.SAME));
+                        final int I = builder.addInterface(Template.emptyClass(ClassData.Package.SAME));
+                        builder.addClass(withDef);
+                        builder.hier.addInherit(C1, C2);
+                        builder.hier.addInherit(C1, I);
+                        builder.objectref = C1;
+                    },
+                    /* objectref = methodref, unrelated interface defines
+                     *
+                     * I0[](def)
+                     * C[]() = mref = oref
+                     */
+                    (final SelectionResolutionTestCase.Builder builder) -> {
+                        builder.addInterface(withDef);
+                        builder.objectref = builder.methodref;
+                    },
+                    /* Inherit methodref, interface defines static
+                     *
+                     * C2[]() = mref, I0[](stat)
+                     * C1[C2]() = oref
+                     */
+                    (final SelectionResolutionTestCase.Builder builder) -> {
+                        final int C1 = builder.addClass(Template.emptyClass(ClassData.Package.SAME));
+                        final int C2 = builder.methodref;
+                        final int I0 = builder.addInterface(withStaticDef);
+                        builder.hier.addInherit(C1, C2);
+                        builder.hier.addInherit(C1, I0);
+                        builder.objectref = C1;
+                    },
+                    /* Inherit methodref, interface defines private
+                     *
+                     * C2[]() = mref, I0[](stat)
+                     * C1[C2]() = oref
+                     */
+                    (final SelectionResolutionTestCase.Builder builder) -> {
+                        final int C1 = builder.addClass(Template.emptyClass(ClassData.Package.SAME));
+                        final int C2 = builder.methodref;
+                        final int I0 = builder.addInterface(withPrivateDef);
+                        builder.hier.addInherit(C1, C2);
+                        builder.hier.addInherit(C1, I0);
+                        builder.objectref = C1;
+                    });
+
+    private static final Template NoMethodSelectionTemplateIfaceMethodref =
+        new Template("NoMethodSelectionTemplate",
+                    /* Inherit methodref
+                     *
+                     * I[]() = mref
+                     * C[I]() = oref
+                     */
+                    (final SelectionResolutionTestCase.Builder builder) -> {
+                        final int C = builder.addClass(Template.emptyClass(ClassData.Package.SAME));
+                        final int I = builder.methodref;
+                        builder.hier.addInherit(C, I);
+                        builder.objectref = C;
+                    },
+                    /* Inherit methodref and interface
+                     *
+                     * I1[]() = mref, I2[]()
+                     * C[T,I]() = oref
+                     */
+                    (final SelectionResolutionTestCase.Builder builder) -> {
+                        final int I1 = builder.methodref;
+                        final int C = builder.addClass(Template.emptyClass(ClassData.Package.SAME));
+                        final int I2 = builder.addInterface(Template.emptyClass(ClassData.Package.SAME));
+                        builder.hier.addInherit(C, I1);
+                        builder.hier.addInherit(C, I2);
+                        builder.objectref = C;
+                    },
+                    /* Inherit methodref, unrelated class defines
+                     *
+                     * C0[](def)
+                     * I[]() = mref
+                     * C[I]() = oref
+                     */
+                    (final SelectionResolutionTestCase.Builder builder) -> {
+                        final int C = builder.addClass(Template.emptyClass(ClassData.Package.SAME));
+                        final int I = builder.methodref;
+                        builder.addClass(withDef);
+                        builder.hier.addInherit(C, I);
+                        builder.objectref = C;
+                    },
+                    /* Inherit methodref and interface, unrelated class defines
+                     *
+                     * C0[](def)
+                     * I1[]() = mref, I2[]()
+                     * C[I1,I2]() = oref
+                     */
+                    (final SelectionResolutionTestCase.Builder builder) -> {
+                        final int I1 = builder.methodref;
+                        final int C = builder.addClass(Template.emptyClass(ClassData.Package.SAME));
+                        final int I2 = builder.addInterface(Template.emptyClass(ClassData.Package.SAME));
+                        builder.addClass(withDef);
+                        builder.hier.addInherit(C, I1);
+                        builder.hier.addInherit(C, I2);
+                        builder.objectref = C;
+                    },
+                    /* Inherit methodref, interface defines static
+                     *
+                     * I[]() = mref, I0[](stat)
+                     * C[I,I0]() = oref
+                     */
+                    (final SelectionResolutionTestCase.Builder builder) -> {
+                        final int C = builder.addClass(Template.emptyClass(ClassData.Package.SAME));
+                        final int I = builder.methodref;
+                        final int I0 = builder.addInterface(withStaticDef);
+                        builder.hier.addInherit(C, I);
+                        builder.hier.addInherit(C, I0);
+                        builder.objectref = C;
+                    },
+                    /* Inherit methodref, unrelated class defines private
+                     *
+                     * I[]() = mref, I0[](priv)
+                     * C[I,I0]() = oref
+                     */
+                    (final SelectionResolutionTestCase.Builder builder) -> {
+                        final int C = builder.addClass(Template.emptyClass(ClassData.Package.SAME));
+                        final int I = builder.methodref;
+                        final int I0 = builder.addInterface(withPrivateDef);
+                        builder.hier.addInherit(C, I);
+                        builder.hier.addInherit(C, I0);
+                        builder.objectref = C;
+                    });
+
+    private static final Collection<TestGroup> testgroups =
+        Arrays.asList(
+                /* invokestatic tests */
+                new TestGroup.Simple(initBuilder,
+                        Template.SetInvoke(SelectionResolutionTestCase.InvokeInstruction.INVOKESTATIC),
+                        NoMethodResolutionTemplateClassBottom,
+                        Template.AllCallsiteCases,
+                        Template.TrivialObjectref),
+                new TestGroup.Simple(initBuilder,
+                        Template.SetInvoke(SelectionResolutionTestCase.InvokeInstruction.INVOKESTATIC),
+                        NoMethodResolutionTemplateIfaceBottom,
+                        Template.CallsiteNotEqualsMethodref,
+                        Template.TrivialObjectref),
+                /* invokevirtual tests */
+                new TestGroup.Simple(initBuilder,
+                        Template.SetInvoke(SelectionResolutionTestCase.InvokeInstruction.INVOKEVIRTUAL),
+                        NoMethodResolutionTemplateClassBottom,
+                        Template.AllCallsiteCases,
+                        NoMethodSelectionTemplateClassMethodref),
+                /* invokeinterface tests */
+                new TestGroup.Simple(initBuilder,
+                        Template.SetInvoke(SelectionResolutionTestCase.InvokeInstruction.INVOKEINTERFACE),
+                        NoMethodResolutionTemplateIfaceBottom,
+                        Template.CallsiteNotEqualsMethodref,
+                        NoMethodSelectionTemplateIfaceMethodref),
+
+                /* Hiding of private interface methods */
+                /* invokevirtual */
+                new TestGroup.Simple(initBuilder,
+                        Template.SetInvoke(SelectionResolutionTestCase.InvokeInstruction.INVOKEVIRTUAL),
+                        Template.ResultCombo(EnumSet.of(Template.Kind.INTERFACE),
+                                             EnumSet.of(MethodData.Access.PRIVATE),
+                                             EnumSet.of(MethodData.Context.INSTANCE,
+                                                        MethodData.Context.ABSTRACT),
+                                             EnumSet.of(ClassData.Package.SAME,
+                                                        ClassData.Package.DIFFERENT)),
+                        Template.MethodrefNotEqualsExpectedIface,
+                        Template.AllCallsiteCases,
+                        Template.TrivialObjectref),
+                /* invokeinterface */
+                new TestGroup.Simple(initBuilder,
+                        Template.SetInvoke(SelectionResolutionTestCase.InvokeInstruction.INVOKEINTERFACE),
+                        Template.ResultCombo(EnumSet.of(Template.Kind.INTERFACE),
+                                             EnumSet.of(MethodData.Access.PRIVATE),
+                                             EnumSet.of(MethodData.Context.INSTANCE,
+                                                        MethodData.Context.ABSTRACT),
+                                             EnumSet.of(ClassData.Package.SAME,
+                                                        ClassData.Package.DIFFERENT)),
+                        Template.IfaceMethodrefNotEqualsExpected,
+                        Template.AllCallsiteCases,
+                        Template.TrivialObjectrefNotEqualMethodref)
+            );
+
+    private NoSuchMethodErrorTest() {
+        super(testgroups);
+    }
+
+    public static void main(final String... args) {
+        new NoSuchMethodErrorTest().run();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/SelectionResolution/classes/selectionresolution/Builder.java	Sat Apr 02 05:39:25 2016 +0200
@@ -0,0 +1,67 @@
+/*
+ * 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.
+ *
+ */
+
+package selectionresolution;
+
+import java.util.HashMap;
+
+abstract class Builder {
+    protected final SelectionResolutionTestCase testcase;
+    protected final HierarchyShape hier;
+    protected final HashMap<Integer,ClassData> classdata;
+
+    public Builder(SelectionResolutionTestCase testcase) {
+        this.testcase = testcase;
+        this.hier = testcase.hier;
+        this.classdata = testcase.classdata;
+    }
+
+    protected String getName(int id) {
+        StringBuilder name = new StringBuilder();
+
+        name.append(getPackageName(classdata.get(id).packageId.ordinal()));
+
+        // Name classes C<id> and interfaces I<id>
+        name.append(getClassName(id));
+
+        return name.toString();
+    }
+
+    protected String getPackageName(int packageId) {
+        return "P" + packageId + "/";
+    }
+
+    protected String getClassName(int id) {
+        // Name classes C<id> and interfaces I<id>
+        if (isClass(id)) {
+            return "C" + id;
+        } else {
+            return "I" + id;
+        }
+    }
+
+    protected boolean isClass(int id) {
+        return hier.isClass(id);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/SelectionResolution/classes/selectionresolution/ByteCodeClassLoader.java	Sat Apr 02 05:39:25 2016 +0200
@@ -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.
+ *
+ */
+
+package selectionresolution;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+
+
+public class ByteCodeClassLoader extends ClassLoader {
+    ArrayList<ClassConstruct> classes = new ArrayList<>();
+    HashMap<String, Class> loadedClasses = new HashMap<>();
+
+    public void addClasses(ClassConstruct... classes) {
+        this.classes.addAll(Arrays.asList(classes));
+    }
+
+    public void loadAll() throws ClassNotFoundException {
+        for (ClassConstruct clazz : classes) {
+            findClass(clazz.getDottedName());
+        }
+    }
+
+
+    @Override
+    public Class findClass(String name) throws ClassNotFoundException {
+
+        Class cls = loadedClasses.get(name);
+
+        if (cls != null) {
+            return cls;
+        }
+
+        for (ClassConstruct clazz : classes) {
+            if (clazz.getDottedName().equals(name)) {
+                return load(clazz);
+            }
+        }
+
+        throw new ClassNotFoundException(name);
+    }
+
+    @Override
+    public Class loadClass(String name) throws ClassNotFoundException {
+        try {
+            return findClass(name);
+        } catch (ClassNotFoundException e) {
+            return super.loadClass(name);
+        }
+    }
+
+    private Class load(ClassConstruct clazz) {
+        byte[] bytecode = clazz.generateBytes();
+        Class loadedClass = defineClass(clazz.getDottedName(), bytecode, 0, bytecode.length);
+        loadedClasses.put(clazz.getDottedName(), loadedClass);
+        return loadedClass;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/SelectionResolution/classes/selectionresolution/ClassBuilder.java	Sat Apr 02 05:39:25 2016 +0200
@@ -0,0 +1,241 @@
+/*
+ * 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.
+ *
+ */
+
+package selectionresolution;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+
+import static jdk.internal.org.objectweb.asm.Opcodes.ACC_ABSTRACT;
+import static jdk.internal.org.objectweb.asm.Opcodes.ACC_PUBLIC;
+import static jdk.internal.org.objectweb.asm.Opcodes.ACC_PRIVATE;
+import static jdk.internal.org.objectweb.asm.Opcodes.ACC_PROTECTED;
+import static jdk.internal.org.objectweb.asm.Opcodes.ACC_STATIC;
+
+/**
+ * Constructs classes and interfaces based on the information from a
+ * DefaultMethodTestCase
+ *
+ */
+public class ClassBuilder extends Builder {
+    private final ArrayList<ClassConstruct> classes;
+
+    // Add a class in every package to be able to instantiate package
+    // private classes from outside the package
+    private final Clazz[] helpers = new Clazz[4];
+    private ClassConstruct callsiteClass;
+
+    public enum ExecutionMode { DIRECT, INDY, MH_INVOKE_EXACT, MH_INVOKE_GENERIC}
+    private final ExecutionMode execMode;
+
+    public ClassBuilder(SelectionResolutionTestCase testcase,
+                        ExecutionMode execMode) {
+        super(testcase);
+        this.classes = new ArrayList<>();
+        this.execMode = execMode;
+    }
+
+    public ClassConstruct[] build() throws Exception {
+        buildClassConstructs();
+        return classes.toArray(new ClassConstruct[0]);
+    }
+
+    public ClassConstruct getCallsiteClass() {
+        return callsiteClass;
+    }
+
+    private void buildClassConstructs() throws Exception {
+        TestBuilder tb = new TestBuilder(testcase.methodref, testcase);
+
+        classes.add(new Clazz("Test", ACC_PUBLIC, -1));
+
+        for (int classId = 0; classId < classdata.size(); classId++) {
+            ClassConstruct C;
+            String[] interfaces = getInterfaces(classId);
+            ClassData data = classdata.get(classId);
+
+            if (isClass(classId)) {
+                C = new Clazz(getName(classId),
+                              getExtending(classId),
+                              getClassModifiers(data),
+                              classId,
+                              interfaces);
+
+                addHelperMethod(classId);
+
+            } else {
+                C = new Interface(getName(classId),
+                                  getAccessibility(data.access),
+                                  classId, interfaces);
+            }
+
+            // Add a method "m()LTestObject;" if applicable
+            if (containsMethod(data)) {
+                // Method will either be abstract or concrete depending on the
+                // abstract modifier
+                C.addTestMethod(getMethodModifiers(data));
+            }
+
+            if (classId == testcase.callsite) {
+                // Add test() method
+                tb.addTest(C, execMode);
+                callsiteClass = C;
+            }
+
+            classes.add(C);
+        }
+        classes.add(tb.getMainTestClass());
+
+    }
+
+    private void addHelperMethod(int classId) {
+        int packageId = classdata.get(classId).packageId.ordinal();
+        Clazz C = helpers[packageId];
+        if (C == null) {
+            C = new Clazz(getPackageName(packageId) + "Helper", -1, ACC_PUBLIC);
+            helpers[packageId] = C;
+            classes.add(C);
+        }
+
+        Method m = C.addMethod("get" + getClassName(classId),
+                               "()L" + getName(classId) + ";",
+                               ACC_PUBLIC + ACC_STATIC);
+        m.makeInstantiateMethod(getName(classId));
+    }
+
+    private String[] getInterfaces(int classId) {
+        ArrayList<String> interfaces = new ArrayList<>();
+
+        // Figure out if we're extending/implementing an interface
+        for (final int intf : hier.interfaces()) {
+            if (hier.inherits(classId, intf)) {
+                interfaces.add(getName(intf));
+            }
+        }
+        return interfaces.toArray(new String[0]);
+    }
+
+    private String getExtending(int classId) {
+        int extending = -1;
+
+        // See if we're extending another class
+        for (final int extendsClass : hier.classes()) {
+            if (hier.inherits(classId, extendsClass)) {
+                // Sanity check that we haven't already found an extending class
+                if (extending != -1) {
+                    throw new RuntimeException("Multiple extending classes");
+                }
+                extending = extendsClass;
+            }
+        }
+
+        return extending == -1 ? null : getName(extending);
+    }
+
+    /**
+     * Returns modifiers for a Class
+     * @param cd ClassData for the Class
+     * @return ASM modifiers for a Class
+     */
+    private int getClassModifiers(ClassData cd) {
+        // For Classes we only care about accessibility (public, private etc)
+        return getAccessibility(cd.access) | getAbstraction(cd.abstraction);
+    }
+
+    /**
+     * Returns modifiers for Method type
+     * @param cd ClassData for the Class or Interface where the Method resides
+     * @return ASM modifiers for the Method
+     */
+    private int getMethodModifiers(ClassData cd) {
+        int mod = 0;
+
+        // For methods we want everything
+        mod += getAccessibility(cd.methoddata.access);
+        mod += getAbstraction(cd.methoddata.context);
+        mod += getContext(cd.methoddata.context);
+        mod += getExtensibility();
+        return mod;
+    }
+
+
+    /**
+     * Convert ClassData access type to ASM
+     * @param access
+     * @return ASM version of accessibility (public / private / protected)
+     */
+    private int getAccessibility(MethodData.Access access) {
+        switch(access) {
+        case PACKAGE:
+            //TODO: Do I need to set this or will this be the default?
+            return 0;
+        case PRIVATE:
+            return ACC_PRIVATE;
+        case PROTECTED:
+            return ACC_PROTECTED;
+        case PUBLIC:
+            return ACC_PUBLIC;
+        default:
+            throw new RuntimeException("Illegal accessibility modifier: " + access);
+        }
+    }
+
+    /**
+     * Convert ClassData abstraction type to ASM
+     * @param abstraction
+     * @return ASM version of abstraction (abstract / non-abstract)
+     */
+    private int getAbstraction(MethodData.Context context) {
+        return context == MethodData.Context.ABSTRACT ? ACC_ABSTRACT : 0;
+    }
+
+    /**
+     * Convert ClassData context type to ASM
+     * @param context
+     * @return ASM version of context (static / non-static)
+     */
+    private int getContext(MethodData.Context context) {
+        return context == MethodData.Context.STATIC ? ACC_STATIC : 0;
+    }
+
+    /**
+     * Convert ClassData extensibility type to ASM
+     * @param extensibility
+     * @return ASM version of extensibility (final / non-final)
+     */
+    private int getExtensibility() {
+        return 0;
+    }
+
+    /**
+     * Determine if we need a method at all, abstraction is set to null if this
+     * Class/Interface should not have a test method
+     * @param cd
+     * @return
+     */
+    private boolean containsMethod(ClassData cd) {
+        return cd.methoddata != null;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/SelectionResolution/classes/selectionresolution/ClassConstruct.java	Sat Apr 02 05:39:25 2016 +0200
@@ -0,0 +1,168 @@
+/*
+ * 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.
+ *
+ */
+
+package selectionresolution;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import jdk.internal.org.objectweb.asm.ClassWriter;
+import jdk.internal.org.objectweb.asm.Opcodes;
+
+public abstract class ClassConstruct {
+    private final ClassWriter cw;
+    private final String name;
+    private final boolean isInterface;
+    private final int index;
+
+    /**
+     * Base constructor for building a Class or Interface
+     * @param name Name of Class/Interface, including package name
+     * @param extending Name of extending Class if any
+     * @param access Access for Class/Interface
+     * @param classFileVersion Class file version
+     * @param interfaces Interface implemented
+     */
+    public ClassConstruct(String name,
+                          String extending,
+                          int access,
+                          int classFileVersion,
+                          int index,
+                          String... interfaces) {
+        this.name = name;
+        isInterface = (access & Opcodes.ACC_INTERFACE) == Opcodes.ACC_INTERFACE;
+        cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
+        cw.visit(classFileVersion, access, name, null, extending, interfaces == null ?  new String[] { } : interfaces);
+        this.index = index;
+    }
+
+    /**
+     * Get full Class/Interface name including package name, as it
+     * should appear in a classfile.
+     *
+     * @return The full Class/Interface name including package name
+     */
+    public String getName() {
+        return name;
+    }
+
+    /**
+     * Get the name of the class, including package as it would appear
+     * in Java source.
+     *
+     * @return The name of the class as it would appear in Java source.
+     */
+    public String getDottedName() {
+        return name.replace("/", ".");
+    }
+
+    public String getPackageName() {
+        final int idx = name.lastIndexOf('/');
+        if (idx != -1) {
+            return name.substring(0, name.indexOf('/'));
+        } else {
+            return null;
+        }
+    }
+
+    public String getClassName() {
+        final int idx = name.lastIndexOf('/');
+        if (idx != -1) {
+            return name.substring(name.indexOf('/'));
+        } else {
+            return name;
+        }
+    }
+
+    /**
+     * Add a method, no code associated with it yet
+     * @param name Name of method
+     * @param descriptor Descriptor for method
+     * @param access Access for the method
+     * @return Method object that can be used for constructing a method body
+     */
+    public Method addMethod(String name,
+                            String descriptor,
+                            int access) {
+        return addMethod(name, descriptor, access, null);
+    }
+
+    /**
+     * Add a method, no code associated with it yet
+     * @param name Name of method
+     * @param descriptor Descriptor for method
+     * @param access Access for the method
+     * @param execMode The execution mode for the method.
+     * @return Method object that can be used for constructing a method body
+     */
+    public Method addMethod(String name,
+                            String descriptor,
+                            int access,
+                            ClassBuilder.ExecutionMode execMode) {
+        return new Method(this, cw, name, descriptor, access, execMode);
+    }
+
+    /**
+     * Adds a m()LTestObject; method which returns null unless the method is abstract
+     * @param access Access for the method
+     */
+    public void addTestMethod(int access) {
+        Method m = new Method(this, cw, Method.defaultMethodName, Method.defaultMethodDescriptor, access, null);
+        if ((access & Opcodes.ACC_ABSTRACT) != Opcodes.ACC_ABSTRACT) {
+            m.makeDefaultMethod();
+        }
+    }
+
+    /**
+     * Construct the class to a byte[]
+     * @return byte[] with class file
+     */
+    public byte[] generateBytes() {
+        cw.visitEnd();
+        return cw.toByteArray();
+    }
+
+    /**
+     * Write out a class to a file in the specified directory.
+     *
+     * @param dir Directory to which to write out the file.
+     */
+    public void writeClass(final File dir) throws Exception {
+        final String pkgname = getPackageName();
+        final File pkgdir = pkgname != null ? new File(dir, getPackageName()) : dir;
+        pkgdir.mkdirs();
+        final File out = new File(pkgdir, getClassName() + ".class");
+        out.createNewFile();
+        try (final FileOutputStream fos = new FileOutputStream(out)) {
+            fos.write(generateBytes());
+        }
+    }
+
+    public boolean isInterface() {
+        return isInterface;
+    }
+
+    public Integer getIndex() {
+        return index;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/SelectionResolution/classes/selectionresolution/ClassData.java	Sat Apr 02 05:39:25 2016 +0200
@@ -0,0 +1,102 @@
+/*
+ * 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.
+ */
+
+package selectionresolution;
+
+/**
+ * A representation of information about a class.  Note that classes
+ * here define only one method.
+ */
+public class ClassData {
+
+    public enum Package {
+        /**
+         * Same package as the callsite.
+         */
+        SAME,
+        /**
+         * Different package from the callsite.
+         */
+        DIFFERENT,
+        /**
+         * Same as DIFFERENT, and also implies that the class access
+         * is package-private.
+         */
+        INACCESSIBLE,
+        /**
+         * Different from everything else.  Used in selection only, to
+         * test skipping package-private definitions.
+         */
+        OTHER,
+        /**
+         * Placeholder, used solely by the template dumper for
+         * printing out the effects of templates.  Don't use for
+         * anything else.
+         */
+        PLACEHOLDER;
+    }
+
+    /**
+     * The package ID for the class.
+     */
+    public final Package packageId;
+
+    /**
+     * The method data for the method definition.  If there is no
+     * method definition, this will be null.
+     */
+    public final MethodData methoddata;
+
+    /**
+     * The class access.  Note that this is controlled by the packageId.
+     */
+    public final MethodData.Access access;
+
+    // This is a hardwired value necessary for ClassBuilder
+    public final MethodData.Context abstraction = MethodData.Context.INSTANCE;
+
+    public ClassData(final Package packageId,
+                     final MethodData methoddata) {
+        this.packageId = packageId;
+        this.methoddata = methoddata;
+
+        if (packageId == Package.INACCESSIBLE)
+            access = MethodData.Access.PACKAGE;
+        else
+            access = MethodData.Access.PUBLIC;
+    }
+
+    public String toString() {
+        StringBuilder sb = new StringBuilder();
+        sb.append(" { ");
+
+        if (methoddata != null) {
+            sb.append(methoddata);
+        }
+
+        sb.append(" }\n\n");
+
+        return sb.toString();
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/SelectionResolution/classes/selectionresolution/Clazz.java	Sat Apr 02 05:39:25 2016 +0200
@@ -0,0 +1,77 @@
+/*
+ * 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.
+ *
+ */
+
+package selectionresolution;
+
+import static jdk.internal.org.objectweb.asm.Opcodes.ACC_PUBLIC;
+import static jdk.internal.org.objectweb.asm.Opcodes.ACC_SUPER;
+import static jdk.internal.org.objectweb.asm.Opcodes.V1_8;
+
+
+class Clazz extends ClassConstruct {
+
+    /**
+     * Construct a Class
+     * @param name Name of Class
+     * @param access Access for the Class
+     */
+    public Clazz(String name, int access, int index) {
+        this(name, null, access, V1_8, index, new String[] { });
+    }
+
+    /**
+     * Construct a Class
+     * @param name Name of Class
+     * @param extending Class being extended
+     * @param access Access for the Class
+     */
+    public Clazz(String name, String extending, int access, int index) {
+        this(name, extending, access, V1_8, index, new String[] { });
+    }
+
+    /**
+     * Construct a Class
+     * @param name Name of Class
+     * @param extending Class being extended
+     * @param access access for the Class
+     * @param implementing Interfaces implemented
+     */
+    public Clazz(String name, String extending, int access, int index, String... implementing) {
+        this(name, extending, access, V1_8, index, implementing);
+    }
+
+    /**
+     * Construct a Class
+     * @param name Name of Class
+     * @param extending Class being extended
+     * @param access Access for the Class
+     * @param classFileVersion Class file version
+     * @param implementing Interfaces implemented
+     */
+    public Clazz(String name, String extending, int access, int classFileVersion, int index, String... implementing) {
+        super(name, extending == null ? "java/lang/Object" : extending, access + ACC_SUPER, classFileVersion, index, implementing);
+        // Add the default constructor
+        addMethod("<init>", "()V", ACC_PUBLIC).makeConstructor(extending);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/SelectionResolution/classes/selectionresolution/HierarchyShape.java	Sat Apr 02 05:39:25 2016 +0200
@@ -0,0 +1,224 @@
+/*
+ * 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.
+ *
+ */
+
+package selectionresolution;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.Map;
+
+/**
+ * A representation of a class/interface hierarchy graph (just the
+ * graph; the class data is represented elsewhere).
+ */
+public class HierarchyShape {
+    public static final int OBJECT_CLASS = -1;
+
+    protected int maxId;
+
+    /**
+     * The names of all the classes.
+     */
+    private final HashSet<Integer> classes;
+
+    /**
+     * The names of all the interfaces.
+     */
+    private final HashSet<Integer> interfaces;
+    private final HashMap<Integer, HashSet<Integer>> extensions;
+
+    /**
+     * Create an empty hierarchy shape.
+     */
+    public HierarchyShape() {
+        this(0, new HashSet<>(), new HashSet<>(), new HashMap<>());
+    }
+
+    private HierarchyShape(final int maxId,
+                          final HashSet<Integer> classes,
+                          final HashSet<Integer> interfaces,
+                          final HashMap<Integer, HashSet<Integer>> extensions) {
+        this.maxId = maxId;
+        this.classes = classes;
+        this.interfaces = interfaces;
+        this.extensions = extensions;
+    }
+
+    /**
+     * Make a copy of this hierarchy shape.
+     */
+    public HierarchyShape copy() {
+        final HashMap<Integer, HashSet<Integer>> newextensions = new HashMap<>();
+
+        for(final Map.Entry<Integer, HashSet<Integer>> entry :
+                extensions.entrySet()) {
+            newextensions.put(entry.getKey(),
+                              (HashSet<Integer>)entry.getValue().clone());
+        }
+
+        return new HierarchyShape(maxId, (HashSet<Integer>) classes.clone(),
+                                  (HashSet<Integer>) interfaces.clone(),
+                                  newextensions);
+    }
+
+    /**
+     * Add a class, and return its id.
+     *
+     * @return The new class id.
+     */
+    public int addClass() {
+        final int id = maxId++;
+        classes.add(id);
+        return id;
+    }
+
+    /**
+     * Add an interface, and return its id.
+     *
+     * @return The new interface id.
+     */
+    public int addInterface() {
+        final int id = maxId++;
+        interfaces.add(id);
+        return id;
+    }
+
+    /**
+     * Add an inheritance.
+     *
+     * @param sub The sub class/interface.
+     * @param sup The super class/interface
+     */
+    public void addInherit(final int sub,
+                           final int sup) {
+        HashSet<Integer> ext = extensions.get(sub);
+
+        if (ext == null) {
+            ext = new HashSet<>();
+            extensions.put(sub, ext);
+        }
+
+        ext.add(sup);
+    }
+
+    @Override
+    public String toString() {
+        String out = "";
+        for(int i = maxId - 1; i >= 0; i--) {
+            out += i + ": ";
+            for(int j = 0; j < maxId; j++) {
+                out += "[" + (inherits(i, j) ? "1" : "0") + "]";
+            }
+            out += "\n";
+        }
+        return out;
+    }
+
+    /**
+     * Indicate whether the first class inherits from the second.
+     *
+     * @param sub The possible subtype.
+     * @param sup The possible supertype.
+     * @return Whether or not {@code sub} inherits from {@code sup}.
+     */
+    public boolean inherits(final int sub, final int sup) {
+        final Set<Integer> ext = extensions.get(sub);
+        if (ext != null) {
+            return ext.contains(sup);
+        } else {
+            return false;
+        }
+    }
+
+    /**
+     * Indicate whether a given type name is a class.
+     *
+     * @param id The type in question.
+     * @return Whether or not the type is a class.
+     */
+    public boolean isClass(final int id) {
+        if (id == OBJECT_CLASS) {
+            return true;
+        }
+        return classes.contains(id);
+    }
+
+    /**
+     * Indicate whether a given type name is an interface.
+     *
+     * @param id The type in question.
+     * @return Whether or not the type is an interface.
+     */
+    public boolean isInterface(final int id) {
+        if (id == OBJECT_CLASS) {
+            return false;
+        }
+        return interfaces.contains(id);
+    }
+
+    /**
+     * Get an iterator over the classes.
+     *
+     * @return An iterator over classes.
+     */
+    public Collection<Integer> classes() {
+        return classes;
+    }
+
+    /**
+     * Get an iterator over the interfaces.
+     *
+     * @return An iterator over interfaces.
+     */
+    public Collection<Integer> interfaces() {
+        return interfaces;
+    }
+
+    /**
+     * Get an iterator over all types.
+     *
+     * @return An iterator over all types.
+     */
+    public Collection<Integer> types() {
+        final Set<Integer> combined = new HashSet(classes);
+        combined.addAll(interfaces);
+        return combined;
+    }
+
+    public int numClasses() {
+        return classes.size();
+    }
+
+    public int numInterfaces() {
+        return interfaces.size();
+    }
+
+    public int numTypes() {
+        return numClasses() + numInterfaces();
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/SelectionResolution/classes/selectionresolution/Interface.java	Sat Apr 02 05:39:25 2016 +0200
@@ -0,0 +1,50 @@
+/*
+ * 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.
+ *
+ */
+
+package selectionresolution;
+
+import static jdk.internal.org.objectweb.asm.Opcodes.ACC_ABSTRACT;
+import static jdk.internal.org.objectweb.asm.Opcodes.ACC_INTERFACE;
+import static jdk.internal.org.objectweb.asm.Opcodes.V1_8;
+
+class Interface extends ClassConstruct {
+
+    public Interface(String name, int access, int index) {
+        this(name, V1_8, access, index, (String)null);
+    }
+
+    public Interface(String name, int index) {
+        this(name, V1_8, index, (String)null);
+    }
+
+
+    public Interface(String name, int access, int index, String... extending) {
+        this(name, V1_8, access, index, extending);
+    }
+
+    public Interface(String name, int classFileVersion, int access, int index, String... extending) {
+        super(name, "java/lang/Object", access + ACC_ABSTRACT + ACC_INTERFACE, classFileVersion, index, extending);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/SelectionResolution/classes/selectionresolution/Method.java	Sat Apr 02 05:39:25 2016 +0200
@@ -0,0 +1,266 @@
+/*
+ * 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.
+ *
+ */
+
+package selectionresolution;
+
+import jdk.internal.org.objectweb.asm.ClassVisitor;
+import jdk.internal.org.objectweb.asm.Handle;
+import jdk.internal.org.objectweb.asm.MethodVisitor;
+
+import java.lang.invoke.CallSite;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
+
+import static jdk.internal.org.objectweb.asm.Opcodes.ACC_PUBLIC;
+import static jdk.internal.org.objectweb.asm.Opcodes.ACC_STATIC;
+import static jdk.internal.org.objectweb.asm.Opcodes.ALOAD;
+import static jdk.internal.org.objectweb.asm.Opcodes.ARETURN;
+import static jdk.internal.org.objectweb.asm.Opcodes.DUP;
+import static jdk.internal.org.objectweb.asm.Opcodes.POP;
+import static jdk.internal.org.objectweb.asm.Opcodes.NEW;
+import static jdk.internal.org.objectweb.asm.Opcodes.SWAP;
+import static jdk.internal.org.objectweb.asm.Opcodes.ASTORE;
+import static jdk.internal.org.objectweb.asm.Opcodes.RETURN;
+import static jdk.internal.org.objectweb.asm.Opcodes.INVOKESPECIAL;
+import static jdk.internal.org.objectweb.asm.Opcodes.INVOKESTATIC;
+import static jdk.internal.org.objectweb.asm.Opcodes.INVOKEINTERFACE;
+import static jdk.internal.org.objectweb.asm.Opcodes.INVOKEVIRTUAL;
+import static jdk.internal.org.objectweb.asm.Opcodes.H_INVOKESPECIAL;
+import static jdk.internal.org.objectweb.asm.Opcodes.H_INVOKESTATIC;
+import static jdk.internal.org.objectweb.asm.Opcodes.H_INVOKEINTERFACE;
+import static jdk.internal.org.objectweb.asm.Opcodes.H_INVOKEVIRTUAL;
+
+class Method {
+    public static final String defaultMethodName        = "m";
+    public static final String defaultMethodDescriptor  = "()Ljava/lang/Integer;";
+    public static final String methodDescriptorTemplate = "(L%s;)Ljava/lang/Integer;";
+    private final ClassConstruct ownerClass;
+    private final String ownerClassName;
+    private final ClassVisitor cv;
+    private final MethodVisitor mv;
+    private final boolean isInterface;
+    private final ClassBuilder.ExecutionMode execMode;
+
+    public Method(ClassConstruct ownerClass, ClassVisitor cv, String name, String descriptor, int access,
+                  ClassBuilder.ExecutionMode execMode) {
+        this.ownerClassName = ownerClass.getName();
+        this.ownerClass = ownerClass;
+        this.isInterface = ownerClass.isInterface();
+        this.execMode = execMode;
+        this.cv = cv;
+        mv = cv.visitMethod(access, name, descriptor, null, null);
+        mv.visitCode();
+    }
+    /**
+     * Add code for the m()Ljava/lang/Integer; method, always returns null
+     */
+    public void makeDefaultMethod() {
+        mv.visitTypeInsn(NEW, "java/lang/Integer");
+        mv.visitInsn(DUP);
+        mv.visitLdcInsn(ownerClass.getIndex());
+        mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Integer", "<init>", "(I)V");
+        mv.visitInsn(ARETURN);
+        mv.visitMaxs(0, 0);
+        mv.visitEnd();
+    }
+
+    public void makePrivateCallMethod(String className) {
+        makeSuperCallMethod(INVOKESPECIAL, className);
+    }
+
+    public void makeSuperCallMethod(int invokeInstruction, String className) {
+        mv.visitVarInsn(ALOAD, 0);
+        makeCall(invokeInstruction, className);
+        mv.visitInsn(POP);
+        done();
+    }
+
+    public void defaultInvoke(int instr, String className, String objectRef) {
+        switch (instr) {
+            case INVOKEVIRTUAL:
+                defaultInvokeVirtual(className, objectRef);
+                break;
+            case INVOKEINTERFACE:
+                defaultInvokeInterface(className, objectRef);
+                break;
+            case INVOKESTATIC:
+                defaultInvokeStatic(className);
+                break;
+            case INVOKESPECIAL:
+                defaultInvokeSpecial(className, objectRef);
+                break;
+            default:
+                break;
+        }
+        mv.visitInsn(ARETURN);
+        mv.visitMaxs(0, 0);
+        mv.visitEnd();
+    }
+
+    public void defaultInvokeVirtual(String className, String objectRef) {
+        String objectRefPackageName = objectRef.substring(0, objectRef.lastIndexOf("/"));
+        makeNewObject(objectRef, objectRefPackageName);
+        makeCall(INVOKEVIRTUAL, className, false);
+    }
+
+    public void defaultInvokeInterface(String className, String objectRef) {
+        String objectRefPackageName = objectRef.substring(0, objectRef.lastIndexOf("/"));
+        makeNewObject(objectRef, objectRefPackageName);
+        makeCall(INVOKEINTERFACE, className, true);
+    }
+
+    public void defaultInvokeSpecial(String className, String objectRef) {
+        String objectRefPackageName = objectRef.substring(0, objectRef.lastIndexOf("/"));
+        makeNewObject(objectRef, objectRefPackageName);
+        makeCall(INVOKESPECIAL, className, false);
+    }
+
+    public void defaultInvokeStatic(String className) {
+        makeCall(INVOKESTATIC, className);
+    }
+
+    private Method makeCall(int invokeInstruction, String className) {
+        return makeCall(invokeInstruction, className, isInterface);
+    }
+
+    private Method makeCall(int invokeInstruction, String className, boolean isInterface) {
+        switch(execMode) {
+            case DIRECT: {
+                mv.visitMethodInsn(invokeInstruction, className, defaultMethodName, defaultMethodDescriptor, isInterface);
+                break;
+            }
+            case INDY: {
+                Handle m = convertToHandle(invokeInstruction, className, defaultMethodName, defaultMethodDescriptor);
+                Handle bsm = generateBootstrapMethod(m);
+                mv.visitInvokeDynamicInsn(defaultMethodName, defaultMethodDescriptor, bsm);
+                break;
+            }
+            case MH_INVOKE_EXACT:
+            case MH_INVOKE_GENERIC: {
+                String invokerName = execMode == ClassBuilder.ExecutionMode.MH_INVOKE_GENERIC
+                        ? "invoke" : "invokeExact";
+
+                Handle m = convertToHandle(invokeInstruction, className, defaultMethodName, defaultMethodDescriptor);
+                mv.visitLdcInsn(m);
+                mv.visitInsn(SWAP);
+                mv.visitMethodInsn(INVOKEVIRTUAL,
+                        "java/lang/invoke/MethodHandle",
+                        invokerName,
+                        String.format(methodDescriptorTemplate, className),
+                        false);
+                break;
+            }
+            default:
+                throw new Error("Unknown execution mode: " + execMode);
+
+        }
+        return this;
+    }
+
+    private Handle generateBootstrapMethod(Handle h) {
+        String bootstrapName = "bootstrapMethod";
+        MethodType bootstrapType = MethodType.methodType(CallSite.class, MethodHandles.Lookup.class, String.class, MethodType.class);
+
+        MethodVisitor bmv = cv.visitMethod(ACC_PUBLIC | ACC_STATIC, bootstrapName, bootstrapType.toMethodDescriptorString(), null, null);
+        bmv.visitCode();
+
+        String constCallSite = "java/lang/invoke/ConstantCallSite";
+        bmv.visitTypeInsn(NEW, constCallSite);
+        bmv.visitInsn(DUP);
+
+        bmv.visitLdcInsn(h);
+
+        bmv.visitMethodInsn(INVOKESPECIAL, constCallSite, "<init>", "(Ljava/lang/invoke/MethodHandle;)V", false);
+        bmv.visitInsn(ARETURN);
+
+        bmv.visitMaxs(0,0);
+        bmv.visitEnd();
+
+        return new Handle(H_INVOKESTATIC, ownerClassName, bootstrapName, bootstrapType.toMethodDescriptorString());
+    }
+
+
+    private static Handle convertToHandle(int invokeInstruction, String className, String methodName, String methodDesc) {
+        int tag;
+        switch (invokeInstruction) {
+            case INVOKEVIRTUAL:   tag = H_INVOKEVIRTUAL;   break;
+            case INVOKEINTERFACE: tag = H_INVOKEINTERFACE; break;
+            case INVOKESPECIAL:   tag = H_INVOKESPECIAL;   break;
+            case INVOKESTATIC:    tag = H_INVOKESTATIC;    break;
+            default:
+                throw new Error("Unknown invoke instruction: "+invokeInstruction);
+        }
+
+        return new Handle(tag, className, methodName, methodDesc);
+    }
+
+    private void makeNewObject(String objectRef, String objectRefPackageName) {
+        String className = objectRef.substring(objectRef.lastIndexOf("/") + 1);
+        makeStaticCall( objectRefPackageName + "/Helper",
+                        "get" + className,
+                        "()L" + objectRef + ";");
+        mv.visitVarInsn(ASTORE, 1);
+        mv.visitVarInsn(ALOAD, 1);
+    }
+
+    public void makeTestCall(String className) {
+        mv.visitTypeInsn(NEW, className);
+        mv.visitInsn(DUP);
+        mv.visitMethodInsn(INVOKESPECIAL, className, "<init>", "()V", false);
+        mv.visitVarInsn(ASTORE, 1);
+        mv.visitVarInsn(ALOAD, 1);
+        mv.visitMethodInsn(INVOKEVIRTUAL, className, "test", "()Ljava/lang/Integer;", false);
+        mv.visitInsn(RETURN);
+        mv.visitMaxs(2, 2);
+        mv.visitEnd();
+    }
+
+    public Method makeStaticCall(String classname, String method, String descriptor) {
+        mv.visitMethodInsn(INVOKESTATIC, classname, method, descriptor, isInterface);
+        return this;
+    }
+
+    public void makeConstructor(String extending) {
+        mv.visitVarInsn(ALOAD, 0);
+        mv.visitMethodInsn(INVOKESPECIAL, extending == null ? "java/lang/Object" : extending, "<init>", "()V", isInterface);
+        mv.visitInsn(RETURN);
+        mv.visitMaxs(0, 0);
+        mv.visitEnd();
+    }
+
+    public void makeInstantiateMethod(String className) {
+        mv.visitTypeInsn(NEW, className);
+        mv.visitInsn(DUP);
+        mv.visitMethodInsn(INVOKESPECIAL, className, "<init>", "()V", false);
+        mv.visitInsn(ARETURN);
+        mv.visitMaxs(0, 0);
+        mv.visitEnd();
+    }
+
+    public void done() {
+        mv.visitInsn(RETURN);
+        mv.visitMaxs(0, 0);
+        mv.visitEnd();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/SelectionResolution/classes/selectionresolution/MethodData.java	Sat Apr 02 05:39:25 2016 +0200
@@ -0,0 +1,104 @@
+/*
+ * 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.
+ *
+ */
+
+package selectionresolution;
+
+/**
+ * A representation of a method definition.
+ */
+public class MethodData {
+
+    public enum Access {
+        PUBLIC(1),
+        PACKAGE(0),
+        PROTECTED(4),
+        PRIVATE(2),
+        /**
+         * Placeholder, used solely for printing out the effects of
+         * templates.  Don't use.
+         */
+        PLACEHOLDER(-1);
+
+        public final int flag;
+
+        Access(int flag) {
+            this.flag = flag;
+        }
+    }
+
+    public enum Context {
+        ABSTRACT,
+        INSTANCE,
+        STATIC,
+        /**
+         * Placeholder, used solely for printing out the effects of
+         * templates.  Don't use.
+         */
+        PLACEHOLDER;
+    };
+
+    /**
+     * Access for the method.
+     */
+    public final Access access;
+
+    /**
+     * Context (static, instance, abstract) for the method.
+     */
+    public final Context context;
+
+    /**
+     * Create method data.
+     */
+    public MethodData(final Access access,
+                      final Context context) {
+
+        this.access = access;
+        this.context = context;
+    }
+
+    public String toString() {
+        StringBuilder sb = new StringBuilder();
+        switch (access) {
+        case PUBLIC: sb.append("public"); break;
+        case PACKAGE: sb.append("package"); break;
+        case PROTECTED: sb.append("protected"); break;
+        case PRIVATE: sb.append("private"); break;
+        case PLACEHOLDER: sb.append(" _"); break;
+        default: throw new RuntimeException("Impossible case");
+        }
+
+        switch (context) {
+        case STATIC: sb.append(" static"); break;
+        case INSTANCE: sb.append(" instance"); break;
+        case ABSTRACT: sb.append("  abstract"); break;
+        case PLACEHOLDER: sb.append(" _"); break;
+        default: throw new RuntimeException("Impossible case");
+        }
+        sb.append(" Integer m();");
+
+        return sb.toString();
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/SelectionResolution/classes/selectionresolution/Result.java	Sat Apr 02 05:39:25 2016 +0200
@@ -0,0 +1,262 @@
+/*
+ * 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.
+ */
+
+package selectionresolution;
+
+import java.util.Arrays;
+import java.util.HashSet;
+
+/**
+ * Representation of an expected result.
+ */
+public interface Result {
+    public static final Result ICCE = new Exception(IncompatibleClassChangeError.class);
+    public static final Result IAE  = new Exception(IllegalAccessError.class);
+    public static final Result NSME = new Exception(NoSuchMethodError.class);
+    public static final Result AME  = new Exception(AbstractMethodError.class);
+
+    // Factories
+
+    /**
+     * Create a result that expects the given class.
+     */
+    public static Result is(int id) {
+        return new Single(id);
+    }
+
+    /**
+     * Create a result that expects the given classes.
+     */
+    public static Result is(int... multiple) {
+        assert multiple.length > 0;
+
+        if (multiple.length == 1) {
+            return new Single(multiple[0]);
+        } else {
+            return new Any(multiple);
+        }
+    }
+
+    /**
+     * Create a result that expects the given exception to be thrown.
+     */
+    public static Result is(Class<? extends Throwable> exType) {
+        return new Exception(exType);
+    }
+
+    /**
+     * Create a result that expects the given exception to be thrown.
+     */
+    public static Result is(Throwable ex) {
+        return Result.is(ex.getClass());
+    }
+
+    public static final Result EMPTY = new Empty();
+
+    /**
+     * Create an empty Result.
+     */
+    public static Result empty() {
+        return EMPTY;
+    }
+
+
+    public boolean complyWith(int i);
+    public boolean complyWith(Throwable e);
+    public boolean complyWith(Result r);
+
+    static class Empty implements Result {
+        @Override
+        public boolean complyWith(int i) {
+            return false;
+        }
+
+        @Override
+        public boolean complyWith(Throwable e) {
+            return false;
+        }
+
+        @Override
+        public boolean complyWith(Result r) {
+            return false;
+        }
+    }
+
+    static class Single implements Result {
+        public int id;
+
+        public Single(int id) {
+            this.id = id;
+        }
+
+        @Override
+        public boolean complyWith(int i) {
+            return id == i;
+        }
+
+        @Override
+        public boolean complyWith(Throwable e) {
+            return false;
+        }
+
+        @Override
+        public boolean complyWith(Result r) {
+            if (r instanceof Single) {
+                return complyWith(((Single)r).id);
+            } else if (r instanceof Any) {
+                return r.complyWith(this);
+            }
+            return false;
+        }
+
+        @Override
+        public boolean equals(Object o) {
+            if (this == o) return true;
+            if (!(o instanceof Single)) return false;
+
+            Single single = (Single) o;
+
+            return (id == single.id);
+        }
+
+        @Override
+        public int hashCode() {
+            return id;
+        }
+
+        @Override
+        public String toString() {
+            final StringBuffer sb = new StringBuffer("Result=Single{");
+            sb.append("id=").append(id);
+            sb.append('}');
+            return sb.toString();
+        }
+    }
+
+    static class Any implements Result {
+        public int[] ids;
+        public Any(int[] ids) {
+            this.ids = ids;
+        }
+
+        @Override
+        public boolean complyWith(int i) {
+            return Arrays.stream(ids)
+                    .anyMatch(j -> j == i);
+        }
+
+        @Override
+        public boolean complyWith(Throwable e) {
+            return false;
+        }
+
+        @Override
+        public boolean complyWith(Result r) {
+            if (r instanceof Single) {
+                return complyWith(((Single)r).id);
+            }
+            if (r instanceof Any) {
+                return Arrays.equals(ids, ((Any) r).ids);
+            }
+            return false;
+        }
+
+        @Override
+        public boolean equals(Object o) {
+            if (this == o) return true;
+            if (o == null || getClass() != o.getClass()) return false;
+
+            Any any = (Any) o;
+
+            return Arrays.equals(ids, any.ids);
+        }
+
+        @Override
+        public int hashCode() {
+            return Arrays.hashCode(ids);
+        }
+
+        @Override
+        public String toString() {
+            final StringBuffer sb = new StringBuffer("Result=Any{");
+            sb.append("ids=");
+            if (ids == null) sb.append("null");
+            else {
+                sb.append('[');
+                for (int i = 0; i < ids.length; ++i)
+                    sb.append(i == 0 ? "" : ", ").append(ids[i]);
+                sb.append(']');
+            }
+            sb.append('}');
+            return sb.toString();
+        }
+    }
+
+    static class Exception implements Result {
+        public Class<? extends Throwable> exc;
+        public Exception(Class<? extends Throwable> e) {
+            this.exc = e;
+        }
+
+        @Override
+        public boolean complyWith(int i) {
+            return false;
+        }
+
+        @Override
+        public boolean complyWith(Throwable e) {
+            return exc.isAssignableFrom(e.getClass());
+        }
+
+        @Override
+        public boolean complyWith(Result r) {
+            if (r instanceof Exception) {
+                return exc.isAssignableFrom(((Exception) r).exc);
+            }
+            return false;
+        }
+
+        @Override
+        public boolean equals(Object o) {
+            if (this == o) return true;
+            if (!(o instanceof Exception)) return false;
+
+            Exception exception = (Exception) o;
+
+            return exc.equals(exception.exc);
+        }
+
+        @Override
+        public int hashCode() {
+            return exc.hashCode();
+        }
+
+        @Override
+        public String toString() {
+            final StringBuffer sb = new StringBuffer("Result=Exception{");
+            sb.append("exc=").append(exc);
+            sb.append('}');
+            return sb.toString();
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/SelectionResolution/classes/selectionresolution/SelectionResolutionTest.java	Sat Apr 02 05:39:25 2016 +0200
@@ -0,0 +1,139 @@
+/*
+ * 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.
+ */
+
+package selectionresolution;
+
+import java.util.function.Consumer;
+import java.util.Collection;
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * A master superclass for all selection/resolution tests.  Contains a
+ * couple of standard definitions that make writing these tests
+ * easier.
+ */
+public abstract class SelectionResolutionTest {
+
+    /**
+     * A unified output function, to ensure that all output goes to
+     * the right string (System.err).
+     *
+     * @param str The line to print.
+     */
+    protected void println(final String str) {
+        System.err.println(str);
+    }
+
+    /**
+     * A test group is a generator for a set of tests that should
+     * share common characteristics.  The Simple class provides a
+     * default implementation that should work for most purposes.
+     */
+    public static interface TestGroup {
+        /**
+         * Given an action that runs a given test case, generate and
+         * run all cases in this test group.
+         */
+        public void runCases(Consumer<SelectionResolutionTestCase> runner);
+
+        /**
+         * The basic implementation of TestGroup.  Produces one case
+         * for every possible combination of cases from each of its
+         * templates, by running them in order on an empty
+         * SelectionResolutionTestCase.Builder.  This should be good
+         * enough for writing most tests.
+         */
+        public static class Simple implements TestGroup {
+            private final Template[] templates;
+            private final SelectionResolutionTestCase.Builder initBuilder;
+
+            public Simple(final SelectionResolutionTestCase.Builder initBuilder,
+                          final Template... templates) {
+                this.templates = templates;
+                this.initBuilder = initBuilder;
+            }
+
+            @Override
+            public void runCases(final Consumer<SelectionResolutionTestCase> runner) {
+                Consumer<SelectionResolutionTestCase.Builder> curr = (builder) -> {
+                    runner.accept(builder.build());
+                };
+
+                for(int i = templates.length - 1; i >= 0; i--) {
+                    final Consumer<SelectionResolutionTestCase.Builder> next = curr;
+                    final Template template = templates[i];
+                    curr = (builder) -> {
+                        template.runCases(next, builder);
+                    };
+                }
+
+                curr.accept(initBuilder);
+            }
+        }
+    }
+
+    private final List<String> errs = new LinkedList<String>();
+
+    private final Collection<TestGroup> testGroups;
+
+    private int testcount = 0;
+
+    /**
+     * Create a test from a set of test groups.  Most actual tests can
+     * just define the test groups and pass them into this
+     * constructor, then call run.
+     */
+    protected SelectionResolutionTest(final Collection<TestGroup> testGroups) {
+        this.testGroups = testGroups;
+    }
+
+    /**
+     * Run all the tests, report errors if they happen.
+     */
+    protected void run() {
+        testGroups.stream().forEach(
+                (group) -> {
+                    group.runCases((final SelectionResolutionTestCase testcase) -> {
+                            testcount++;
+                            final String err = testcase.run();
+
+                            if (err != null) {
+                                errs.add(err);
+                            }
+                        });
+                });
+
+        println("Ran " + testcount + " cases");
+
+        if(!errs.isEmpty()) {
+            println("Errors occurred in test:");
+            for(final String err : errs) {
+                println(err);
+            }
+            throw new RuntimeException("Errors occurred in test");
+        } else {
+            println("All test cases succeeded");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/SelectionResolution/classes/selectionresolution/SelectionResolutionTestCase.java	Sat Apr 02 05:39:25 2016 +0200
@@ -0,0 +1,452 @@
+/*
+ * 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.
+ */
+
+package selectionresolution;
+
+import java.io.File;
+import java.io.FileWriter;
+import java.util.HashMap;
+
+/**
+ * One individual test case.  This class also defines a builder, which
+ * can be used to build up cases.
+ */
+public class SelectionResolutionTestCase {
+
+    public enum InvokeInstruction {
+        INVOKESTATIC,
+        INVOKESPECIAL,
+        INVOKEINTERFACE,
+        INVOKEVIRTUAL;
+    }
+
+    /**
+     * The class data (includes interface data).
+     */
+    public final HashMap<Integer, ClassData> classdata;
+    /**
+     * The hierarchy shape.
+     */
+    public final HierarchyShape hier;
+    /**
+     * The invoke instruction to use.
+     */
+    public final InvokeInstruction invoke;
+    /**
+     * Which class is the methodref (or interface methodref).
+     */
+    public final int methodref;
+    /**
+     * Which class is the objectref.
+     */
+    public final int objectref;
+    /**
+     * Which class is the callsite (this must be a class, not an interface.
+     */
+    public final int callsite;
+    /**
+     * The expected result.
+     */
+    public final Result result;
+
+    private SelectionResolutionTestCase(final HashMap<Integer, ClassData> classdata,
+                                        final HierarchyShape hier,
+                                        final InvokeInstruction invoke,
+                                        final int methodref,
+                                        final int objectref,
+                                        final int callsite,
+                                        final int expected) {
+        this.classdata = classdata;
+        this.hier = hier;
+        this.invoke = invoke;
+        this.methodref = methodref;
+        this.objectref = objectref;
+        this.callsite = callsite;
+        this.result = Result.is(expected);
+    }
+
+    private SelectionResolutionTestCase(final HashMap<Integer, ClassData> classdata,
+                                        final HierarchyShape hier,
+                                        final InvokeInstruction invoke,
+                                        final int methodref,
+                                        final int objectref,
+                                        final int callsite,
+                                        final Result result) {
+        this.classdata = classdata;
+        this.hier = hier;
+        this.invoke = invoke;
+        this.methodref = methodref;
+        this.objectref = objectref;
+        this.callsite = callsite;
+        this.result = result;
+    }
+
+    private static int currError = 0;
+
+    private String dumpClasses(final ClassConstruct[] classes)
+        throws Exception {
+        final String errorDirName = "error_" + currError++;
+        final File errorDir = new File(errorDirName);
+        errorDir.mkdirs();
+        for (int i = 0; i < classes.length; i++) {
+            classes[i].writeClass(errorDir);
+        }
+        try (final FileWriter fos =
+             new FileWriter(new File(errorDir, "description.txt"))) {
+            fos.write(this.toString());
+        }
+        return errorDirName;
+    }
+
+    /**
+     * Run this case, return an error message, or null.
+     *
+     * @return An error message, or null if the case succeeded.
+     */
+    public String run() {
+        /* Uncomment this line to print EVERY case */
+        //System.err.println("Running\n" + this);
+        final ClassBuilder builder =
+            new ClassBuilder(this, ClassBuilder.ExecutionMode.DIRECT);
+        try {
+            final ByteCodeClassLoader bcl = new ByteCodeClassLoader();
+            final ClassConstruct[] classes = builder.build();
+
+            try {
+                bcl.addClasses(classes);
+                bcl.loadAll();
+
+                // Grab the callsite class.
+                final Class testclass =
+                    bcl.findClass(builder.getCallsiteClass().getDottedName());
+
+                // Get the 'test' method out of it and call it.  The
+                // return value tess which class that got selected.
+                final java.lang.reflect.Method method =
+                    testclass.getDeclaredMethod("test");
+                final int actual = (Integer) method.invoke(null);
+                // Check the result.
+                if (!result.complyWith(actual)) {
+                    final String dump = dumpClasses(classes);
+                    return "Failed:\n" + this + "\nExpected " + result + " got " + actual + "\nClasses written to " + dump;
+                }
+            } catch (Throwable t) {
+                // This catch block is handling exceptions that we
+                // might expect to see.
+                final Throwable actual = t.getCause();
+                if (actual == null) {
+                    final String dump = dumpClasses(classes);
+                    System.err.println("Unexpected exception in test\n" + this + "\nClasses written to " + dump);
+                    throw t;
+                } else if (result == null) {
+                    final String dump = dumpClasses(classes);
+                    return "Failed:\n" + this + "\nUnexpected exception " + actual + "\nClasses written to " + dump;
+                } else if (!result.complyWith(actual)) {
+                    final String dump = dumpClasses(classes);
+                    return "Failed:\n" + this + "\nExpected " + this.result + " got " + actual + "\nClasses written to " + dump;
+                }
+            }
+        } catch(Throwable e) {
+            throw new RuntimeException(e);
+        }
+        return null;
+    }
+
+    private static void addPackage(final StringBuilder sb,
+                                  final ClassData cd) {
+        switch (cd.packageId) {
+        case SAME: sb.append("Same."); break;
+        case DIFFERENT: sb.append("Different."); break;
+        case OTHER: sb.append("Other."); break;
+        case PLACEHOLDER: sb.append("_."); break;
+        default: throw new RuntimeException("Impossible case");
+        }
+    }
+
+    public String toString() {
+        final StringBuilder sb = new StringBuilder();
+        //sb.append("hierarchy:\n" + hier + "\n");
+        sb.append("invoke:    " + invoke + "\n");
+        if (methodref != -1) {
+            if (hier.isClass(methodref)) {
+                sb.append("methodref: C" + methodref + "\n");
+            } else {
+                sb.append("methodref: I" + methodref + "\n");
+            }
+        }
+        if (objectref != -1) {
+            if (hier.isClass(objectref)) {
+                sb.append("objectref: C" + objectref + "\n");
+            } else {
+                sb.append("objectref: I" + objectref + "\n");
+            }
+        }
+        if (callsite != -1) {
+            if (hier.isClass(callsite)) {
+                sb.append("callsite: C" + callsite + "\n");
+            } else {
+                sb.append("callsite: I" + callsite + "\n");
+            }
+        }
+        sb.append("result: " + result + "\n");
+        sb.append("classes:\n\n");
+
+        for(int i = 0; classdata.containsKey(i); i++) {
+            final ClassData cd = classdata.get(i);
+
+            if (hier.isClass(i)) {
+                sb.append("class ");
+                addPackage(sb, cd);
+                sb.append("C" + i);
+            } else {
+                sb.append("interface ");
+                addPackage(sb, cd);
+                sb.append("I" + i);
+            }
+
+            boolean first = true;
+            for(final int j : hier.classes()) {
+                if (hier.inherits(i, j)) {
+                    if (first) {
+                        sb.append(" extends C" + j);
+                    } else {
+                        sb.append(", C" + j);
+                    }
+                }
+            }
+
+            first = true;
+            for(final int j : hier.interfaces()) {
+                if (hier.inherits(i, j)) {
+                    if (first) {
+                        sb.append(" implements I" + j);
+                    } else {
+                        sb.append(", I" + j);
+                    }
+                }
+            }
+
+            sb.append(cd);
+        }
+
+        return sb.toString();
+    }
+
+    /**
+     * A builder, facilitating building up test cases.
+     */
+    public static class Builder {
+        /**
+         * A map from class (or interface) id's to ClassDatas
+         */
+        public final HashMap<Integer, ClassData> classdata;
+        /**
+         * The hierarchy shape.
+         */
+        public final HierarchyShape hier;
+        /**
+         * Which invoke instruction to use.
+         */
+        public InvokeInstruction invoke;
+        /**
+         * The id of the methodref (or interface methodref).
+         */
+        public int methodref = -1;
+        /**
+         * The id of the object ref.  Note that for the generator
+         * framework to work, this must be set to something.  If an
+         * objectref isn't used, just set it to the methodref.
+         */
+        public int objectref = -1;
+        /**
+         * The id of the callsite.
+         */
+        public int callsite = -1;
+        /**
+         * The id of the expected result.  This is used to store the
+         * expected resolution result.
+         */
+        public int expected;
+        /**
+         * The expected result.  This needs to be set before the final
+         * test case is built.
+         */
+        public Result result;
+
+        /**
+         * Create an empty Builder object.
+         */
+        public Builder() {
+            classdata = new HashMap<>();
+            hier = new HierarchyShape();
+        }
+
+        private Builder(final HashMap<Integer, ClassData> classdata,
+                        final HierarchyShape hier,
+                        final InvokeInstruction invoke,
+                        final int methodref,
+                        final int objectref,
+                        final int callsite,
+                        final int expected,
+                        final Result result) {
+            this.classdata = classdata;
+            this.hier = hier;
+            this.invoke = invoke;
+            this.methodref = methodref;
+            this.objectref = objectref;
+            this.callsite = callsite;
+            this.expected = expected;
+            this.result = result;
+        }
+
+        private Builder(final Builder other) {
+            this((HashMap<Integer, ClassData>) other.classdata.clone(),
+                 other.hier.copy(), other.invoke, other.methodref, other.objectref,
+                 other.callsite, other.expected, other.result);
+        }
+
+        public SelectionResolutionTestCase build() {
+            if (result != null) {
+                return new SelectionResolutionTestCase(classdata, hier, invoke,
+                                                       methodref, objectref,
+                                                       callsite, result);
+            } else {
+                return new SelectionResolutionTestCase(classdata, hier, invoke,
+                                                       methodref, objectref,
+                                                       callsite, expected);
+            }
+        }
+
+        /**
+         * Set the expected result.
+         */
+        public void setResult(final Result result) {
+            this.result = result;
+        }
+
+        /**
+         * Add a class, and return its id.
+         *
+         * @return The new class' id.
+         */
+        public int addClass(final ClassData data) {
+            final int id = hier.addClass();
+            classdata.put(id, data);
+            return id;
+        }
+
+        /**
+         * Add an interface, and return its id.
+         *
+         * @return The new class' id.
+         */
+        public int addInterface(final ClassData data) {
+            final int id = hier.addInterface();
+            classdata.put(id, data);
+            return id;
+        }
+
+        /**
+         * Make a copy of this builder.
+         */
+        public Builder copy() {
+            return new Builder(this);
+        }
+
+        public String toString() {
+            final StringBuilder sb = new StringBuilder();
+            //sb.append("hierarchy:\n" + hier + "\n");
+            sb.append("invoke:    " + invoke + "\n");
+            if (methodref != -1) {
+                if (hier.isClass(methodref)) {
+                    sb.append("methodref: C" + methodref + "\n");
+                } else {
+                    sb.append("methodref: I" + methodref + "\n");
+                }
+            }
+            if (objectref != -1) {
+                if (hier.isClass(objectref)) {
+                    sb.append("objectref: C" + objectref + "\n");
+                } else {
+                    sb.append("objectref: I" + objectref + "\n");
+                }
+            }
+            if (callsite != -1) {
+                if (hier.isClass(callsite)) {
+                    sb.append("callsite: C" + callsite + "\n");
+                } else {
+                    sb.append("callsite: I" + callsite + "\n");
+                }
+            }
+            if (expected != -1) {
+                if (hier.isClass(expected)) {
+                    sb.append("expected: C" + expected + "\n");
+                } else {
+                    sb.append("expected: I" + expected + "\n");
+                }
+            }
+            sb.append("result: " + result + "\n");
+            sb.append("classes:\n\n");
+
+            for(int i = 0; classdata.containsKey(i); i++) {
+                final ClassData cd = classdata.get(i);
+
+                if (hier.isClass(i)) {
+                    sb.append("class ");
+                    addPackage(sb, cd);
+                    sb.append("C" + i);
+                } else {
+                    sb.append("interface ");
+                    addPackage(sb, cd);
+                    sb.append("I" + i);
+                }
+
+                boolean first = true;
+                for(final int j : hier.classes()) {
+                    if (hier.inherits(i, j)) {
+                        if (first) {
+                            sb.append(" extends C" + j);
+                        } else {
+                            sb.append(", C" + j);
+                        }
+                    }
+                }
+
+                first = true;
+                for(final int j : hier.interfaces()) {
+                    if (hier.inherits(i, j)) {
+                        if (first) {
+                            sb.append(" implements I" + j);
+                        } else {
+                            sb.append(", I" + j);
+                        }
+                    }
+                }
+
+                sb.append(cd);
+            }
+
+            return sb.toString();
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/SelectionResolution/classes/selectionresolution/Template.java	Sat Apr 02 05:39:25 2016 +0200
@@ -0,0 +1,5005 @@
+/*
+ * 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.
+ */
+
+package selectionresolution;
+
+import java.util.function.BiConsumer;
+import java.util.function.Consumer;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.EnumSet;
+import java.util.HashSet;
+import java.util.LinkedList;
+
+/**
+ * Templates are sets of transformations that are applied to a
+ * SelectionResolutionTestCase.Builder as part of building up a test
+ * case.  Templates should contain a collection of different
+ * transforms, all of which represent an "interesting" case in a
+ * general category of cases.
+ *
+ */
+public class Template {
+
+    public enum Kind { CLASS, INTERFACE; }
+
+    public final Collection<Consumer<SelectionResolutionTestCase.Builder>> cases;
+    public final String name;
+
+    /**
+     * Create a template from a collection of lambdas that modify a Builder.
+     *
+     * @param name The name of the template.
+     * @param cases The cases in the template.
+     */
+    public Template(final String name,
+                    final Collection<Consumer<SelectionResolutionTestCase.Builder>> cases) {
+        this.cases = cases;
+        this.name = name;
+    }
+
+    /**
+     * Build a template out of a set of lambdas that modify a Builder.
+     *
+     * @param name The name of the template.
+     * @param cases The cases in the template.
+     */
+    public Template(final String name,
+                    final Consumer<SelectionResolutionTestCase.Builder>... cases) {
+        this(name, Arrays.asList(cases));
+    }
+
+    /**
+     * Build a template out of a set of lambdas that modify a Builder.
+     * Also include all cases from another template.
+     *
+     * @param name The name of the template.
+     * @param include Include all cases from this template.
+     * @param cases The cases in the template.
+     */
+    public Template(final String name,
+                    final Template include,
+                    final Consumer<SelectionResolutionTestCase.Builder>... cases) {
+        this(name, new LinkedList(include.cases));
+        this.cases.addAll(Arrays.asList(cases));
+    }
+
+    /**
+     * Build a template out of a set of lambdas that modify a Builder.
+     * Also include all cases from another template.
+     *
+     * @param name The name of the template.
+     * @param include Include all cases from this template.
+     * @param cases The cases in the template.
+     */
+    public Template(final String name,
+                    final Template... others) {
+        this(name, new LinkedList());
+
+        for(final Template template : others) {
+            cases.addAll(template.cases);
+        }
+    }
+
+    /**
+     * Run all cases in the template.  This will run each action in
+     * the template and then call the next action on a separate copy
+     * of the builder parameter.
+     *
+     * @param The next action to perform of the Builder.
+     * @param The Builder to modify.
+     */
+    public void runCases(final Consumer<SelectionResolutionTestCase.Builder> next,
+                         final SelectionResolutionTestCase.Builder builder) {
+        for(final Consumer<SelectionResolutionTestCase.Builder> thiscase : cases) {
+            final SelectionResolutionTestCase.Builder localbuilder = builder.copy();
+            thiscase.accept(localbuilder);
+            next.accept(localbuilder);
+        }
+    }
+
+    public void printCases(final SelectionResolutionTestCase.Builder builder) {
+        int i = 1;
+        System.err.println("Template " + name + ":\n");
+        for(final Consumer<SelectionResolutionTestCase.Builder> thiscase : cases) {
+            final SelectionResolutionTestCase.Builder localbuilder = builder.copy();
+            thiscase.accept(localbuilder);
+            System.err.println("Case " + i++);
+            System.err.println(localbuilder);
+        }
+    }
+
+    /* Create an empty class in the given package */
+    public static final ClassData emptyClass(final ClassData.Package pck) {
+        return new ClassData(pck, null);
+    }
+
+    /* These are functions that are used to build callsite templates */
+    public static void callsiteIsMethodref(final SelectionResolutionTestCase.Builder builder) {
+        builder.callsite = builder.methodref;
+    }
+
+    public static void callsiteSubclassMethodref(final SelectionResolutionTestCase.Builder builder) {
+        final int callsite =
+            builder.addClass(Template.emptyClass(ClassData.Package.SAME));
+        builder.hier.addInherit(callsite, builder.methodref);
+        builder.callsite = callsite;
+    }
+
+    public static void callsiteUnrelatedMethodref(final SelectionResolutionTestCase.Builder builder) {
+        final int callsite =
+            builder.addClass(Template.emptyClass(ClassData.Package.SAME));
+        builder.callsite = callsite;
+    }
+
+    public static void methodrefIsExpected(final SelectionResolutionTestCase.Builder builder) {
+        builder.methodref = builder.expected;
+    }
+
+    public static final Template MethodrefEqualsExpected =
+        new Template("MethodrefEqualsExpected",
+                     Template::methodrefIsExpected);
+
+    /*****************************
+     *    Set Invoke Template    *
+     *****************************/
+
+    public static final Template SetInvoke(final SelectionResolutionTestCase.InvokeInstruction invoke) {
+        return new Template("SetInvoke(" + invoke + ")",
+                            Collections.singleton((builder) -> {
+                                    builder.invoke = invoke;
+                                }));
+    }
+
+    /*****************************
+     *   Result Combo Template   *
+     *****************************/
+    public static Template ResultCombo(final EnumSet<Kind> kinds,
+                                       final EnumSet<MethodData.Access> accesses,
+                                       final EnumSet<MethodData.Context> contexts,
+                                       final EnumSet<ClassData.Package> packages) {
+        final LinkedList<Consumer<SelectionResolutionTestCase.Builder>> cases =
+            new LinkedList<>();
+
+        for (final Kind kind : kinds) {
+            for (final MethodData.Access acc : accesses) {
+                for (final MethodData.Context ctx : contexts) {
+                    if (!(acc == MethodData.Access.PRIVATE &&
+                          ctx == MethodData.Context.ABSTRACT)) {
+                        for (final ClassData.Package pck : packages) {
+                            cases.add((builder) -> {
+                                    final MethodData meth = new MethodData(acc, ctx);
+                                    final ClassData cls = new ClassData(pck, meth);
+                                    switch(kind) {
+                                    case CLASS:
+                                        builder.expected = builder.addClass(cls);
+                                        break;
+                                    case INTERFACE:
+                                        builder.expected = builder.addInterface(cls);
+                                        break;
+                                    }
+                                });
+                        }
+                    }
+                }
+            }
+        }
+
+        return new Template("ResultCombo", cases);
+    }
+
+    public static Template ResolutionOverride(final EnumSet<Kind> kinds,
+                                              final EnumSet<MethodData.Access> accesses,
+                                              final EnumSet<MethodData.Context> contexts,
+                                              final EnumSet<ClassData.Package> packages) {
+        final LinkedList<Consumer<SelectionResolutionTestCase.Builder>> cases =
+            new LinkedList<>();
+
+        for (final Kind kind : kinds) {
+            for (final MethodData.Access acc : accesses) {
+                for (final MethodData.Context ctx : contexts) {
+                    if (!(acc == MethodData.Access.PRIVATE &&
+                          ctx == MethodData.Context.ABSTRACT)) {
+                        for (final ClassData.Package pck : packages) {
+                            cases.add((builder) -> {
+                                    final MethodData meth = new MethodData(acc, ctx);
+                                    final ClassData cls = new ClassData(pck, meth);
+                                    int override = -1;
+                                    switch(kind) {
+                                    case CLASS:
+                                        override = builder.addClass(cls);
+                                        break;
+                                    case INTERFACE:
+                                        override = builder.addInterface(cls);
+                                        break;
+                                    }
+                                    builder.hier.addInherit(override, builder.expected);
+                                });
+                        }
+                    }
+                }
+            }
+        }
+
+        return new Template("ResultCombo", cases);
+    }
+
+    /******************************
+     *    Resolution Templates    *
+     ******************************/
+
+    private static MethodData getMethodData(final MethodData.Access acc,
+                                            final MethodData.Context ctx) {
+        if (!(acc == MethodData.Access.PUBLIC ||
+              acc == MethodData.Access.PLACEHOLDER) &&
+            ctx != MethodData.Context.STATIC) {
+            return null;
+        } else {
+            return new MethodData(MethodData.Access.PUBLIC, ctx);
+        }
+    }
+
+    public static final Template MethodrefNotEqualsExpectedClass =
+        new Template("MethodrefNotEqualsExpectedClass",
+                     /* Case 1: Inherit from super.
+                      *
+                      * C2[](res)
+                      * C1[C2]() = mref
+                      */
+                     (final SelectionResolutionTestCase.Builder builder) -> {
+                         final int C2 = builder.expected;
+                         final int C1 = builder.addClass(emptyClass(ClassData.Package.SAME));
+                         builder.hier.addInherit(C1, C2);
+                         builder.methodref = C1;
+                     },
+                     /* Case 2: Inherit from super.
+                      *
+                      * C2[](res), I[](def)
+                      * C1[C2,I]() = mref
+                      */
+                     (final SelectionResolutionTestCase.Builder builder) -> {
+                         final ClassData.Package pck =
+                             builder.classdata.get(builder.expected).packageId;
+                         final MethodData.Context ctx =
+                             builder.classdata.get(builder.expected).methoddata.context;
+                         final MethodData.Access acc =
+                             builder.classdata.get(builder.expected).methoddata.access;
+                         final MethodData mdata = getMethodData(acc, ctx);
+                         final ClassData withDef = new ClassData(pck, mdata);
+                         final int C2 = builder.expected;
+                         final int C1 = builder.addClass(emptyClass(ClassData.Package.SAME));
+                         final int I = builder.addInterface(withDef);
+                         builder.hier.addInherit(C1, C2);
+                         builder.hier.addInherit(C1, I);
+                         builder.methodref = C1;
+                     },
+                     /* Case 3: Inherit from super's super.
+                      *
+                      * C3[](res)
+                      * C2[](), I[](def)
+                      * C1[C2,I]() = mref
+                      */
+                     (final SelectionResolutionTestCase.Builder builder) -> {
+                         final ClassData.Package pck =
+                             builder.classdata.get(builder.expected).packageId;
+                         final MethodData.Context ctx =
+                             builder.classdata.get(builder.expected).methoddata.context;
+                         final MethodData.Access acc =
+                             builder.classdata.get(builder.expected).methoddata.access;
+                         final MethodData mdata = getMethodData(acc, ctx);
+                         final ClassData withDef = new ClassData(pck, mdata);
+                         final int C3 = builder.expected;
+                         final int C2 = builder.addClass(emptyClass(pck));
+                         final int C1 = builder.addClass(emptyClass(ClassData.Package.SAME));
+                         final int I = builder.addInterface(withDef);
+                         builder.hier.addInherit(C2, C3);
+                         builder.hier.addInherit(C1, C2);
+                         builder.hier.addInherit(C1, I);
+                         builder.methodref = C1;
+                     });
+
+    public static final Template IfaceMethodrefNotEqualsExpected =
+        new Template("IfaceMethodrefNotEqualsExpected",
+                     /* Case 1: Inherit from super.
+                      *
+                      * I2[](res)
+                      * I1[I2]() = mref
+                      */
+                     (final SelectionResolutionTestCase.Builder builder) -> {
+                         final ClassData.Package pck =
+                             builder.classdata.get(builder.expected).packageId;
+                         final int I2 = builder.expected;
+                         final int I1 = builder.addInterface(emptyClass(pck));
+                         builder.hier.addInherit(I1, I2);
+                         builder.methodref = I1;
+                     },
+                     /* Case 2: Inherit from super, skip private.
+                      *
+                      * I2[](res)
+                      * I2[I3](priv)
+                      * I1[I2]() = mref
+                      */
+                     (final SelectionResolutionTestCase.Builder builder) -> {
+                         final ClassData.Package pck =
+                             builder.classdata.get(builder.expected).packageId;
+                         final MethodData meth =
+                             new MethodData(MethodData.Access.PRIVATE,
+                                            MethodData.Context.INSTANCE);
+                         final ClassData withPrivDef = new ClassData(pck, meth);
+                         final int I3 = builder.expected;
+                         final int I2 = builder.addInterface(withPrivDef);
+                         final int I1 = builder.addInterface(emptyClass(pck));
+                         builder.hier.addInherit(I1, I2);
+                         builder.hier.addInherit(I2, I3);
+                         builder.methodref = I1;
+                     },
+                     /* Case 3: Inherit from super, skip static.
+                      *
+                      * I2[](res)
+                      * I2[I3](stat)
+                      * I1[I2]() = mref
+                      */
+                     (final SelectionResolutionTestCase.Builder builder) -> {
+                         final ClassData.Package pck =
+                             builder.classdata.get(builder.expected).packageId;
+                         final MethodData meth =
+                             new MethodData(MethodData.Access.PUBLIC,
+                                            MethodData.Context.STATIC);
+                         final ClassData withStatDef = new ClassData(pck, meth);
+                         final int I3 = builder.expected;
+                         final int I2 = builder.addInterface(withStatDef);
+                         final int I1 = builder.addInterface(emptyClass(pck));
+                         builder.hier.addInherit(I1, I2);
+                         builder.hier.addInherit(I2, I3);
+                         builder.methodref = I1;
+                     },
+                     /* Case 4: Maximally-specific.
+                      *
+                      * I3[](def)
+                      * I2[I3](res)
+                      * I1[I2]() = mref
+                      */
+                     (final SelectionResolutionTestCase.Builder builder) -> {
+                         final ClassData.Package pck =
+                             builder.classdata.get(builder.expected).packageId;
+                         final MethodData.Context ctx =
+                             builder.classdata.get(builder.expected).methoddata.context;
+                         final MethodData.Access acc =
+                             builder.classdata.get(builder.expected).methoddata.access;
+                         final MethodData mdata = getMethodData(acc, ctx);
+                         final ClassData withDef = new ClassData(pck, mdata);
+                         final int I3 = builder.addInterface(withDef);
+                         final int I2 = builder.expected;
+                         final int I1 = builder.addInterface(emptyClass(pck));
+                         builder.hier.addInherit(I1, I2);
+                         builder.hier.addInherit(I2, I3);
+                         builder.methodref = I1;
+                     },
+                     /* Case 5: Diamond, expected at top.
+                      *
+                      * I4[](res)
+                      * I2[I4](), I3[I4]()
+                      * I1[I2,I3]() = mref
+                      */
+                     (final SelectionResolutionTestCase.Builder builder) -> {
+                         final ClassData.Package pck =
+                             builder.classdata.get(builder.expected).packageId;
+                         final int I4 = builder.expected;
+                         final int I3 = builder.addInterface(emptyClass(pck));
+                         final int I2 = builder.addInterface(emptyClass(pck));
+                         final int I1 = builder.addInterface(emptyClass(pck));
+                         builder.hier.addInherit(I1, I2);
+                         builder.hier.addInherit(I1, I3);
+                         builder.hier.addInherit(I2, I4);
+                         builder.hier.addInherit(I3, I4);
+                         builder.methodref = I1;
+                     },
+                     /* Case 6: Diamond, skip private.
+                      *
+                      * I4[](res)
+                      * I2[I4](priv), I3[I4]()
+                      * I1[I2,I3]() = mref
+                      */
+                     (final SelectionResolutionTestCase.Builder builder) -> {
+                         final ClassData.Package pck =
+                             builder.classdata.get(builder.expected).packageId;
+                         final MethodData.Context ctx =
+                             builder.classdata.get(builder.expected).methoddata.context;
+                         final MethodData.Access acc =
+                             builder.classdata.get(builder.expected).methoddata.access;
+                         final MethodData mdata = getMethodData(acc, ctx);
+                         final MethodData meth =
+                             new MethodData(MethodData.Access.PRIVATE,
+                                            MethodData.Context.INSTANCE);
+                         final ClassData withPrivDef = new ClassData(pck, meth);
+                         final int I4 = builder.expected;
+                         final int I3 = builder.addInterface(emptyClass(pck));
+                         final int I2 = builder.addInterface(withPrivDef);
+                         final int I1 = builder.addInterface(emptyClass(pck));
+                         builder.hier.addInherit(I1, I2);
+                         builder.hier.addInherit(I1, I3);
+                         builder.hier.addInherit(I2, I4);
+                         builder.hier.addInherit(I3, I4);
+                         builder.methodref = I1;
+                     },
+                     /* Case 7: Diamond, skip static.
+                      *
+                      * I4[](res)
+                      * I2[I4](stat), I3[I4]()
+                      * I1[I2,I3]() = mref
+                      */
+                     (final SelectionResolutionTestCase.Builder builder) -> {
+                         final ClassData.Package pck =
+                             builder.classdata.get(builder.expected).packageId;
+                         final MethodData.Context ctx =
+                             builder.classdata.get(builder.expected).methoddata.context;
+                         final MethodData.Access acc =
+                             builder.classdata.get(builder.expected).methoddata.access;
+                         final MethodData mdata = getMethodData(acc, ctx);
+                         final MethodData meth =
+                             new MethodData(MethodData.Access.PUBLIC,
+                                            MethodData.Context.STATIC);
+                         final ClassData withStatDef = new ClassData(pck, meth);
+                         final int I4 = builder.expected;
+                         final int I3 = builder.addInterface(emptyClass(pck));
+                         final int I2 = builder.addInterface(withStatDef);
+                         final int I1 = builder.addInterface(emptyClass(pck));
+                         builder.hier.addInherit(I1, I2);
+                         builder.hier.addInherit(I1, I3);
+                         builder.hier.addInherit(I2, I4);
+                         builder.hier.addInherit(I3, I4);
+                         builder.methodref = I1;
+                     },
+                     /* Case 8: Diamond, maximally-specific.
+                      *
+                      * I4[](def)
+                      * I2[I4](res), I3[I4]()
+                      * I1[I2,I3]() = mref
+                      */
+                     (final SelectionResolutionTestCase.Builder builder) -> {
+                         final ClassData.Package pck =
+                             builder.classdata.get(builder.expected).packageId;
+                         final MethodData.Context ctx =
+                             builder.classdata.get(builder.expected).methoddata.context;
+                         final MethodData.Access acc =
+                             builder.classdata.get(builder.expected).methoddata.access;
+                         final MethodData mdata = getMethodData(acc, ctx);
+                         final ClassData withDef = new ClassData(pck, mdata);
+                         final int I4 = builder.addInterface(withDef);
+                         final int I3 = builder.addInterface(emptyClass(pck));
+                         final int I2 = builder.expected;
+                         final int I1 = builder.addInterface(emptyClass(pck));
+                         builder.hier.addInherit(I1, I2);
+                         builder.hier.addInherit(I1, I3);
+                         builder.hier.addInherit(I2, I4);
+                         builder.hier.addInherit(I3, I4);
+                         builder.methodref = I1;
+                     },
+                     /* Case 9: Diamond, maximally-specific, skipping private.
+                      *
+                      * I4[](def)
+                      * I2[I4](res), I3[I4](priv)
+                      * I1[I2,I3]() = mref
+                      */
+                     (final SelectionResolutionTestCase.Builder builder) -> {
+                         final ClassData.Package pck =
+                             builder.classdata.get(builder.expected).packageId;
+                         final MethodData.Context ctx =
+                             builder.classdata.get(builder.expected).methoddata.context;
+                         final MethodData.Access acc =
+                             builder.classdata.get(builder.expected).methoddata.access;
+                         final MethodData mdata = getMethodData(acc, ctx);
+                         final ClassData withDef = new ClassData(pck, mdata);
+                         final MethodData meth =
+                             new MethodData(MethodData.Access.PRIVATE,
+                                            MethodData.Context.INSTANCE);
+                         final ClassData withPrivDef = new ClassData(pck, meth);
+                         final int I4 = builder.addInterface(withDef);
+                         final int I3 = builder.addInterface(withPrivDef);
+                         final int I2 = builder.expected;
+                         final int I1 = builder.addInterface(emptyClass(pck));
+                         builder.hier.addInherit(I1, I2);
+                         builder.hier.addInherit(I1, I3);
+                         builder.hier.addInherit(I2, I4);
+                         builder.hier.addInherit(I3, I4);
+                         builder.methodref = I1;
+                     },
+                     /* Case 10: Diamond, maximally-specific, skipping static.
+                      *
+                      * I4[](def)
+                      * I2[I4](res), I3[I4](stat)
+                      * I1[I2,I3]() = mref
+                      */
+                     (final SelectionResolutionTestCase.Builder builder) -> {
+                         final ClassData.Package pck =
+                             builder.classdata.get(builder.expected).packageId;
+                         final MethodData.Context ctx =
+                             builder.classdata.get(builder.expected).methoddata.context;
+                         final MethodData.Access acc =
+                             builder.classdata.get(builder.expected).methoddata.access;
+                         final MethodData mdata = getMethodData(acc, ctx);
+                         final ClassData withDef = new ClassData(pck, mdata);
+                         final MethodData meth =
+                             new MethodData(MethodData.Access.PUBLIC,
+                                            MethodData.Context.STATIC);
+                         final ClassData withStatDef = new ClassData(pck, meth);
+                         final int I4 = builder.addInterface(withDef);
+                         final int I3 = builder.addInterface(withStatDef);
+                         final int I2 = builder.expected;
+                         final int I1 = builder.addInterface(emptyClass(pck));
+                         builder.hier.addInherit(I1, I2);
+                         builder.hier.addInherit(I1, I3);
+                         builder.hier.addInherit(I2, I4);
+                         builder.hier.addInherit(I3, I4);
+                         builder.methodref = I1;
+                     });
+
+    public static final Template MethodrefNotEqualsExpectedIface =
+        new Template("MethodrefNotEqualsExpectedIface",
+                    /* Case 1: Inherit from superinterface.
+                     *
+                     * I[](res)
+                     * C[I]() = mref
+                     */
+                    (final SelectionResolutionTestCase.Builder builder) -> {
+                        final ClassData.Package pck =
+                            builder.classdata.get(builder.expected).packageId;
+                        final int I = builder.expected;
+                        final int C = builder.addClass(emptyClass(pck));
+                        builder.hier.addInherit(C, I);
+                        builder.methodref = C;
+                     },
+                     /* Case 2: Diamond, expected at top.
+                      *
+                      * I3[](res)
+                      * I1[I3](), I2[I3]()
+                      * C[I1,I2]() = mref
+                      */
+                     (final SelectionResolutionTestCase.Builder builder) -> {
+                         final ClassData.Package pck =
+                             builder.classdata.get(builder.expected).packageId;
+                         final int I3 = builder.expected;
+                         final int I2 = builder.addInterface(emptyClass(pck));
+                         final int I1 = builder.addInterface(emptyClass(pck));
+                         final int C = builder.addClass(emptyClass(pck));
+                         builder.hier.addInherit(C, I1);
+                         builder.hier.addInherit(C, I2);
+                         builder.hier.addInherit(I1, I3);
+                         builder.hier.addInherit(I2, I3);
+                         builder.methodref = C;
+                     },
+                     /* Case 3: Diamond, skipping private.
+                      *
+                      * I3[](def)
+                      * I1[I3](priv), I2[I3]()
+                      * C[I1,I2]() = mref
+                      */
+                     (final SelectionResolutionTestCase.Builder builder) -> {
+                         final ClassData.Package pck =
+                             builder.classdata.get(builder.expected).packageId;
+                         final MethodData.Context ctx =
+                             builder.classdata.get(builder.expected).methoddata.context;
+                         final MethodData.Access acc =
+                             builder.classdata.get(builder.expected).methoddata.access;
+                         final MethodData meth =
+                             new MethodData(MethodData.Access.PRIVATE,
+                                            MethodData.Context.INSTANCE);
+                         final ClassData withPrivDef = new ClassData(pck, meth);
+                         final int I3 = builder.expected;
+                         final int I2 = builder.addInterface(emptyClass(pck));
+                         final int I1 = builder.addInterface(withPrivDef);
+                         final int C = builder.addClass(emptyClass(pck));
+                         builder.hier.addInherit(C, I1);
+                         builder.hier.addInherit(C, I2);
+                         builder.hier.addInherit(I1, I3);
+                         builder.hier.addInherit(I2, I3);
+                         builder.methodref = C;
+                     },
+                     /* Case 4: Diamond, skipping static.
+                      *
+                      * I3[](def)
+                      * I1[I3](stat), I2[I3]()
+                      * C[I1,I2]() = mref
+                      */
+                     (final SelectionResolutionTestCase.Builder builder) -> {
+                         final ClassData.Package pck =
+                             builder.classdata.get(builder.expected).packageId;
+                         final MethodData.Context ctx =
+                             builder.classdata.get(builder.expected).methoddata.context;
+                         final MethodData.Access acc =
+                             builder.classdata.get(builder.expected).methoddata.access;
+                         final MethodData meth =
+                             new MethodData(MethodData.Access.PUBLIC,
+                                            MethodData.Context.STATIC);
+                         final ClassData withStatDef = new ClassData(pck, meth);
+                         final int I3 = builder.expected;
+                         final int I2 = builder.addInterface(emptyClass(pck));
+                         final int I1 = builder.addInterface(withStatDef);
+                         final int C = builder.addClass(emptyClass(pck));
+                         builder.hier.addInherit(C, I1);
+                         builder.hier.addInherit(C, I2);
+                         builder.hier.addInherit(I1, I3);
+                         builder.hier.addInherit(I2, I3);
+                         builder.methodref = C;
+                     },
+                     /* Case 5: Diamond, maximally-specific.
+                      *
+                      * I3[](def)
+                      * I1[I3](res), I2[I3]()
+                      * C[I1,I2]() = mref
+                      */
+                     (final SelectionResolutionTestCase.Builder builder) -> {
+                         final ClassData.Package pck =
+                             builder.classdata.get(builder.expected).packageId;
+                         final MethodData.Context ctx =
+                             builder.classdata.get(builder.expected).methoddata.context;
+                         final MethodData.Access acc =
+                             builder.classdata.get(builder.expected).methoddata.access;
+                         final MethodData mdata = getMethodData(acc, ctx);
+                         final ClassData withDef = new ClassData(pck, mdata);
+                         final int I3 = builder.addInterface(withDef);
+                         final int I2 = builder.addInterface(emptyClass(pck));
+                         final int I1 = builder.expected;
+                         final int C = builder.addClass(emptyClass(pck));
+                         builder.hier.addInherit(C, I1);
+                         builder.hier.addInherit(C, I2);
+                         builder.hier.addInherit(I1, I3);
+                         builder.hier.addInherit(I2, I3);
+                         builder.methodref = C;
+                     },
+                     /* Case 6: Diamond, maximally-specific, skipping private.
+                      *
+                      * I3[](def)
+                      * I1[I3](res), I2[I3](priv)
+                      * C[I1,I2]() = mref
+                      */
+                     (final SelectionResolutionTestCase.Builder builder) -> {
+                         final ClassData.Package pck =
+                             builder.classdata.get(builder.expected).packageId;
+                         final MethodData.Context ctx =
+                             builder.classdata.get(builder.expected).methoddata.context;
+                         final MethodData.Access acc =
+                             builder.classdata.get(builder.expected).methoddata.access;
+                         final MethodData mdata = getMethodData(acc, ctx);
+                         final ClassData withDef = new ClassData(pck, mdata);
+                         final MethodData meth =
+                             new MethodData(MethodData.Access.PRIVATE,
+                                            MethodData.Context.INSTANCE);
+                         final ClassData withPrivDef = new ClassData(pck, meth);
+                         final int I3 = builder.addInterface(withDef);
+                         final int I2 = builder.addInterface(withPrivDef);
+                         final int I1 = builder.expected;
+                         final int C = builder.addClass(emptyClass(pck));
+                         builder.hier.addInherit(C, I1);
+                         builder.hier.addInherit(C, I2);
+                         builder.hier.addInherit(I1, I3);
+                         builder.hier.addInherit(I2, I3);
+                         builder.methodref = C;
+                     },
+                     /* Case 7: Diamond, maximally-specific, skipping static.
+                      *
+                      * I3[](def)
+                      * I1[I3](res), I2[I3](stat)
+                      * C[I1,I2]() = mref
+                      */
+                     (final SelectionResolutionTestCase.Builder builder) -> {
+                         final ClassData.Package pck =
+                             builder.classdata.get(builder.expected).packageId;
+                         final MethodData.Context ctx =
+                             builder.classdata.get(builder.expected).methoddata.context;
+                         final MethodData.Access acc =
+                             builder.classdata.get(builder.expected).methoddata.access;
+                         final MethodData mdata = getMethodData(acc, ctx);
+                         final ClassData withDef = new ClassData(pck, mdata);
+                         final MethodData meth =
+                             new MethodData(MethodData.Access.PUBLIC,
+                                            MethodData.Context.STATIC);
+                         final ClassData withStatDef = new ClassData(pck, meth);
+                         final int I3 = builder.addInterface(withDef);
+                         final int I2 = builder.addInterface(withStatDef);
+                         final int I1 = builder.expected;
+                         final int C = builder.addClass(emptyClass(pck));
+                         builder.hier.addInherit(C, I1);
+                         builder.hier.addInherit(C, I2);
+                         builder.hier.addInherit(I1, I3);
+                         builder.hier.addInherit(I2, I3);
+                         builder.methodref = C;
+                     },
+                     /* Case 8: Diamond, with superclass, expected at top.
+                      *
+                      * I2[](res)
+                      * C2[I2](), I1[I2]()
+                      * C1[I1,C2]() = mref
+                      */
+                     (final SelectionResolutionTestCase.Builder builder) -> {
+                         final ClassData.Package pck =
+                             builder.classdata.get(builder.expected).packageId;
+                         final int I2 = builder.expected;
+                         final int I1 = builder.addInterface(emptyClass(pck));
+                         final int C2 = builder.addInterface(emptyClass(pck));
+                         final int C1 = builder.addClass(emptyClass(pck));
+                         builder.hier.addInherit(C1, I1);
+                         builder.hier.addInherit(C1, C2);
+                         builder.hier.addInherit(I1, I2);
+                         builder.hier.addInherit(C2, I2);
+                         builder.methodref = C1;
+                     },
+                     /* Case 9: Diamond with superclass, maximally-specific.
+                      *
+                      * I2[](def)
+                      * C2[I2](), I1[I2](res),
+                      * C1[I1,C2]() = mref
+                      */
+                     (final SelectionResolutionTestCase.Builder builder) -> {
+                         final ClassData.Package pck =
+                             builder.classdata.get(builder.expected).packageId;
+                         final MethodData.Context ctx =
+                             builder.classdata.get(builder.expected).methoddata.context;
+                         final MethodData.Access acc =
+                             builder.classdata.get(builder.expected).methoddata.access;
+                         final MethodData mdata = getMethodData(acc, ctx);
+                         final ClassData withDef = new ClassData(pck, mdata);
+                         final int I2 = builder.addInterface(withDef);
+                         final int C2 = builder.addClass(emptyClass(pck));
+                         final int I1 = builder.expected;
+                         final int C1 = builder.addClass(emptyClass(pck));
+                         builder.hier.addInherit(C1, I1);
+                         builder.hier.addInherit(C1, C2);
+                         builder.hier.addInherit(I1, I2);
+                         builder.hier.addInherit(C2, I2);
+                         builder.methodref = C1;
+                     },
+                     /* Case 10: Inherit through superclass.
+                      *
+                      * I[](res)
+                      * C2[I]()
+                      * C1[C2]() = mref
+                      */
+                     (final SelectionResolutionTestCase.Builder builder) -> {
+                         final ClassData.Package pck =
+                             builder.classdata.get(builder.expected).packageId;
+                         final int I = builder.expected;
+                         final int C2 = builder.addInterface(emptyClass(pck));
+                         final int C1 = builder.addClass(emptyClass(pck));
+                         builder.hier.addInherit(C1, I);
+                         builder.hier.addInherit(C1, C2);
+                         builder.hier.addInherit(C2, I);
+                         builder.methodref = C1;
+                     },
+                     /* Case 11: Diamond, inherit through superclass,
+                      * expected at top.
+                      *
+                      * I3[](res)
+                      * I1[I3](), I2[I3]()
+                      * C2[I1,I2]()
+                      * C1[C2]() = mref
+                      */
+                     (final SelectionResolutionTestCase.Builder builder) -> {
+                         final ClassData.Package pck =
+                             builder.classdata.get(builder.expected).packageId;
+                         final int I3 = builder.expected;
+                         final int I2 = builder.addInterface(emptyClass(pck));
+                         final int I1 = builder.addInterface(emptyClass(pck));
+                         final int C2 = builder.addClass(emptyClass(pck));
+                         final int C1 = builder.addClass(emptyClass(pck));
+                         builder.hier.addInherit(C2, I1);
+                         builder.hier.addInherit(C2, I2);
+                         builder.hier.addInherit(I1, I3);
+                         builder.hier.addInherit(I2, I3);
+                         builder.hier.addInherit(C1, C2);
+                         builder.methodref = C1;
+                     },
+                     /* Case 12: Diamond through superclass, skip private.
+                      *
+                      * I3[](res)
+                      * I1[I3](priv), I2[I3]()
+                      * C2[I1,I2]()
+                      * C1[C2]() = mref
+                      */
+                     (final SelectionResolutionTestCase.Builder builder) -> {
+                         final ClassData.Package pck =
+                             builder.classdata.get(builder.expected).packageId;
+                         final MethodData.Context ctx =
+                             builder.classdata.get(builder.expected).methoddata.context;
+                         final MethodData.Access acc =
+                             builder.classdata.get(builder.expected).methoddata.access;
+                         final MethodData mdata = getMethodData(acc, ctx);
+                         final ClassData withDef = new ClassData(pck, mdata);
+                         final MethodData meth =
+                             new MethodData(MethodData.Access.PRIVATE,
+                                            MethodData.Context.INSTANCE);
+                         final ClassData withPrivDef = new ClassData(pck, meth);
+                         final int I3 = builder.expected;
+                         final int I2 = builder.addInterface(emptyClass(pck));
+                         final int I1 = builder.addInterface(withPrivDef);
+                         final int C2 = builder.addClass(emptyClass(pck));
+                         final int C1 = builder.addClass(emptyClass(pck));
+                         builder.hier.addInherit(C2, I1);
+                         builder.hier.addInherit(C2, I2);
+                         builder.hier.addInherit(I1, I3);
+                         builder.hier.addInherit(I2, I3);
+                         builder.hier.addInherit(C1, C2);
+                         builder.methodref = C1;
+                     },
+                     /* Case 13: Diamond through superclass, skip static.
+                      *
+                      * I3[](def)
+                      * I1[I3](stat), I2[I3]()
+                      * C2[I1,I2]()
+                      * C1[C2]() = mref
+                      */
+                     (final SelectionResolutionTestCase.Builder builder) -> {
+                         final ClassData.Package pck =
+                             builder.classdata.get(builder.expected).packageId;
+                         final MethodData.Context ctx =
+                             builder.classdata.get(builder.expected).methoddata.context;
+                         final MethodData.Access acc =
+                             builder.classdata.get(builder.expected).methoddata.access;
+                         final MethodData mdata = getMethodData(acc, ctx);
+                         final ClassData withDef = new ClassData(pck, mdata);
+                         final MethodData meth =
+                             new MethodData(MethodData.Access.PUBLIC,
+                                            MethodData.Context.STATIC);
+                         final ClassData withStatDef = new ClassData(pck, meth);
+                         final int I3 = builder.expected;
+                         final int I2 = builder.addInterface(emptyClass(pck));
+                         final int I1 = builder.addInterface(withStatDef);
+                         final int C2 = builder.addClass(emptyClass(pck));
+                         final int C1 = builder.addClass(emptyClass(pck));
+                         builder.hier.addInherit(C2, I1);
+                         builder.hier.addInherit(C2, I2);
+                         builder.hier.addInherit(I1, I3);
+                         builder.hier.addInherit(I2, I3);
+                         builder.hier.addInherit(C1, C2);
+                         builder.methodref = C1;
+                     },
+                     /* Case 14: Diamond through superclass, maximally-specific.
+                      *
+                      * I3[](def)
+                      * I1[I3](res), I2[I3]()
+                      * C2[I1,I2]()
+                      * C1[C2]() = mref
+                      */
+                     (final SelectionResolutionTestCase.Builder builder) -> {
+                         final ClassData.Package pck =
+                             builder.classdata.get(builder.expected).packageId;
+                         final MethodData.Context ctx =
+                             builder.classdata.get(builder.expected).methoddata.context;
+                         final MethodData.Access acc =
+                             builder.classdata.get(builder.expected).methoddata.access;
+                         final MethodData mdata = getMethodData(acc, ctx);
+                         final ClassData withDef = new ClassData(pck, mdata);
+                         final int I3 = builder.addInterface(withDef);
+                         final int I2 = builder.addInterface(emptyClass(pck));
+                         final int I1 = builder.expected;
+                         final int C2 = builder.addClass(emptyClass(pck));
+                         final int C1 = builder.addClass(emptyClass(pck));
+                         builder.hier.addInherit(C2, I1);
+                         builder.hier.addInherit(C2, I2);
+                         builder.hier.addInherit(I1, I3);
+                         builder.hier.addInherit(I2, I3);
+                         builder.hier.addInherit(C1, C2);
+                         builder.methodref = C1;
+                     },
+                     /* Case 15: Diamond through superclass,
+                      * maximally-specific, skip private.
+                      *
+                      * I3[](def)
+                      * I1[I3](res), I2[I3](priv)
+                      * C2[I1,I2]()
+                      * C1[C2]() = mref
+                      */
+                     (final SelectionResolutionTestCase.Builder builder) -> {
+                         final ClassData.Package pck =
+                             builder.classdata.get(builder.expected).packageId;
+                         final MethodData.Context ctx =
+                             builder.classdata.get(builder.expected).methoddata.context;
+                         final MethodData.Access acc =
+                             builder.classdata.get(builder.expected).methoddata.access;
+                         final MethodData mdata = getMethodData(acc, ctx);
+                         final ClassData withDef = new ClassData(pck, mdata);
+                         final MethodData meth =
+                             new MethodData(MethodData.Access.PRIVATE,
+                                            MethodData.Context.INSTANCE);
+                         final ClassData withPrivDef = new ClassData(pck, meth);
+                         final int I3 = builder.addInterface(withDef);
+                         final int I2 = builder.addInterface(withPrivDef);
+                         final int I1 = builder.expected;
+                         final int C2 = builder.addClass(emptyClass(pck));
+                         final int C1 = builder.addClass(emptyClass(pck));
+                         builder.hier.addInherit(C2, I1);
+                         builder.hier.addInherit(C2, I2);
+                         builder.hier.addInherit(I1, I3);
+                         builder.hier.addInherit(I2, I3);
+                         builder.hier.addInherit(C1, C2);
+                         builder.methodref = C1;
+                     },
+                     /* Case 16: Diamond through superclass,
+                      * maximally-specific, skip static.
+                      *
+                      * I3[](pub)
+                      * I1[I3](res), I2[I3](stat)
+                      * C2[I1,I2]()
+                      * C1[C2]() = mref
+                      */
+                     (final SelectionResolutionTestCase.Builder builder) -> {
+                         final ClassData.Package pck =
+                             builder.classdata.get(builder.expected).packageId;
+                         final MethodData.Context ctx =
+                             builder.classdata.get(builder.expected).methoddata.context;
+                         final MethodData.Access acc =
+                             builder.classdata.get(builder.expected).methoddata.access;
+                         final MethodData mdata = getMethodData(acc, ctx);
+                         final ClassData withDef = new ClassData(pck, mdata);
+                         final MethodData meth =
+                             new MethodData(MethodData.Access.PUBLIC,
+                                            MethodData.Context.STATIC);
+                         final ClassData withStatDef = new ClassData(pck, meth);
+                         final int I3 = builder.addInterface(withDef);
+                         final int I2 = builder.addInterface(withStatDef);
+                         final int I1 = builder.expected;
+                         final int C2 = builder.addClass(emptyClass(pck));
+                         final int C1 = builder.addClass(emptyClass(pck));
+                         builder.hier.addInherit(C2, I1);
+                         builder.hier.addInherit(C2, I2);
+                         builder.hier.addInherit(I1, I3);
+                         builder.hier.addInherit(I2, I3);
+                         builder.hier.addInherit(C1, C2);
+                         builder.methodref = C1;
+                     },
+                     /* Case 17: Diamond, with superclass, inherit through
+                      * superclass, expected at top.
+                      *
+                      * I2[](res)
+                      * C3[I2](), I1[I2]()
+                      * C2[I1,C3]()
+                      * C1[C2]() = mref
+                      */
+                     (final SelectionResolutionTestCase.Builder builder) -> {
+                         final ClassData.Package pck =
+                             builder.classdata.get(builder.expected).packageId;
+                         final int I2 = builder.expected;
+                         final int I1 = builder.addInterface(emptyClass(pck));
+                         final int C3 = builder.addInterface(emptyClass(pck));
+                         final int C2 = builder.addClass(emptyClass(pck));
+                         final int C1 = builder.addClass(emptyClass(pck));
+                         builder.hier.addInherit(C2, I1);
+                         builder.hier.addInherit(C2, C3);
+                         builder.hier.addInherit(I1, I2);
+                         builder.hier.addInherit(C3, I2);
+                         builder.hier.addInherit(C1, C2);
+                         builder.methodref = C1;
+                     },
+                     /* Case 18: Diamond, with superclass, inherit through
+                      * superclass, maximally-specific.
+                      *
+                      * I2[](def)
+                      * C3[I2](), I1[I2](res),
+                      * C2[I1,C3]()
+                      * C1[I1,C2]() = mref
+                      */
+                     (final SelectionResolutionTestCase.Builder builder) -> {
+                         final ClassData.Package pck =
+                             builder.classdata.get(builder.expected).packageId;
+                         final MethodData.Context ctx =
+                             builder.classdata.get(builder.expected).methoddata.context;
+                         final MethodData.Access acc =
+                             builder.classdata.get(builder.expected).methoddata.access;
+                         final MethodData mdata = getMethodData(acc, ctx);
+                         final ClassData withDef = new ClassData(pck, mdata);
+                         final int I2 = builder.addInterface(withDef);
+                         final int C3 = builder.addClass(emptyClass(pck));
+                         final int I1 = builder.expected;
+                         final int C2 = builder.addClass(emptyClass(pck));
+                         final int C1 = builder.addClass(emptyClass(pck));
+                         builder.hier.addInherit(C2, I1);
+                         builder.hier.addInherit(C2, C3);
+                         builder.hier.addInherit(I1, I2);
+                         builder.hier.addInherit(C3, I2);
+                         builder.hier.addInherit(C1, C2);
+                         builder.methodref = C1;
+                     });
+
+    public static final Template IfaceMethodrefAmbiguous =
+        new Template("IfaceMethodrefAmbiguous",
+                     /* Ambiguous.
+                      *
+                      * I2[](def), I3[](def)
+                      * I1[I2]() = mref
+                      */
+                     (final SelectionResolutionTestCase.Builder builder) -> {
+                         final ClassData.Package pck =
+                             builder.classdata.get(builder.expected).packageId;
+                         final ClassData expected =
+                             builder.classdata.get(builder.expected);
+                         final int I3 = builder.addInterface(expected);
+                         final int I2 = builder.expected;
+                         final int I1 = builder.addInterface(emptyClass(pck));
+                         builder.hier.addInherit(I1, I2);
+                         builder.hier.addInherit(I1, I3);
+                         builder.methodref = I1;
+                     });
+
+    public static final Template MethodrefAmbiguous =
+        new Template("MethodrefAmbiguous",
+                     /* Ambiguous.
+                      *
+                      * I1[](def), I2[](def)
+                      * C[I2]() = mref
+                      */
+                     (final SelectionResolutionTestCase.Builder builder) -> {
+                         final ClassData.Package pck =
+                             builder.classdata.get(builder.expected).packageId;
+                         final ClassData expected =
+                             builder.classdata.get(builder.expected);
+                         final int I1 = builder.addInterface(expected);
+                         final int I2 = builder.expected;
+                         final int C = builder.addClass(emptyClass(pck));
+                         builder.hier.addInherit(C, I2);
+                         builder.hier.addInherit(C, I1);
+                         builder.methodref = C;
+                     });
+
+    /******************************
+     *     Callsite Templates     *
+     ******************************/
+
+    public static final Template AllCallsiteCases =
+        new Template("AllCallsiteCases",
+                     Template::callsiteIsMethodref,
+                     Template::callsiteSubclassMethodref,
+                     Template::callsiteUnrelatedMethodref);
+
+    public static final Template InvokespecialCallsiteCases =
+        new Template("InvokespecialCallsiteCases",
+                     Template::callsiteIsMethodref,
+                     Template::callsiteSubclassMethodref);
+
+    public static final Template CallsiteEqualsMethodref =
+        new Template("CallsiteEqualsMethodref",
+                     Template::callsiteIsMethodref);
+
+    public static final Template CallsiteSubclassMethodref =
+        new Template("CallsiteSubclassMethodref",
+                     Template::callsiteSubclassMethodref);
+
+    public static final Template CallsiteUnrelatedToMethodref =
+        new Template("CallsiteUnrelatedToMethodref",
+                     Template::callsiteUnrelatedMethodref);
+
+    public static final Template CallsiteNotEqualsMethodref =
+        new Template("CallsiteNotEqualsMethodref",
+                     Template::callsiteSubclassMethodref,
+                     Template::callsiteUnrelatedMethodref);
+
+    /*********************************
+     * AbstractMethodError Templates *
+     *********************************/
+
+    public static final Template ReabstractExpectedIface =
+        new Template("ReabstractExpectedIface",
+                     (builder) -> {},
+                     (final SelectionResolutionTestCase.Builder builder) -> {
+                         final ClassData expected =
+                             builder.classdata.get(builder.expected);
+                         final ClassData.Package pck = expected.packageId;
+                         final MethodData.Access acc =
+                             builder.classdata.get(builder.expected).methoddata.access;
+                         final MethodData mdata =
+                             getMethodData(acc, MethodData.Context.STATIC);
+                         final ClassData withDef = new ClassData(pck, mdata);
+                         final int C2 = builder.addInterface(withDef);
+                         final int C1 = builder.expected;
+                         builder.hier.addInherit(C1, C2);
+                     },
+                     (final SelectionResolutionTestCase.Builder builder) -> {
+                         final ClassData expected =
+                             builder.classdata.get(builder.expected);
+                         final ClassData.Package pck = expected.packageId;
+                         final MethodData.Access acc =
+                             builder.classdata.get(builder.expected).methoddata.access;
+                         final MethodData mdata =
+                             getMethodData(acc, MethodData.Context.INSTANCE);
+                         final ClassData withDef = new ClassData(pck, mdata);
+                         final int C2 = builder.addInterface(withDef);
+                         final int C1 = builder.expected;
+                         builder.hier.addInherit(C1, C2);
+                     });
+
+    public static final Template ReabstractExpectedClass =
+        new Template("ReabstractExpectedClass",
+                     ReabstractExpectedIface,
+                     (final SelectionResolutionTestCase.Builder builder) -> {
+                         final ClassData expected =
+                             builder.classdata.get(builder.expected);
+                         final ClassData.Package pck = expected.packageId;
+                         final MethodData.Access acc =
+                             builder.classdata.get(builder.expected).methoddata.access;
+                         final MethodData mdata =
+                             getMethodData(acc, MethodData.Context.STATIC);
+                         final ClassData withDef = new ClassData(pck, mdata);
+                         final int C2 = builder.addClass(withDef);
+                         final int C1 = builder.expected;
+                         builder.hier.addInherit(C1, C2);
+                     },
+                     (final SelectionResolutionTestCase.Builder builder) -> {
+                         final ClassData expected =
+                             builder.classdata.get(builder.expected);
+                         final ClassData.Package pck = expected.packageId;
+                         final MethodData.Access acc =
+                             builder.classdata.get(builder.expected).methoddata.access;
+                         final MethodData mdata =
+                             getMethodData(acc, MethodData.Context.INSTANCE);
+                         final ClassData withDef = new ClassData(pck, mdata);
+                         final int C2 = builder.addClass(withDef);
+                         final int C1 = builder.expected;
+                         builder.hier.addInherit(C1, C2);
+                     });
+
+    public static final Template ReabstractMethodrefResolvedClass =
+        new Template("ReabstractMethodrefResolvedClass",
+                    /* Case 1: Objectref overrides.
+                     *
+                     * C2[](*) = mref
+                     * C1[C2](res) = oref = expected
+                     */
+                    (final SelectionResolutionTestCase.Builder builder) -> {
+                        final ClassData.Package pck =
+                            builder.classdata.get(builder.methodref).packageId;
+                        final ClassData oldexpected =
+                            builder.classdata.get(builder.expected);
+                        final MethodData.Access acc =
+                            builder.classdata.get(builder.expected).methoddata.access;
+                        final ClassData withDef =
+                            new ClassData(pck, new MethodData(acc, MethodData.Context.ABSTRACT));
+                        final int C2 = builder.methodref;
+                        final int C1 = builder.addClass(withDef);
+                        builder.hier.addInherit(C1, C2);
+                        builder.objectref = C1;
+                        builder.expected = C1;
+                    },
+                    /* Case 2: Objectref's super overrides.
+                     *
+                     * C3[*](*) = mref
+                     * C2[C3](res) = expected
+                     * C1[C2]() = oref
+                     */
+                    (final SelectionResolutionTestCase.Builder builder) -> {
+                        final ClassData.Package pck =
+                            builder.classdata.get(builder.methodref).packageId;
+                        final ClassData oldexpected =
+                            builder.classdata.get(builder.expected);
+                        final MethodData.Access acc =
+                            builder.classdata.get(builder.expected).methoddata.access;
+                        final ClassData withDef =
+                            new ClassData(pck, new MethodData(acc, MethodData.Context.ABSTRACT));
+                        final int C3 = builder.methodref;
+                        final int C2 = builder.addClass(withDef);
+                        final int C1 = builder.addClass(emptyClass(pck));
+                        builder.hier.addInherit(C2, C3);
+                        builder.hier.addInherit(C1, C2);
+                        builder.objectref = C1;
+                        builder.expected = C2;
+                    },
+                    /* Case 3: Objectref's super overrides, skip private.
+                     *
+                     * C3[*](*) = mref
+                     * C2[C3](res) = expected
+                     * C1[C2](priv) = oref
+                     */
+                    (final SelectionResolutionTestCase.Builder builder) -> {
+                        final ClassData.Package pck =
+                            builder.classdata.get(builder.methodref).packageId;
+                        final ClassData oldexpected =
+                            builder.classdata.get(builder.expected);
+                        final MethodData.Access acc =
+                            builder.classdata.get(builder.expected).methoddata.access;
+                        final ClassData withDef =
+                            new ClassData(pck, new MethodData(acc, MethodData.Context.ABSTRACT));
+                        final MethodData meth =
+                            new MethodData(MethodData.Access.PRIVATE,
+                                           MethodData.Context.INSTANCE);
+                        final ClassData withPrivDef = new ClassData(pck, meth);
+                        final int C3 = builder.methodref;
+                        final int C2 = builder.addClass(withDef);
+                        final int C1 = builder.addClass(withPrivDef);
+                        builder.hier.addInherit(C2, C3);
+                        builder.hier.addInherit(C1, C2);
+                        builder.objectref = C1;
+                        builder.expected = C2;
+                    },
+                    /* Case 4: Objectref's super overrides, skip static.
+                     *
+                     * C3[*](*) = mref
+                     * C2[C3](res) = expected
+                     * C1[C2](stat) = oref
+                     */
+                    (final SelectionResolutionTestCase.Builder builder) -> {
+                        final ClassData.Package pck =
+                            builder.classdata.get(builder.methodref).packageId;
+                        final ClassData oldexpected =
+                            builder.classdata.get(builder.expected);
+                        final MethodData.Access acc =
+                            builder.classdata.get(builder.expected).methoddata.access;
+                        final ClassData withDef =
+                            new ClassData(pck, new MethodData(acc, MethodData.Context.ABSTRACT));
+                        final MethodData meth =
+                            new MethodData(MethodData.Access.PUBLIC,
+                                           MethodData.Context.STATIC);
+                        final ClassData withStatDef = new ClassData(pck, meth);
+                        final int C3 = builder.methodref;
+                        final int C2 = builder.addClass(withDef);
+                        final int C1 = builder.addClass(withStatDef);
+                        builder.hier.addInherit(C2, C3);
+                        builder.hier.addInherit(C1, C2);
+                        builder.objectref = C1;
+                        builder.expected = C2;
+                    });
+
+    public static final Template ReabstractMethodrefResolvedIface =
+        new Template("ReabstractMethodrefResolvedIface",
+                    /* Case 1: Objectref overrides.
+                     *
+                     * C2[](*) = mref
+                     * C1[C2](res) = oref = expected
+                     */
+                    (final SelectionResolutionTestCase.Builder builder) -> {
+                        final ClassData.Package pck =
+                            builder.classdata.get(builder.methodref).packageId;
+                        final ClassData oldexpected =
+                            builder.classdata.get(builder.expected);
+                        final MethodData.Access acc =
+                            builder.classdata.get(builder.expected).methoddata.access;
+                        final ClassData withDef =
+                            new ClassData(pck, new MethodData(acc, MethodData.Context.ABSTRACT));
+                        final int C2 = builder.methodref;
+                        final int C1 = builder.addClass(withDef);
+                        builder.hier.addInherit(C1, C2);
+                        builder.objectref = C1;
+                        builder.expected = C1;
+                    },
+                    /* Case 2: Objectref's super overrides.
+                     *
+                     * C3[](*) = mref
+                     * C2[C3](res) = expected
+                     * C1[C2]() = oref
+                     */
+                    (final SelectionResolutionTestCase.Builder builder) -> {
+                        final ClassData.Package pck =
+                            builder.classdata.get(builder.methodref).packageId;
+                        final ClassData oldexpected =
+                            builder.classdata.get(builder.expected);
+                        final MethodData.Access acc =
+                            builder.classdata.get(builder.expected).methoddata.access;
+                        final ClassData withDef =
+                            new ClassData(pck, new MethodData(acc, MethodData.Context.ABSTRACT));
+                        final int C3 = builder.methodref;
+                        final int C2 = builder.addClass(withDef);
+                        final int C1 = builder.addClass(emptyClass(pck));
+                        builder.hier.addInherit(C2, C3);
+                        builder.hier.addInherit(C1, C2);
+                        builder.objectref = C1;
+                        builder.expected = C2;
+                    },
+                    /* Case 3: Objectref's super overrides, skip private.
+                     *
+                     * C3[*](*) = mref
+                     * C2[C3](res) = expected
+                     * C1[C2](priv) = oref
+                     */
+                    (final SelectionResolutionTestCase.Builder builder) -> {
+                        final ClassData.Package pck =
+                            builder.classdata.get(builder.methodref).packageId;
+                        final ClassData oldexpected =
+                            builder.classdata.get(builder.expected);
+                        final MethodData.Access acc =
+                            builder.classdata.get(builder.expected).methoddata.access;
+                        final ClassData withDef =
+                            new ClassData(pck, new MethodData(acc, MethodData.Context.ABSTRACT));
+                        final MethodData meth =
+                            new MethodData(MethodData.Access.PRIVATE,
+                                           MethodData.Context.INSTANCE);
+                        final ClassData withPrivDef = new ClassData(pck, meth);
+                        final int C3 = builder.methodref;
+                        final int C2 = builder.addClass(withDef);
+                        final int C1 = builder.addClass(withPrivDef);
+                        builder.hier.addInherit(C2, C3);
+                        builder.hier.addInherit(C1, C2);
+                        builder.objectref = C1;
+                        builder.expected = C2;
+                    },
+                    /* Case 4: Objectref's super overrides, skip static.
+                     *
+                     * C3[*](*) = mref
+                     * C2[C3](res) = expected
+                     * C1[C2](stat) = oref
+                     */
+                    (final SelectionResolutionTestCase.Builder builder) -> {
+                        final ClassData.Package pck =
+                            builder.classdata.get(builder.methodref).packageId;
+                        final ClassData oldexpected =
+                            builder.classdata.get(builder.expected);
+                        final MethodData.Access acc =
+                            builder.classdata.get(builder.expected).methoddata.access;
+                        final ClassData withDef =
+                            new ClassData(pck, new MethodData(acc, MethodData.Context.ABSTRACT));
+                        final MethodData meth =
+                            new MethodData(MethodData.Access.PUBLIC,
+                                           MethodData.Context.STATIC);
+                        final ClassData withStatDef = new ClassData(pck, meth);
+                        final int C3 = builder.methodref;
+                        final int C2 = builder.addClass(withDef);
+                        final int C1 = builder.addClass(withStatDef);
+                        builder.hier.addInherit(C2, C3);
+                        builder.hier.addInherit(C1, C2);
+                        builder.objectref = C1;
+                        builder.expected = C2;
+                    },
+                    /* Case 5: Overlapping with new interface overriding.
+                     *
+                     * I2[*](def) = old expected
+                     * C2[*](*) = mref, I1[I2](res) = expected
+                     * C1[C2,I2]() = oref
+                     */
+                    (final SelectionResolutionTestCase.Builder builder) -> {
+                        final ClassData.Package pck =
+                            builder.classdata.get(builder.methodref).packageId;
+                        final ClassData oldexpected =
+                            builder.classdata.get(builder.expected);
+                        final MethodData.Access acc =
+                            builder.classdata.get(builder.expected).methoddata.access;
+                        final ClassData withDef =
+                            new ClassData(pck, new MethodData(acc, MethodData.Context.ABSTRACT));
+                        final int C2 = builder.methodref;
+                        final int I2 = builder.expected;
+                        final int I1 = builder.addInterface(withDef);
+                        final int C1 = builder.addClass(emptyClass(pck));
+                        builder.hier.addInherit(C1, C2);
+                        builder.hier.addInherit(C1, I1);
+                        builder.hier.addInherit(I1, I2);
+                        builder.objectref = C1;
+                        builder.expected = I1;
+                    },
+                    /* Case 6: Overlapping with new interface, skip private.
+                     *
+                     * I2[*](def) = old expected
+                     * C2[*](*) = mref, I1[I2](res) = expected
+                     * C1[C2,I2](priv) = oref
+                     */
+                    (final SelectionResolutionTestCase.Builder builder) -> {
+                        final ClassData.Package pck =
+                            builder.classdata.get(builder.methodref).packageId;
+                        final ClassData oldexpected =
+                            builder.classdata.get(builder.expected);
+                        final MethodData.Access acc =
+                            builder.classdata.get(builder.expected).methoddata.access;
+                        final ClassData withDef =
+                            new ClassData(pck, new MethodData(acc, MethodData.Context.ABSTRACT));
+                        final MethodData meth =
+                            new MethodData(MethodData.Access.PRIVATE,
+                                           MethodData.Context.INSTANCE);
+                        final ClassData withPrivDef = new ClassData(pck, meth);
+                        final int C2 = builder.methodref;
+                        final int I2 = builder.expected;
+                        final int I1 = builder.addInterface(withDef);
+                        final int C1 = builder.addClass(withPrivDef);
+                        builder.hier.addInherit(C1, C2);
+                        builder.hier.addInherit(C1, I1);
+                        builder.hier.addInherit(I1, I2);
+                        builder.objectref = C1;
+                        builder.expected = I1;
+                    },
+                    /* Case 7: Overlapping with new interface, skip static.
+                     *
+                     * I2[*](def) = old expected
+                     * C2[*](*) = mref, I1[I2](res) = expected
+                     * C1[C2,I2](stat) = oref
+                     */
+                    (final SelectionResolutionTestCase.Builder builder) -> {
+                        final ClassData.Package pck =
+                            builder.classdata.get(builder.methodref).packageId;
+                        final ClassData oldexpected =
+                            builder.classdata.get(builder.expected);
+                        final MethodData.Access acc =
+                            builder.classdata.get(builder.expected).methoddata.access;
+                        final ClassData withDef =
+                            new ClassData(pck, new MethodData(acc, MethodData.Context.ABSTRACT));
+                        final MethodData meth =
+                            new MethodData(MethodData.Access.PUBLIC,
+                                           MethodData.Context.STATIC);
+                        final ClassData withStatDef = new ClassData(pck, meth);
+                        final int C2 = builder.methodref;
+                        final int I2 = builder.expected;
+                        final int I1 = builder.addInterface(withDef);
+                        final int C1 = builder.addClass(withStatDef);
+                        builder.hier.addInherit(C1, C2);
+                        builder.hier.addInherit(C1, I1);
+                        builder.hier.addInherit(I1, I2);
+                        builder.objectref = C1;
+                        builder.expected = I1;
+                    },
+                    /* Case 8: Overlap with objectref's super with new
+                     * interface overriding, inherit through class.
+                     *
+                     * I2[*](def) = old expected
+                     * C3[](*) = mref, I1[I2](res) = expected
+                     * C2[C3,I1]()
+                     * C1[C2]() = oref
+                     */
+                    (final SelectionResolutionTestCase.Builder builder) -> {
+                        final ClassData.Package pck =
+                            builder.classdata.get(builder.methodref).packageId;
+                        final ClassData oldexpected =
+                            builder.classdata.get(builder.expected);
+                        final MethodData.Access acc =
+                            builder.classdata.get(builder.expected).methoddata.access;
+                        final ClassData withDef =
+                            new ClassData(pck, new MethodData(acc, MethodData.Context.ABSTRACT));
+                        final int C3 = builder.methodref;
+                        final int C2 = builder.addClass(emptyClass(pck));
+                        final int I2 = builder.expected;
+                        final int I1 = builder.addInterface(withDef);
+                        final int C1 = builder.addClass(emptyClass(pck));
+                        builder.hier.addInherit(C2, C3);
+                        builder.hier.addInherit(C1, C2);
+                        builder.hier.addInherit(C2, I1);
+                        builder.hier.addInherit(I1, I2);
+                        builder.objectref = C1;
+                        builder.expected = I1;
+                    },
+                    /* Case 9: Overlap with objectref's super with new
+                     * interface double diamond, overriding.
+                     *
+                     * I3[*](def) = old expected
+                     * C3[](*) = mref, I2[I3](def)
+                     * C2[C3,I2](), I1[I2](res) = expected
+                     * C1[C2,I1]() = oref
+                     */
+                    (final SelectionResolutionTestCase.Builder builder) -> {
+                        final ClassData.Package pck =
+                            builder.classdata.get(builder.methodref).packageId;
+                        final ClassData oldexpected =
+                            builder.classdata.get(builder.expected);
+                        final MethodData.Access acc =
+                            builder.classdata.get(builder.expected).methoddata.access;
+                        final ClassData withDef =
+                            new ClassData(pck, new MethodData(acc, MethodData.Context.ABSTRACT));
+                        final int C3 = builder.methodref;
+                        final int C2 = builder.addClass(emptyClass(pck));
+                        final int I3 = builder.expected;
+                        final int I2 = builder.addInterface(withDef);
+                        final int I1 = builder.addInterface(withDef);
+                        final int C1 = builder.addClass(emptyClass(pck));
+                        builder.hier.addInherit(C2, C3);
+                        builder.hier.addInherit(C1, C2);
+                        builder.hier.addInherit(C1, I1);
+                        builder.hier.addInherit(C2, I2);
+                        builder.hier.addInherit(I1, I2);
+                        builder.hier.addInherit(I2, I3);
+                        builder.objectref = C1;
+                        builder.expected = I1;
+                    },
+                    /* Case 10: Overlap with objectref's super with new
+                     * interface double diamond, skip private.
+                     *
+                     * I3[*](def) = old expected
+                     * C3[](*) = mref, I2[I3](res) = expected
+                     * C2[C3,I2](), I1[I2](priv)
+                     * C1[C2,I1]() = oref
+                     */
+                    (final SelectionResolutionTestCase.Builder builder) -> {
+                        final ClassData.Package pck =
+                            builder.classdata.get(builder.methodref).packageId;
+                        final ClassData oldexpected =
+                            builder.classdata.get(builder.expected);
+                        final MethodData.Access acc =
+                            builder.classdata.get(builder.expected).methoddata.access;
+                        final ClassData withDef =
+                            new ClassData(pck, new MethodData(acc, MethodData.Context.ABSTRACT));
+                        final MethodData meth =
+                            new MethodData(MethodData.Access.PRIVATE,
+                                           MethodData.Context.INSTANCE);
+                        final ClassData withPrivDef = new ClassData(pck, meth);
+                        final int C3 = builder.methodref;
+                        final int C2 = builder.addClass(emptyClass(pck));
+                        final int I3 = builder.expected;
+                        final int I2 = builder.addInterface(withDef);
+                        final int I1 = builder.addInterface(withPrivDef);
+                        final int C1 = builder.addClass(emptyClass(pck));
+                        builder.hier.addInherit(C2, C3);
+                        builder.hier.addInherit(C1, C2);
+                        builder.hier.addInherit(C1, I1);
+                        builder.hier.addInherit(C2, I2);
+                        builder.hier.addInherit(I1, I2);
+                        builder.hier.addInherit(I2, I3);
+                        builder.objectref = C1;
+                        builder.expected = I2;
+                    },
+                    /* Case 11: Overlap with objectref's super with new
+                     * interface double diamond, skip static.
+                     *
+                     * I3[*](def) = old expected
+                     * C3[](*) = mref, I2[I3](res) = expected
+                     * C2[C3,I2](), I1[I2](stat)
+                     * C1[C2,I1]() = oref
+                     */
+                    (final SelectionResolutionTestCase.Builder builder) -> {
+                        final ClassData.Package pck =
+                            builder.classdata.get(builder.methodref).packageId;
+                        final ClassData oldexpected =
+                            builder.classdata.get(builder.expected);
+                        final MethodData.Access acc =
+                            builder.classdata.get(builder.expected).methoddata.access;
+                        final ClassData withDef =
+                            new ClassData(pck, new MethodData(acc, MethodData.Context.ABSTRACT));
+                        final MethodData meth =
+                            new MethodData(MethodData.Access.PUBLIC,
+                                           MethodData.Context.STATIC);
+                        final ClassData withStatDef = new ClassData(pck, meth);
+                        final int C3 = builder.methodref;
+                        final int C2 = builder.addClass(emptyClass(pck));
+                        final int I3 = builder.expected;
+                        final int I2 = builder.addInterface(withDef);
+                        final int I1 = builder.addInterface(withStatDef);
+                        final int C1 = builder.addClass(emptyClass(pck));
+                        builder.hier.addInherit(C2, C3);
+                        builder.hier.addInherit(C1, C2);
+                        builder.hier.addInherit(C1, I1);
+                        builder.hier.addInherit(C2, I2);
+                        builder.hier.addInherit(I1, I2);
+                        builder.hier.addInherit(I2, I3);
+                        builder.objectref = C1;
+                        builder.expected = I2;
+                    },
+                    /* Case 12: Objectref's super overrides, skip interface below.
+                     *
+                     * C3[](*) = mref
+                     * C2[C3](res) = expected, I[](def)
+                     * C1[C2,I]() = oref
+                     */
+                    (final SelectionResolutionTestCase.Builder builder) -> {
+                        final ClassData.Package pck =
+                            builder.classdata.get(builder.methodref).packageId;
+                        final ClassData oldexpected =
+                            builder.classdata.get(builder.expected);
+                        final MethodData.Access acc =
+                            builder.classdata.get(builder.expected).methoddata.access;
+                        final ClassData withDef =
+                            new ClassData(pck, new MethodData(acc, MethodData.Context.ABSTRACT));
+                        final int C3 = builder.methodref;
+                        final int C2 = builder.addClass(withDef);
+                        final int C1 = builder.addClass(emptyClass(pck));
+                        final int I = builder.addInterface(withDef);
+                        builder.hier.addInherit(C2, C3);
+                        builder.hier.addInherit(C1, C2);
+                        builder.hier.addInherit(C1, I);
+                        builder.objectref = C1;
+                        builder.expected = C2;
+                    },
+                    /* Case 13: Objectref's super overrides, skip interface above.
+                     *
+                     * C3[](*) = mref, I[](def)
+                     * C2[C3,I](res) = expected
+                     * C1[C2]() = oref
+                     */
+                    (final SelectionResolutionTestCase.Builder builder) -> {
+                        final ClassData.Package pck =
+                            builder.classdata.get(builder.methodref).packageId;
+                        final ClassData oldexpected =
+                            builder.classdata.get(builder.expected);
+                        final MethodData.Access acc =
+                            builder.classdata.get(builder.expected).methoddata.access;
+                        final ClassData withDef =
+                            new ClassData(pck, new MethodData(acc, MethodData.Context.ABSTRACT));
+                        final int C3 = builder.methodref;
+                        final int C2 = builder.addClass(withDef);
+                        final int C1 = builder.addClass(emptyClass(pck));
+                        final int I = builder.addInterface(withDef);
+                        builder.hier.addInherit(C2, C3);
+                        builder.hier.addInherit(C1, C2);
+                        builder.hier.addInherit(C2, I);
+                        builder.objectref = C1;
+                        builder.expected = C2;
+                    });
+
+    public static final Template ReabstractIfaceMethodrefResolved =
+        new Template("ReabstractIfaceMethodrefResolved",
+                     /* Case 1: Objectref overrides.
+                      *
+                      * I[](*) = mref
+                      * C[I](res) = oref = expected
+                      */
+                     (final SelectionResolutionTestCase.Builder builder) -> {
+                         final ClassData.Package pck =
+                             builder.classdata.get(builder.methodref).packageId;
+                        final ClassData oldexpected =
+                            builder.classdata.get(builder.expected);
+                        final MethodData.Access acc =
+                            builder.classdata.get(builder.expected).methoddata.access;
+                        final ClassData withDef =
+                            new ClassData(pck, new MethodData(acc, MethodData.Context.ABSTRACT));
+                         final int I = builder.methodref;
+                         final int C = builder.addClass(withDef);
+                         builder.hier.addInherit(C, I);
+                         builder.objectref = C;
+                         builder.expected = C;
+                     },
+                     /* Case 2: Diamond, methodref at top, overriding.
+                      *
+                      * I3[](*) = mref
+                      * I1[I3](), I2[I3](res) = expected
+                      * C[I1,I2]() = oref
+                      */
+                     (final SelectionResolutionTestCase.Builder builder) -> {
+                         final ClassData.Package pck =
+                             builder.classdata.get(builder.expected).packageId;
+                        final ClassData oldexpected =
+                            builder.classdata.get(builder.expected);
+                        final MethodData.Access acc =
+                            builder.classdata.get(builder.expected).methoddata.access;
+                        final ClassData withDef =
+                            new ClassData(pck, new MethodData(acc, MethodData.Context.ABSTRACT));
+                         final int I3 = builder.methodref;
+                         final int I2 = builder.addInterface(withDef);
+                         final int I1 = builder.addInterface(emptyClass(pck));
+                         final int C = builder.addClass(emptyClass(pck));
+                         builder.hier.addInherit(C, I1);
+                         builder.hier.addInherit(C, I2);
+                         builder.hier.addInherit(I1, I3);
+                         builder.hier.addInherit(I2, I3);
+                         builder.objectref = C;
+                         builder.expected = I2;
+                     },
+                     /* Case 3: Diamond, methodref at top, skip static.
+                      *
+                      * I3[](*) = mref
+                      * I1[I3](), I2[I3](res) = expected
+                      * C[I1,I2](stat) = oref
+                      */
+                     (final SelectionResolutionTestCase.Builder builder) -> {
+                         final ClassData.Package pck =
+                             builder.classdata.get(builder.expected).packageId;
+                        final ClassData oldexpected =
+                            builder.classdata.get(builder.expected);
+                        final MethodData.Access acc =
+                            builder.classdata.get(builder.expected).methoddata.access;
+                        final ClassData withDef =
+                            new ClassData(pck, new MethodData(acc, MethodData.Context.ABSTRACT));
+                        final MethodData meth =
+                            new MethodData(MethodData.Access.PUBLIC,
+                                           MethodData.Context.STATIC);
+                        final ClassData withStatDef = new ClassData(pck, meth);
+                         final int I3 = builder.methodref;
+                         final int I2 = builder.addInterface(withDef);
+                         final int I1 = builder.addInterface(emptyClass(pck));
+                         final int C = builder.addClass(withStatDef);
+                         builder.hier.addInherit(C, I1);
+                         builder.hier.addInherit(C, I2);
+                         builder.hier.addInherit(I1, I3);
+                         builder.hier.addInherit(I2, I3);
+                         builder.objectref = C;
+                         builder.expected = I2;
+                     },
+                     /* Case 4: Diamond, with superclass, methodref at top,
+                      * class overriding.
+                      *
+                      * I2[](*) = mref
+                      * C2[I2](res) = expected, I1[I2]()
+                      * C1[I1,C2]() = oref
+                      */
+                     (final SelectionResolutionTestCase.Builder builder) -> {
+                         final ClassData.Package pck =
+                             builder.classdata.get(builder.expected).packageId;
+                        final ClassData oldexpected =
+                            builder.classdata.get(builder.expected);
+                        final MethodData.Access acc =
+                            builder.classdata.get(builder.expected).methoddata.access;
+                        final ClassData withDef =
+                            new ClassData(pck, new MethodData(acc, MethodData.Context.ABSTRACT));
+                         final int I2 = builder.methodref;
+                         final int I1 = builder.addInterface(emptyClass(pck));
+                         final int C2 = builder.addClass(withDef);
+                         final int C1 = builder.addClass(emptyClass(pck));
+                         builder.hier.addInherit(C1, I1);
+                         builder.hier.addInherit(C1, C2);
+                         builder.hier.addInherit(I1, I2);
+                         builder.hier.addInherit(C2, I2);
+                         builder.objectref = C1;
+                         builder.expected = C2;
+                     },
+                     /* Case 5: Diamond, with superclass, methodref at top,
+                      * class overriding, skip static.
+                      *
+                      * I2[](*) = mref
+                      * C2[I2](res) = expected, I1[I2]()
+                      * C1[I1,C2](stat) = oref
+                      */
+                     (final SelectionResolutionTestCase.Builder builder) -> {
+                         final ClassData.Package pck =
+                             builder.classdata.get(builder.expected).packageId;
+                        final ClassData oldexpected =
+                            builder.classdata.get(builder.expected);
+                        final MethodData.Access acc =
+                            builder.classdata.get(builder.expected).methoddata.access;
+                        final ClassData withDef =
+                            new ClassData(pck, new MethodData(acc, MethodData.Context.ABSTRACT));
+                        final MethodData meth =
+                            new MethodData(MethodData.Access.PUBLIC,
+                                           MethodData.Context.STATIC);
+                        final ClassData withStatDef = new ClassData(pck, meth);
+                         final int I2 = builder.methodref;
+                         final int I1 = builder.addInterface(emptyClass(pck));
+                         final int C2 = builder.addClass(withDef);
+                         final int C1 = builder.addClass(withStatDef);
+                         builder.hier.addInherit(C1, I1);
+                         builder.hier.addInherit(C1, C2);
+                         builder.hier.addInherit(I1, I2);
+                         builder.hier.addInherit(C2, I2);
+                         builder.objectref = C1;
+                         builder.expected = C2;
+                     },
+                     /* Case 6: Diamond, with superclass, expected at top,
+                      * interface overriding
+                      *
+                      * I2[](*) = mref
+                      * C2[I2](), I1[I2](res) = expected
+                      * C1[I1,C2]() = oref
+                      */
+                     (final SelectionResolutionTestCase.Builder builder) -> {
+                         final ClassData.Package pck =
+                             builder.classdata.get(builder.expected).packageId;
+                         final ClassData oldexpected =
+                             builder.classdata.get(builder.expected);
+                         final MethodData.Access acc =
+                             builder.classdata.get(builder.expected).methoddata.access;
+                         final ClassData withDef =
+                             new ClassData(pck, new MethodData(acc, MethodData.Context.ABSTRACT));
+                         final int I2 = builder.methodref;
+                         final int I1 = builder.addInterface(withDef);
+                         final int C2 = builder.addClass(emptyClass(pck));
+                         final int C1 = builder.addClass(emptyClass(pck));
+                         builder.hier.addInherit(C1, I1);
+                         builder.hier.addInherit(C1, C2);
+                         builder.hier.addInherit(I1, I2);
+                         builder.hier.addInherit(C2, I2);
+                         builder.objectref = C1;
+                         builder.expected = I1;
+                     },
+                     /* Case 7: Diamond, with superclass, expected at top,
+                      * interface skip static
+                      *
+                      * I2[](*) = mref
+                      * C2[I2](), I1[I2](res) = expected
+                      * C1[I1,C2](stat) = oref
+                      */
+                     (final SelectionResolutionTestCase.Builder builder) -> {
+                         final ClassData.Package pck =
+                             builder.classdata.get(builder.expected).packageId;
+                         final ClassData oldexpected =
+                             builder.classdata.get(builder.expected);
+                         final MethodData.Access acc =
+                             builder.classdata.get(builder.expected).methoddata.access;
+                         final ClassData withDef =
+                             new ClassData(pck, new MethodData(acc, MethodData.Context.ABSTRACT));
+                         final MethodData meth =
+                             new MethodData(MethodData.Access.PUBLIC,
+                                            MethodData.Context.STATIC);
+                         final ClassData withStatDef = new ClassData(pck, meth);
+                         final int I2 = builder.methodref;
+                         final int I1 = builder.addInterface(withDef);
+                         final int C2 = builder.addClass(emptyClass(pck));
+                         final int C1 = builder.addClass(withStatDef);
+                         builder.hier.addInherit(C1, I1);
+                         builder.hier.addInherit(C1, C2);
+                         builder.hier.addInherit(I1, I2);
+                         builder.hier.addInherit(C2, I2);
+                         builder.objectref = C1;
+                         builder.expected = I1;
+                     },
+                     /* Case 8: Y, with superclass, overlaping, expected
+                      * at top, class overrides
+                      *
+                      * C2[I2](res) = expected, I1[](*) = mref
+                      * C1[I1,C2]() = oref
+                      */
+                     (final SelectionResolutionTestCase.Builder builder) -> {
+                         final ClassData.Package pck =
+                             builder.classdata.get(builder.expected).packageId;
+                         final ClassData oldexpected =
+                             builder.classdata.get(builder.expected);
+                         final MethodData.Access acc =
+                             builder.classdata.get(builder.expected).methoddata.access;
+                         final ClassData withDef =
+                             new ClassData(pck, new MethodData(acc, MethodData.Context.ABSTRACT));
+                         final int I1 = builder.methodref;
+                         final int C2 = builder.addClass(withDef);
+                         final int C1 = builder.addClass(emptyClass(pck));
+                         builder.hier.addInherit(C1, I1);
+                         builder.hier.addInherit(C1, C2);
+                         builder.objectref = C1;
+                         builder.expected = C2;
+                     },
+                     /* Case 9: Diamond, with superclass, overlaping, expected
+                      * at top, class overrides
+                      *
+                      * I2[](def) = old expected
+                      * C2[I2](res) = expected, I1[](*) = mref
+                      * C1[I1,C2]() = oref
+                      */
+                     (final SelectionResolutionTestCase.Builder builder) -> {
+                         final ClassData.Package pck =
+                             builder.classdata.get(builder.expected).packageId;
+                         final ClassData oldexpected =
+                             builder.classdata.get(builder.expected);
+                         final MethodData.Access acc =
+                             builder.classdata.get(builder.expected).methoddata.access;
+                         final ClassData withDef =
+                             new ClassData(pck, new MethodData(acc, MethodData.Context.ABSTRACT));
+                         final int I2 = builder.expected;
+                         final int I1 = builder.methodref;
+                         final int C2 = builder.addClass(withDef);
+                         final int C1 = builder.addClass(emptyClass(pck));
+                         builder.hier.addInherit(C1, I1);
+                         builder.hier.addInherit(C1, C2);
+                         builder.hier.addInherit(C2, I2);
+                         builder.objectref = C1;
+                         builder.expected = C2;
+                     },
+                     /* Case 10: Diamond, with superclass, overlaping, expected
+                      * at top, class overrides, skipping static
+                      *
+                      * I2[](def) = old expected
+                      * C2[I2](res) = expected, I1[](*) = mref
+                      * C1[I1,C2](stat) = oref
+                      */
+                     (final SelectionResolutionTestCase.Builder builder) -> {
+                         final ClassData.Package pck =
+                             builder.classdata.get(builder.expected).packageId;
+                         final ClassData oldexpected =
+                             builder.classdata.get(builder.expected);
+                         final MethodData.Access acc =
+                             builder.classdata.get(builder.expected).methoddata.access;
+                         final ClassData withDef =
+                             new ClassData(pck, new MethodData(acc, MethodData.Context.ABSTRACT));
+                         final MethodData meth =
+                             new MethodData(MethodData.Access.PUBLIC,
+                                            MethodData.Context.STATIC);
+                         final ClassData withStatDef = new ClassData(pck, meth);
+                         final int I2 = builder.expected;
+                         final int I1 = builder.methodref;
+                         final int C2 = builder.addClass(withDef);
+                         final int C1 = builder.addClass(withStatDef);
+                         builder.hier.addInherit(C1, I1);
+                         builder.hier.addInherit(C1, C2);
+                         builder.hier.addInherit(C2, I2);
+                         builder.objectref = C1;
+                         builder.expected = C2;
+                     },
+                     /* Case 11: Superclass overrides.
+                      *
+                      * I[](*) = mref
+                      * C2[I](res) = expected
+                      * C1[C2]() = oref
+                      */
+                     (final SelectionResolutionTestCase.Builder builder) -> {
+                         final ClassData.Package pck =
+                             builder.classdata.get(builder.expected).packageId;
+                         final MethodData.Access acc =
+                             builder.classdata.get(builder.expected).methoddata.access;
+                         final ClassData withDef =
+                             new ClassData(pck, new MethodData(acc, MethodData.Context.ABSTRACT));
+                         final int I = builder.methodref;
+                         final int C2 = builder.addClass(withDef);
+                         final int C1 = builder.addClass(emptyClass(pck));
+                         builder.hier.addInherit(C1, I);
+                         builder.hier.addInherit(C1, C2);
+                         builder.hier.addInherit(C2, I);
+                         builder.objectref = C1;
+                     },
+                     /* Case 12: Superclass overrides, skipping static.
+                      *
+                      * I[](*) = mref
+                      * C2[I](res) = expected
+                      * C1[C2](stat) = oref
+                      */
+                     (final SelectionResolutionTestCase.Builder builder) -> {
+                         final ClassData.Package pck =
+                             builder.classdata.get(builder.expected).packageId;
+                         final MethodData.Access acc =
+                             builder.classdata.get(builder.expected).methoddata.access;
+                         final ClassData withDef =
+                             new ClassData(pck, new MethodData(acc, MethodData.Context.ABSTRACT));
+                         final MethodData meth =
+                             new MethodData(MethodData.Access.PUBLIC,
+                                            MethodData.Context.STATIC);
+                         final ClassData withStatDef = new ClassData(pck, meth);
+                         final int I = builder.methodref;
+                         final int C2 = builder.addClass(withDef);
+                         final int C1 = builder.addClass(withStatDef);
+                         builder.hier.addInherit(C1, I);
+                         builder.hier.addInherit(C1, C2);
+                         builder.hier.addInherit(C2, I);
+                         builder.objectref = C1;
+                     },
+                     /* Case 13: Double diamond, with superclass, inherit through
+                      * superclass, expected at top.
+                      *
+                      * I3[](def) = old expected
+                      * C3[I3](), I2[*](*) = mref
+                      * C2[I2,C3](), I1[I2](res) = expected
+                      * C1[C2,I1]() = oref
+                      */
+                     (final SelectionResolutionTestCase.Builder builder) -> {
+                         final ClassData.Package pck =
+                             builder.classdata.get(builder.expected).packageId;
+                         final ClassData oldexpected =
+                             builder.classdata.get(builder.expected);
+                         final MethodData.Access acc =
+                             builder.classdata.get(builder.expected).methoddata.access;
+                         final ClassData withDef =
+                             new ClassData(pck, new MethodData(acc, MethodData.Context.ABSTRACT));
+                         final int I3 = builder.expected;
+                         final int I2 = builder.methodref;
+                         final int I1 = builder.addInterface(withDef);
+                         final int C3 = builder.addClass(emptyClass(pck));
+                         final int C2 = builder.addClass(emptyClass(pck));
+                         final int C1 = builder.addClass(emptyClass(pck));
+                         builder.hier.addInherit(C2, I2);
+                         builder.hier.addInherit(C2, C3);
+                         builder.hier.addInherit(C3, I3);
+                         builder.hier.addInherit(C1, C2);
+                         builder.hier.addInherit(I1, I2);
+                         builder.hier.addInherit(C1, I1);
+                         builder.objectref = C1;
+                         builder.expected = I1;
+                     },
+                     /* Case 14: Double diamond, with superclass, inherit through
+                      * superclass, expected at top.
+                      *
+                      * I3[](def) = mref
+                      * C3[I3](), I2[*](*) = expected
+                      * C2[I2,C3](), I1[I2](priv)
+                      * C1[C2,I1]() = oref
+                      */
+                     (final SelectionResolutionTestCase.Builder builder) -> {
+                         final ClassData.Package pck =
+                             builder.classdata.get(builder.expected).packageId;
+                         final ClassData oldexpected =
+                             builder.classdata.get(builder.expected);
+                         final MethodData.Access acc =
+                             builder.classdata.get(builder.expected).methoddata.access;
+                         final ClassData withDef =
+                             new ClassData(pck, new MethodData(acc, MethodData.Context.ABSTRACT));
+                         final MethodData meth =
+                             new MethodData(MethodData.Access.PRIVATE,
+                                            MethodData.Context.INSTANCE);
+                         final ClassData withPrivDef = new ClassData(pck, meth);
+                         final int I3 = builder.methodref;
+                         final int I2 = builder.addInterface(withDef);
+                         final int I1 = builder.addInterface(withPrivDef);
+                         final int C3 = builder.addClass(emptyClass(pck));
+                         final int C2 = builder.addClass(emptyClass(pck));
+                         final int C1 = builder.addClass(emptyClass(pck));
+                         builder.hier.addInherit(C2, I2);
+                         builder.hier.addInherit(C2, C3);
+                         builder.hier.addInherit(C3, I3);
+                         builder.hier.addInherit(C1, C2);
+                         builder.hier.addInherit(I2, I3);
+                         builder.hier.addInherit(I1, I2);
+                         builder.hier.addInherit(C1, I1);
+                         builder.objectref = C1;
+                         builder.expected = I2;
+                     },
+                     /* Case 15: Double diamond, with superclass, inherit through
+                      * superclass, expected at top.
+                      *
+                      * I3[](def) = mref
+                      * C3[I3](), I2[*](*) = expected
+                      * C2[I2,C3](), I1[I2](stat)
+                      * C1[C2,I1]() = oref
+                      */
+                     (final SelectionResolutionTestCase.Builder builder) -> {
+                         final ClassData.Package pck =
+                             builder.classdata.get(builder.expected).packageId;
+                         final ClassData oldexpected =
+                             builder.classdata.get(builder.expected);
+                         final MethodData.Access acc =
+                             builder.classdata.get(builder.expected).methoddata.access;
+                         final ClassData withDef =
+                             new ClassData(pck, new MethodData(acc, MethodData.Context.ABSTRACT));
+                         final MethodData meth =
+                             new MethodData(MethodData.Access.PUBLIC,
+                                            MethodData.Context.STATIC);
+                         final ClassData withStatDef = new ClassData(pck, meth);
+                         final int I3 = builder.methodref;
+                         final int I2 = builder.addInterface(withDef);
+                         final int I1 = builder.addInterface(withStatDef);
+                         final int C3 = builder.addClass(emptyClass(pck));
+                         final int C2 = builder.addClass(emptyClass(pck));
+                         final int C1 = builder.addClass(emptyClass(pck));
+                         builder.hier.addInherit(C2, I2);
+                         builder.hier.addInherit(C2, C3);
+                         builder.hier.addInherit(C3, I3);
+                         builder.hier.addInherit(C1, C2);
+                         builder.hier.addInherit(I2, I3);
+                         builder.hier.addInherit(I1, I2);
+                         builder.hier.addInherit(C1, I1);
+                         builder.objectref = C1;
+                         builder.expected = I2;
+                     });
+
+    /******************************
+     *    Abstract Overrides      *
+     ******************************/
+
+    public static final Template OverrideAbstractExpectedIface =
+        Template.ResolutionOverride(EnumSet.of(Template.Kind.INTERFACE),
+                                    EnumSet.of(MethodData.Access.PUBLIC),
+                                    EnumSet.allOf(MethodData.Context.class),
+                                    EnumSet.of(ClassData.Package.SAME));
+
+    public static final Template OverrideAbstractExpectedClass =
+        Template.ResolutionOverride(EnumSet.allOf(Template.Kind.class),
+                                    EnumSet.of(MethodData.Access.PUBLIC),
+                                    EnumSet.allOf(MethodData.Context.class),
+                                    EnumSet.of(ClassData.Package.SAME));
+
+    public static final Template SelectionOverrideAbstract =
+        new Template("SelectionOverrideAbstract",
+                     (final SelectionResolutionTestCase.Builder builder) -> {
+                         final ClassData expected =
+                             builder.classdata.get(builder.expected);
+                         final MethodData olddef =
+                             expected.methoddata;
+                         if (MethodData.Context.ABSTRACT == olddef.context) {
+                             final ClassData.Package pck = expected.packageId;
+                             final MethodData.Access acc = olddef.access;
+                             final MethodData mdata =
+                                 getMethodData(MethodData.Access.PUBLIC,
+                                               MethodData.Context.INSTANCE);
+                             final ClassData withDef = new ClassData(pck, mdata);
+                             final int C2 = builder.objectref;
+                             final int C1 = builder.addClass(withDef);
+                             builder.hier.addInherit(C1, C2);
+                             builder.objectref = C1;
+                             builder.expected = C1;
+                         }
+                     });
+
+
+    /******************************
+     * Ignored Abstract Templates *
+     ******************************/
+
+    public static final Template IgnoredAbstract =
+        new Template("IgnoredAbstract",
+                     (builder) -> {},
+                     (final SelectionResolutionTestCase.Builder builder) -> {
+                         final ClassData methodref =
+                             builder.classdata.get(builder.methodref);
+                         final ClassData.Package pck = methodref.packageId;
+                         final MethodData mdata =
+                             getMethodData(MethodData.Access.PUBLIC,
+                                           MethodData.Context.ABSTRACT);
+                         final ClassData withDef = new ClassData(pck, mdata);
+                         final int C2 = builder.addInterface(withDef);
+                         final int C1 = builder.methodref;
+                         builder.hier.addInherit(C1, C2);
+                     });
+
+    /******************************
+     *     Selection Templates    *
+     ******************************/
+
+
+
+    public static final Template TrivialObjectref =
+        new Template("TrivialObjectref",
+                     Collections.singleton((builder) -> {
+                             builder.objectref = builder.methodref;
+                         }));
+
+    public static final Template TrivialObjectrefNotEqualMethodref =
+        new Template("TrivialObjectrefNotEqualMethodref",
+                     Collections.singleton(
+                         (final SelectionResolutionTestCase.Builder builder) -> {
+                             final ClassData oldexpected =
+                             builder.classdata.get(builder.expected);
+                             final ClassData.Package pck = oldexpected.packageId;
+                             final int C2 = builder.methodref;
+                             final int C1 = builder.addClass(emptyClass(pck));
+                             builder.hier.addInherit(C1, C2);
+                             builder.objectref = C1;
+                         }));
+
+    public static final Template MethodrefSelectionResolvedIsClassNoOverride =
+        new Template("MethodrefSelectionResolvedIsClassNoOverride",
+                    /* Trivial.
+                     *
+                     * C[](*) = mref = oref
+                     */
+                    (builder) -> {
+                        builder.objectref = builder.methodref;
+                    },
+                    /* Case 1: Inherit from super.
+                     *
+                     * C2[](*) = mref
+                     * C1[C2]() = oref
+                     */
+                    (final SelectionResolutionTestCase.Builder builder) -> {
+                        final ClassData.Package pck =
+                            builder.classdata.get(builder.methodref).packageId;
+                        final int C2 = builder.methodref;
+                        final int C1 = builder.addClass(emptyClass(pck));
+                        builder.hier.addInherit(C1, C2);
+                        builder.objectref = C1;
+                    },
+                    /* Case 2: Objectref has private def.
+                     *
+                     * C2[](*) = mref
+                     * C1[C2](priv) = oref
+                     */
+                    (final SelectionResolutionTestCase.Builder builder) -> {
+                        final ClassData.Package pck =
+                            builder.classdata.get(builder.methodref).packageId;
+                        final ClassData oldexpected =
+                            builder.classdata.get(builder.expected);
+                        final MethodData meth =
+                            new MethodData(MethodData.Access.PRIVATE,
+                                           MethodData.Context.INSTANCE);
+                        final ClassData withDef = new ClassData(pck, meth);
+                        final int C2 = builder.methodref;
+                        final int C1 = builder.addClass(withDef);
+                        builder.hier.addInherit(C1, C2);
+                        builder.objectref = C1;
+                    },
+                    /* Case 3: Objectref has static def.
+                     *
+                     * C2[](*) = mref
+                     * C1[C2](stat) = oref
+                     */
+                    (final SelectionResolutionTestCase.Builder builder) -> {
+                        final ClassData.Package pck =
+                            builder.classdata.get(builder.methodref).packageId;
+                        final ClassData oldexpected =
+                            builder.classdata.get(builder.expected);
+                        final MethodData meth =
+                            new MethodData(MethodData.Access.PUBLIC,
+                                           MethodData.Context.STATIC);
+                        final ClassData withDef = new ClassData(pck, meth);
+                        final int C2 = builder.methodref;
+                        final int C1 = builder.addClass(withDef);
+                        builder.hier.addInherit(C1, C2);
+                        builder.objectref = C1;
+                    },
+                    /* Case 4: Skip inherit from interface.
+                     *
+                     * C2[](*) = mref, I[](def)
+                     * C1[C2,I]() = oref
+                     */
+                    (final SelectionResolutionTestCase.Builder builder) -> {
+                        final ClassData oldexpected =
+                            builder.classdata.get(builder.expected);
+                        final ClassData.Package pck = oldexpected.packageId;
+                        final MethodData.Context ctx =
+                            builder.classdata.get(builder.expected).methoddata.context;
+                        final MethodData.Access acc =
+                            builder.classdata.get(builder.expected).methoddata.access;
+                        final MethodData mdata = getMethodData(acc, ctx);
+                        final ClassData withDef = new ClassData(pck, mdata);
+                        final int C2 = builder.methodref;
+                        final int C1 = builder.addClass(emptyClass(pck));
+                        final int I = builder.addInterface(withDef);
+                        builder.hier.addInherit(C1, C2);
+                        builder.hier.addInherit(C1, I);
+                        builder.objectref = C1;
+                    },
+                    /* Case 5: Objectref's super has a private def.
+                     *
+                     * C3[*](*) = mref
+                     * C2[C3](res) = expected
+                     * C1[C2]() = oref
+                     */
+                    (final SelectionResolutionTestCase.Builder builder) -> {
+                        final ClassData.Package pck =
+                            builder.classdata.get(builder.methodref).packageId;
+                        final ClassData oldexpected =
+                            builder.classdata.get(builder.expected);
+                        final MethodData meth =
+                            new MethodData(MethodData.Access.PRIVATE,
+                                           MethodData.Context.INSTANCE);
+                        final ClassData withDef =
+                            new ClassData(pck, meth);
+                        final int C3 = builder.methodref;
+                        final int C2 = builder.addClass(withDef);
+                        final int C1 = builder.addClass(emptyClass(pck));
+                        builder.hier.addInherit(C2, C3);
+                        builder.hier.addInherit(C1, C2);
+                        builder.objectref = C1;
+                    },
+                    /* Case 6: Objectref's super has a static def.
+                     *
+                     * C3[*](*) = mref
+                     * C2[C3](res) = expected
+                     * C1[C2]() = oref
+                     */
+                    (final SelectionResolutionTestCase.Builder builder) -> {
+                        final ClassData.Package pck =
+                            builder.classdata.get(builder.methodref).packageId;
+                        final ClassData oldexpected =
+                            builder.classdata.get(builder.expected);
+                        final MethodData meth =
+                            new MethodData(MethodData.Access.PUBLIC,
+                                           MethodData.Context.STATIC);
+                        final ClassData withDef =
+                            new ClassData(pck, meth);
+                        final int C3 = builder.methodref;
+                        final int C2 = builder.addClass(withDef);
+                        final int C1 = builder.addClass(emptyClass(pck));
+                        builder.hier.addInherit(C2, C3);
+                        builder.hier.addInherit(C1, C2);
+                        builder.objectref = C1;
+                    });
+
+    public static final Template MethodrefSelectionResolvedIsClassOverride =
+        new Template("MethodrefSelectionResolvedIsClassOverride",
+                    /* Case 7: Objectref overrides.
+                     *
+                     * C2[](*) = mref
+                     * C1[C2](res) = oref = expected
+                     */
+                    (final SelectionResolutionTestCase.Builder builder) -> {
+                        final ClassData.Package pck =
+                            builder.classdata.get(builder.methodref).packageId;
+                        final ClassData oldexpected =
+                            builder.classdata.get(builder.expected);
+                        final ClassData withDef =
+                            new ClassData(pck, oldexpected.methoddata);
+                        final int C2 = builder.methodref;
+                        final int C1 = builder.addClass(withDef);
+                        builder.hier.addInherit(C1, C2);
+                        builder.objectref = C1;
+                        builder.expected = C1;
+                    },
+                    /* Case 8: Objectref's super overrides.
+                     *
+                     * C3[*](*) = mref
+                     * C2[C3](res)
+                     * C1[C2]() = oref
+                     */
+                    (final SelectionResolutionTestCase.Builder builder) -> {
+                        final ClassData.Package pck =
+                            builder.classdata.get(builder.methodref).packageId;
+                        final ClassData oldexpected =
+                            builder.classdata.get(builder.expected);
+                        final ClassData withDef =
+                            new ClassData(pck, oldexpected.methoddata);
+                        final int C3 = builder.methodref;
+                        final int C2 = builder.addClass(withDef);
+                        final int C1 = builder.addClass(emptyClass(pck));
+                        builder.hier.addInherit(C2, C3);
+                        builder.hier.addInherit(C1, C2);
+                        builder.objectref = C1;
+                        builder.expected = C2;
+                    },
+                    /* Case 9: Objectref's super overrides,
+                     *         objectref has a private def.
+                     *
+                     * C3[*](*) = mref
+                     * C2[C3](res)
+                     * C1[C2](priv) = oref
+                     */
+                    (final SelectionResolutionTestCase.Builder builder) -> {
+                        final ClassData.Package pck =
+                            builder.classdata.get(builder.methodref).packageId;
+                        final ClassData oldexpected =
+                            builder.classdata.get(builder.expected);
+                        final ClassData withDef =
+                            new ClassData(pck, oldexpected.methoddata);
+                        final MethodData meth =
+                            new MethodData(MethodData.Access.PRIVATE,
+                                           MethodData.Context.INSTANCE);
+                        final ClassData withPrivDef =
+                            new ClassData(pck, meth);
+                        final int C3 = builder.methodref;
+                        final int C2 = builder.addClass(withDef);
+                        final int C1 = builder.addClass(withPrivDef);
+                        builder.hier.addInherit(C2, C3);
+                        builder.hier.addInherit(C1, C2);
+                        builder.objectref = C1;
+                        builder.expected = C2;
+                    },
+                    /* Case 10: Objectref's super overrides,
+                     *          objectref has a static def.
+                     *
+                     * C3[*](*) = mref
+                     * C2[C3](res)
+                     * C1[C2](stat) = oref
+                     */
+                    (final SelectionResolutionTestCase.Builder builder) -> {
+                        final ClassData.Package pck =
+                            builder.classdata.get(builder.methodref).packageId;
+                        final ClassData oldexpected =
+                            builder.classdata.get(builder.expected);
+                        final ClassData withDef =
+                            new ClassData(pck, oldexpected.methoddata);
+                        final MethodData meth =
+                            new MethodData(MethodData.Access.PUBLIC,
+                                           MethodData.Context.STATIC);
+                        final ClassData withPrivDef =
+                            new ClassData(pck, meth);
+                        final int C3 = builder.methodref;
+                        final int C2 = builder.addClass(withDef);
+                        final int C1 = builder.addClass(withPrivDef);
+                        builder.hier.addInherit(C2, C3);
+                        builder.hier.addInherit(C1, C2);
+                        builder.objectref = C1;
+                        builder.expected = C2;
+                    });
+
+    public static final Template MethodrefSelectionResolvedIsClass =
+        new Template("MethodrefSelectionResolvedIsClass",
+                     MethodrefSelectionResolvedIsClassNoOverride,
+                     MethodrefSelectionResolvedIsClassOverride);
+
+    public static final Template MethodrefSelectionPackageSkipNoOverride =
+        new Template("MethodrefSelectionPackageSkipNoOverride",
+                     MethodrefSelectionResolvedIsClass,
+                    /* Case 11: Objectref has public def in other package.
+                     *
+                     * C2[](*) = mref
+                     * Other.C1[C2](pub) = oref
+                     */
+                    (final SelectionResolutionTestCase.Builder builder) -> {
+                        final ClassData.Package pck =
+                            builder.classdata.get(builder.methodref).packageId;
+                        final ClassData oldexpected =
+                            builder.classdata.get(builder.expected);
+                        final MethodData meth =
+                            new MethodData(MethodData.Access.PUBLIC,
+                                           MethodData.Context.INSTANCE);
+                        final ClassData withDef =
+                            new ClassData(ClassData.Package.OTHER, meth);
+                        final int C2 = builder.methodref;
+                        final int C1 = builder.addClass(withDef);
+                        builder.hier.addInherit(C1, C2);
+                        builder.objectref = C1;
+                    },
+                    /* Case 12: Objectref has package private def in other package.
+                     *
+                     * C2[](*) = mref
+                     * Other.C1[C2](pack) = oref
+                     */
+                    (final SelectionResolutionTestCase.Builder builder) -> {
+                        final ClassData.Package pck =
+                            builder.classdata.get(builder.methodref).packageId;
+                        final ClassData oldexpected =
+                            builder.classdata.get(builder.expected);
+                        final MethodData meth =
+                            new MethodData(MethodData.Access.PACKAGE,
+                                           MethodData.Context.INSTANCE);
+                        final ClassData withDef =
+                            new ClassData(ClassData.Package.OTHER, meth);
+                        final int C2 = builder.methodref;
+                        final int C1 = builder.addClass(withDef);
+                        builder.hier.addInherit(C1, C2);
+                        builder.objectref = C1;
+                    },
+                    /* Case 13: Objectref has protected def in other package.
+                     *
+                     * C2[](*) = mref
+                     * Other.C1[C2](prot) = oref
+                     */
+                    (final SelectionResolutionTestCase.Builder builder) -> {
+                        final ClassData.Package pck =
+                            builder.classdata.get(builder.methodref).packageId;
+                        final ClassData oldexpected =
+                            builder.classdata.get(builder.expected);
+                        final MethodData meth =
+                            new MethodData(MethodData.Access.PROTECTED,
+                                           MethodData.Context.INSTANCE);
+                        final ClassData withDef =
+                            new ClassData(ClassData.Package.OTHER, meth);
+                        final int C2 = builder.methodref;
+                        final int C1 = builder.addClass(withDef);
+                        builder.hier.addInherit(C1, C2);
+                        builder.objectref = C1;
+                    },
+                    /* Case 14: Objectref's super has a public def in other package.
+                     *
+                     * C3[*](*) = mref
+                     * Other.C2[C3](pub) = expected
+                     * C1[C2]() = oref
+                     */
+                    (final SelectionResolutionTestCase.Builder builder) -> {
+                        final ClassData.Package pck =
+                            builder.classdata.get(builder.methodref).packageId;
+                        final ClassData oldexpected =
+                            builder.classdata.get(builder.expected);
+                        final MethodData meth =
+                            new MethodData(MethodData.Access.PUBLIC,
+                                           MethodData.Context.INSTANCE);
+                        final ClassData withDef =
+                            new ClassData(ClassData.Package.OTHER, meth);
+                        final int C3 = builder.methodref;
+                        final int C2 = builder.addClass(withDef);
+                        final int C1 = builder.addClass(emptyClass(pck));
+                        builder.hier.addInherit(C2, C3);
+                        builder.hier.addInherit(C1, C2);
+                        builder.objectref = C1;
+                    },
+                    /* Case 15: Objectref's super has a package
+                     * private def in other package.
+                     *
+                     * C3[*](*) = mref
+                     * Other.C2[C3](pack) = expected
+                     * C1[C2]() = oref
+                     */
+                    (final SelectionResolutionTestCase.Builder builder) -> {
+                        final ClassData.Package pck =
+                            builder.classdata.get(builder.methodref).packageId;
+                        final ClassData oldexpected =
+                            builder.classdata.get(builder.expected);
+                        final MethodData meth =
+                            new MethodData(MethodData.Access.PACKAGE,
+                                           MethodData.Context.INSTANCE);
+                        final ClassData withDef =
+                            new ClassData(ClassData.Package.OTHER, meth);
+                        final int C3 = builder.methodref;
+                        final int C2 = builder.addClass(withDef);
+                        final int C1 = builder.addClass(emptyClass(pck));
+                        builder.hier.addInherit(C2, C3);
+                        builder.hier.addInherit(C1, C2);
+                        builder.objectref = C1;
+                    },
+                    /* Case 16: Objectref's super has a protected def
+                     * in other package.
+                     *
+                     * C3[*](*) = mref
+                     * Other.C2[C3](pack) = expected
+                     * C1[C2]() = oref
+                     */
+                    (final SelectionResolutionTestCase.Builder builder) -> {
+                        final ClassData.Package pck =
+                            builder.classdata.get(builder.methodref).packageId;
+                        final ClassData oldexpected =
+                            builder.classdata.get(builder.expected);
+                        final MethodData meth =
+                            new MethodData(MethodData.Access.PROTECTED,
+                                           MethodData.Context.INSTANCE);
+                        final ClassData withDef =
+                            new ClassData(ClassData.Package.OTHER, meth);
+                        final int C3 = builder.methodref;
+                        final int C2 = builder.addClass(withDef);
+                        final int C1 = builder.addClass(emptyClass(pck));
+                        builder.hier.addInherit(C2, C3);
+                        builder.hier.addInherit(C1, C2);
+                        builder.objectref = C1;
+                    },
+                    /* Case 18: Objectref's has a public def in other
+                     * package, skip private.
+                     *
+                     * C3[*](*) = mref
+                     * Other.C2[C3](priv)
+                     * C1[C2](pub) = oref, expected
+                     */
+                    (final SelectionResolutionTestCase.Builder builder) -> {
+                        final ClassData.Package pck =
+                            builder.classdata.get(builder.methodref).packageId;
+                        final ClassData oldexpected =
+                            builder.classdata.get(builder.expected);
+                        final MethodData meth =
+                            new MethodData(MethodData.Access.PUBLIC,
+                                           MethodData.Context.INSTANCE);
+                        final ClassData withDef =
+                            new ClassData(ClassData.Package.OTHER, meth);
+                        final MethodData privmeth =
+                            new MethodData(MethodData.Access.PRIVATE,
+                                           MethodData.Context.INSTANCE);
+                        final ClassData withPrivDef =
+                            new ClassData(pck, privmeth);
+                        final int C3 = builder.methodref;
+                        final int C2 = builder.addClass(withPrivDef);
+                        final int C1 = builder.addClass(withDef);
+                        builder.hier.addInherit(C2, C3);
+                        builder.hier.addInherit(C1, C2);
+                        builder.objectref = C1;
+                    },
+                    /* Case 19: Objectref's has a package private def in other
+                     * package, skip private.
+                     *
+                     * C3[*](*) = mref
+                     * Other.C2[C3](priv)
+                     * C1[C2](pack) = oref, expected
+                     */
+                    (final SelectionResolutionTestCase.Builder builder) -> {
+                        final ClassData.Package pck =
+                            builder.classdata.get(builder.methodref).packageId;
+                        final ClassData oldexpected =
+                            builder.classdata.get(builder.expected);
+                        final MethodData meth =
+                            new MethodData(MethodData.Access.PACKAGE,
+                                           MethodData.Context.INSTANCE);
+                        final ClassData withDef =
+                            new ClassData(ClassData.Package.OTHER, meth);
+                        final MethodData privmeth =
+                            new MethodData(MethodData.Access.PRIVATE,
+                                           MethodData.Context.INSTANCE);
+                        final ClassData withPrivDef =
+                            new ClassData(pck, privmeth);
+                        final int C3 = builder.methodref;
+                        final int C2 = builder.addClass(withPrivDef);
+                        final int C1 = builder.addClass(withDef);
+                        builder.hier.addInherit(C2, C3);
+                        builder.hier.addInherit(C1, C2);
+                        builder.objectref = C1;
+                    },
+                    /* Case 20: Objectref's has a protected def in other
+                     * package, skip private.
+                     *
+                     * C3[*](*) = mref
+                     * Other.C2[C3](priv)
+                     * C1[C2](pro) = oref, expected
+                     */
+                    (final SelectionResolutionTestCase.Builder builder) -> {
+                        final ClassData.Package pck =
+                            builder.classdata.get(builder.methodref).packageId;
+                        final ClassData oldexpected =
+                            builder.classdata.get(builder.expected);
+                        final MethodData meth =
+                            new MethodData(MethodData.Access.PROTECTED,
+                                           MethodData.Context.INSTANCE);
+                        final ClassData withDef =
+                            new ClassData(ClassData.Package.OTHER, meth);
+                        final MethodData privmeth =
+                            new MethodData(MethodData.Access.PRIVATE,
+                                           MethodData.Context.INSTANCE);
+                        final ClassData withPrivDef =
+                            new ClassData(pck, privmeth);
+                        final int C3 = builder.methodref;
+                        final int C2 = builder.addClass(withPrivDef);
+                        final int C1 = builder.addClass(withDef);
+                        builder.hier.addInherit(C2, C3);
+                        builder.hier.addInherit(C1, C2);
+                        builder.objectref = C1;
+                    },
+                    /* Case 21: Objectref's super has a public def in other
+                     * package, skip private.
+                     *
+                     * C3[*](*) = mref
+                     * Other.C2[C3](pub) = expected
+                     * C1[C2](priv) = oref
+                     */
+                    (final SelectionResolutionTestCase.Builder builder) -> {
+                        final ClassData.Package pck =
+                            builder.classdata.get(builder.methodref).packageId;
+                        final ClassData oldexpected =
+                            builder.classdata.get(builder.expected);
+                        final MethodData meth =
+                            new MethodData(MethodData.Access.PUBLIC,
+                                           MethodData.Context.INSTANCE);
+                        final ClassData withDef =
+                            new ClassData(ClassData.Package.OTHER, meth);
+                        final MethodData privmeth =
+                            new MethodData(MethodData.Access.PRIVATE,
+                                           MethodData.Context.INSTANCE);
+                        final ClassData withPrivDef =
+                            new ClassData(pck, privmeth);
+                        final int C3 = builder.methodref;
+                        final int C2 = builder.addClass(withDef);
+                        final int C1 = builder.addClass(withPrivDef);
+                        builder.hier.addInherit(C2, C3);
+                        builder.hier.addInherit(C1, C2);
+                        builder.objectref = C1;
+                    },
+                    /* Case 22: Objectref's superhas a package private
+                     * def in other package, skip private.
+                     *
+                     * C3[*](*) = mref
+                     * Other.C2[C3](pack) = expected
+                     * C1[C2](priv) = oref
+                     */
+                    (final SelectionResolutionTestCase.Builder builder) -> {
+                        final ClassData.Package pck =
+                            builder.classdata.get(builder.methodref).packageId;
+                        final ClassData oldexpected =
+                            builder.classdata.get(builder.expected);
+                        final MethodData meth =
+                            new MethodData(MethodData.Access.PACKAGE,
+                                           MethodData.Context.INSTANCE);
+                        final ClassData withDef =
+                            new ClassData(ClassData.Package.OTHER, meth);
+                        final MethodData privmeth =
+                            new MethodData(MethodData.Access.PRIVATE,
+                                           MethodData.Context.INSTANCE);
+                        final ClassData withPrivDef =
+                            new ClassData(pck, privmeth);
+                        final int C3 = builder.methodref;
+                        final int C2 = builder.addClass(withDef);
+                        final int C1 = builder.addClass(withPrivDef);
+                        builder.hier.addInherit(C2, C3);
+                        builder.hier.addInherit(C1, C2);
+                        builder.objectref = C1;
+                    },
+                    /* Case 23: Objectref's super has a protected def
+                     * in other package, skip private.
+                     *
+                     * C3[*](*) = mref
+                     * Other.C2[C3](pro) = expected
+                     * C1[C2](priv) = oref
+                     */
+                    (final SelectionResolutionTestCase.Builder builder) -> {
+                        final ClassData.Package pck =
+                            builder.classdata.get(builder.methodref).packageId;
+                        final ClassData oldexpected =
+                            builder.classdata.get(builder.expected);
+                        final MethodData meth =
+                            new MethodData(MethodData.Access.PROTECTED,
+                                           MethodData.Context.INSTANCE);
+                        final ClassData withDef =
+                            new ClassData(ClassData.Package.OTHER, meth);
+                        final MethodData privmeth =
+                            new MethodData(MethodData.Access.PRIVATE,
+                                           MethodData.Context.INSTANCE);
+                        final ClassData withPrivDef =
+                            new ClassData(pck, privmeth);
+                        final int C3 = builder.methodref;
+                        final int C2 = builder.addClass(withPrivDef);
+                        final int C1 = builder.addClass(withDef);
+                        builder.hier.addInherit(C2, C3);
+                        builder.hier.addInherit(C1, C2);
+                        builder.objectref = C1;
+                    });
+
+    public static final Template MethodrefSelectionPackageSkip =
+        new Template("MethodrefSelectionPackageSkip",
+                     MethodrefSelectionPackageSkipNoOverride,
+                    /* Case 17: Transitive override.
+                     *
+                     * C3[*](*) = mref
+                     * C2[C3](pub)
+                     * Other.C1[C2](pack) = oref, expected
+                     */
+                    (final SelectionResolutionTestCase.Builder builder) -> {
+                        final ClassData.Package pck =
+                            builder.classdata.get(builder.expected).packageId;
+                        final ClassData oldexpected =
+                            builder.classdata.get(builder.expected);
+                        final MethodData meth =
+                            new MethodData(MethodData.Access.PUBLIC,
+                                           MethodData.Context.INSTANCE);
+                        final MethodData packmeth =
+                            new MethodData(MethodData.Access.PACKAGE,
+                                           MethodData.Context.INSTANCE);
+                        final ClassData withPubDef = new ClassData(pck, meth);
+                        final ClassData withPackDef =
+                            new ClassData(ClassData.Package.OTHER, packmeth);
+                        final int C3 = builder.methodref;
+                        final int C2 = builder.addClass(withPubDef);
+                        final int C1 = builder.addClass(withPackDef);
+                        builder.hier.addInherit(C2, C3);
+                        builder.hier.addInherit(C1, C2);
+                        builder.objectref = C1;
+                        builder.expected = C1;
+                    },
+                    /* Case 24: Transitive override, skip private in between.
+                     *
+                     * C4[*](*) = mref
+                     * C3[C4](pub)
+                     * C2[C3](priv)
+                     * Other.C1[C2](pack) = oref, expected
+                     */
+                    (final SelectionResolutionTestCase.Builder builder) -> {
+                        final ClassData.Package pck =
+                            builder.classdata.get(builder.expected).packageId;
+                        final ClassData oldexpected =
+                            builder.classdata.get(builder.expected);
+                        final MethodData meth =
+                            new MethodData(MethodData.Access.PUBLIC,
+                                           MethodData.Context.INSTANCE);
+                        final MethodData packmeth =
+                            new MethodData(MethodData.Access.PACKAGE,
+                                           MethodData.Context.INSTANCE);
+                        final ClassData withPubDef = new ClassData(pck, meth);
+                        final ClassData withPackDef =
+                            new ClassData(ClassData.Package.OTHER, packmeth);
+                        final MethodData privmeth =
+                            new MethodData(MethodData.Access.PRIVATE,
+                                           MethodData.Context.INSTANCE);
+                        final ClassData withPrivDef =
+                            new ClassData(pck, privmeth);
+                        final int C4 = builder.methodref;
+                        final int C3 = builder.addClass(withPubDef);
+                        final int C2 = builder.addClass(withPrivDef);
+                        final int C1 = builder.addClass(withPackDef);
+                        builder.hier.addInherit(C3, C4);
+                        builder.hier.addInherit(C2, C3);
+                        builder.hier.addInherit(C1, C2);
+                        builder.objectref = C1;
+                        builder.expected = C1;
+                    },
+                    /* Case 25: Transitive override, skip private in between.
+                     *
+                     * C4[*](*) = mref
+                     * C3[C4](pub)
+                     * Other.C2[C3](pack) = expected
+                     * C1[C2](pack) = oref
+                     */
+                    (final SelectionResolutionTestCase.Builder builder) -> {
+                        final ClassData.Package pck =
+                            builder.classdata.get(builder.expected).packageId;
+                        final ClassData oldexpected =
+                            builder.classdata.get(builder.expected);
+                        final MethodData meth =
+                            new MethodData(MethodData.Access.PUBLIC,
+                                           MethodData.Context.INSTANCE);
+                        final MethodData packmeth =
+                            new MethodData(MethodData.Access.PACKAGE,
+                                           MethodData.Context.INSTANCE);
+                        final ClassData withPubDef = new ClassData(pck, meth);
+                        final ClassData withPackDef =
+                            new ClassData(ClassData.Package.OTHER, packmeth);
+                        final MethodData privmeth =
+                            new MethodData(MethodData.Access.PRIVATE,
+                                           MethodData.Context.INSTANCE);
+                        final ClassData withPrivDef =
+                            new ClassData(pck, privmeth);
+                        final int C4 = builder.methodref;
+                        final int C3 = builder.addClass(withPubDef);
+                        final int C2 = builder.addClass(withPackDef);
+                        final int C1 = builder.addClass(withPrivDef);
+                        builder.hier.addInherit(C3, C4);
+                        builder.hier.addInherit(C2, C3);
+                        builder.hier.addInherit(C1, C2);
+                        builder.objectref = C2;
+                        builder.expected = C2;
+                    });
+
+    public static final Template MethodrefSelectionResolvedIsIfaceNoOverride =
+        new Template("MethodrefSelectionResolvedIsIfaceNoOverride",
+                    /* Trivial objectref.
+                     *
+                     * C[](*) = mref = oref
+                     */
+                    (builder) -> {
+                        builder.objectref = builder.methodref;
+                    },
+                    /* Case 1: Inherit from super.
+                     *
+                     * C2[](*) = mref
+                     * C1[C2]() = oref
+                     */
+                    (final SelectionResolutionTestCase.Builder builder) -> {
+                        final ClassData.Package pck =
+                            builder.classdata.get(builder.methodref).packageId;
+                        final int C2 = builder.methodref;
+                        final int C1 = builder.addClass(emptyClass(pck));
+                        builder.hier.addInherit(C1, C2);
+                        builder.objectref = C1;
+                    },
+                    /* Case 2: Objectref has private def.
+                     *
+                     * C2[](*) = mref
+                     * C1[C2](priv) = oref
+                     */
+                    (final SelectionResolutionTestCase.Builder builder) -> {
+                        final ClassData.Package pck =
+                            builder.classdata.get(builder.methodref).packageId;
+                        final ClassData oldexpected =
+                            builder.classdata.get(builder.expected);
+                        final MethodData meth =
+                            new MethodData(MethodData.Access.PRIVATE,
+                                           MethodData.Context.INSTANCE);
+                        final ClassData withDef = new ClassData(pck, meth);
+                        final int C2 = builder.methodref;
+                        final int C1 = builder.addClass(withDef);
+                        builder.hier.addInherit(C1, C2);
+                        builder.objectref = C1;
+                    },
+                    /* Case 3: Objectref has static def.
+                     *
+                     * C2[](*) = mref
+                     * C1[C2](stat) = oref
+                     */
+                    (final SelectionResolutionTestCase.Builder builder) -> {
+                        final ClassData.Package pck =
+                            builder.classdata.get(builder.methodref).packageId;
+                        final ClassData oldexpected =
+                            builder.classdata.get(builder.expected);
+                        final MethodData meth =
+                            new MethodData(MethodData.Access.PUBLIC,
+                                           MethodData.Context.STATIC);
+                        final ClassData withDef = new ClassData(pck, meth);
+                        final int C2 = builder.methodref;
+                        final int C1 = builder.addClass(withDef);
+                        builder.hier.addInherit(C1, C2);
+                        builder.objectref = C1;
+                    },
+                    /* Case 4: Overlapping.
+                     *
+                     * I[*](res) = expected
+                     * C2[*](*) = mref
+                     * C1[C2,I]() = oref
+                     */
+                    (final SelectionResolutionTestCase.Builder builder) -> {
+                        final ClassData.Package pck =
+                            builder.classdata.get(builder.methodref).packageId;
+                        final int C2 = builder.methodref;
+                        final int I = builder.expected;
+                        final int C1 = builder.addClass(emptyClass(pck));
+                        builder.hier.addInherit(C1, C2);
+                        builder.hier.addInherit(C1, I);
+                        builder.objectref = C1;
+                    },
+                    /* Case 5: Overlapping with new interface.
+                     *
+                     * I2[*](res) = expected
+                     * C2[*](*) = mref, I1[I2]()
+                     * C1[C2,I2]() = oref
+                     */
+                    (final SelectionResolutionTestCase.Builder builder) -> {
+                        final ClassData.Package pck =
+                            builder.classdata.get(builder.methodref).packageId;
+                        final int C2 = builder.methodref;
+                        final int I2 = builder.expected;
+                        final int I1 = builder.addInterface(emptyClass(pck));
+                        final int C1 = builder.addClass(emptyClass(pck));
+                        builder.hier.addInherit(C1, C2);
+                        builder.hier.addInherit(C1, I1);
+                        builder.hier.addInherit(I1, I2);
+                        builder.objectref = C1;
+                    },
+                    /* Case 6: Overlapping with new interface with private def.
+                     *
+                     * I2[*](res) = expected
+                     * C2[*](*) = mref, I1[I2](priv)
+                     * C1[C2,I2]() = oref
+                     */
+                    (final SelectionResolutionTestCase.Builder builder) -> {
+                        final ClassData.Package pck =
+                            builder.classdata.get(builder.methodref).packageId;
+                        final MethodData meth =
+                            new MethodData(MethodData.Access.PRIVATE,
+                                           MethodData.Context.INSTANCE);
+                        final ClassData withPrivDef =
+                            new ClassData(pck, meth);
+                        final int C2 = builder.methodref;
+                        final int I2 = builder.expected;
+                        final int I1 = builder.addInterface(withPrivDef);
+                        final int C1 = builder.addClass(emptyClass(pck));
+                        builder.hier.addInherit(C1, C2);
+                        builder.hier.addInherit(C1, I1);
+                        builder.hier.addInherit(I1, I2);
+                        builder.objectref = C1;
+                    },
+                    /* Case 7: Overlapping with new interface with static def.
+                     *
+                     * I2[*](res) = expected
+                     * C2[*](*) = mref, I1[I2](stat)
+                     * C1[C2,I2]() = oref
+                     */
+                    (final SelectionResolutionTestCase.Builder builder) -> {
+                        final ClassData.Package pck =
+                            builder.classdata.get(builder.methodref).packageId;
+                        final MethodData meth =
+                            new MethodData(MethodData.Access.PUBLIC,
+                                           MethodData.Context.STATIC);
+                        final ClassData withStatDef =
+                            new ClassData(pck, meth);
+                        final int C2 = builder.methodref;
+                        final int I2 = builder.expected;
+                        final int I1 = builder.addInterface(withStatDef);
+                        final int C1 = builder.addClass(emptyClass(pck));
+                        builder.hier.addInherit(C1, C2);
+                        builder.hier.addInherit(C1, I1);
+                        builder.hier.addInherit(I1, I2);
+                        builder.objectref = C1;
+                    },
+                    /* Case 8: Objectref's super has a private def.
+                     *
+                     * C3[*](*) = mref
+                     * C2[C3](priv)
+                     * C1[C2]() = oref
+                     */
+                    (final SelectionResolutionTestCase.Builder builder) -> {
+                        final ClassData.Package pck =
+                            builder.classdata.get(builder.methodref).packageId;
+                        final ClassData oldexpected =
+                            builder.classdata.get(builder.expected);
+                        final MethodData meth =
+                            new MethodData(MethodData.Access.PRIVATE,
+                                           MethodData.Context.INSTANCE);
+                        final ClassData withDef =
+                            new ClassData(pck, meth);
+                        final int C3 = builder.methodref;
+                        final int C2 = builder.addClass(withDef);
+                        final int C1 = builder.addClass(emptyClass(pck));
+                        builder.hier.addInherit(C2, C3);
+                        builder.hier.addInherit(C1, C2);
+                        builder.objectref = C1;
+                    },
+                    /* Case 9: Objectref's super has a static def.
+                     *
+                     * C3[*](*) = mref
+                     * C2[C3](stat)
+                     * C1[C2]() = oref
+                     */
+                    (final SelectionResolutionTestCase.Builder builder) -> {
+                        final ClassData.Package pck =
+                            builder.classdata.get(builder.methodref).packageId;
+                        final ClassData oldexpected =
+                            builder.classdata.get(builder.expected);
+                        final MethodData meth =
+                            new MethodData(MethodData.Access.PUBLIC,
+                                           MethodData.Context.STATIC);
+                        final ClassData withDef =
+                            new ClassData(pck, meth);
+                        final int C3 = builder.methodref;
+                        final int C2 = builder.addClass(withDef);
+                        final int C1 = builder.addClass(emptyClass(pck));
+                        builder.hier.addInherit(C2, C3);
+                        builder.hier.addInherit(C1, C2);
+                        builder.objectref = C1;
+                    },
+                    /* Case 10: Overlap with objectref's super.
+                     *
+                     * I[*](res) = expected
+                     * C3[](*) = mref
+                     * C2[C3,I]()
+                     * C1[C2]() = oref
+                     */
+                    (final SelectionResolutionTestCase.Builder builder) -> {
+                        final ClassData.Package pck =
+                            builder.classdata.get(builder.methodref).packageId;
+                        final int C3 = builder.methodref;
+                        final int C2 = builder.addClass(emptyClass(pck));
+                        final int I = builder.expected;
+                        final int C1 = builder.addClass(emptyClass(pck));
+                        builder.hier.addInherit(C2, C3);
+                        builder.hier.addInherit(C1, C2);
+                        builder.hier.addInherit(C2, I);
+                        builder.objectref = C1;
+                    },
+                    /* Case 11: Overlap with objectref's super with new interface.
+                     *
+                     * I2[*](res) = expected
+                     * C3[](*) = mref, I1[I2]()
+                     * C2[C3,I1]()
+                     * C1[C2]() = oref
+                     */
+                    (final SelectionResolutionTestCase.Builder builder) -> {
+                        final ClassData.Package pck =
+                            builder.classdata.get(builder.methodref).packageId;
+                        final int C3 = builder.methodref;
+                        final int C2 = builder.addClass(emptyClass(pck));
+                        final int I2 = builder.expected;
+                        final int I1 = builder.addInterface(emptyClass(pck));
+                        final int C1 = builder.addClass(emptyClass(pck));
+                        builder.hier.addInherit(C2, C3);
+                        builder.hier.addInherit(C1, C2);
+                        builder.hier.addInherit(C2, I1);
+                        builder.hier.addInherit(I1, I2);
+                        builder.objectref = C1;
+                    },
+                    /* Case 12: Overlap with objectref's super with new
+                     * interface with private def.
+                     *
+                     * I2[*](res) = expected
+                     * C3[](*) = mref, I1[I2](priv)
+                     * C2[C3,I1]()
+                     * C1[C2]() = oref
+                     */
+                    (final SelectionResolutionTestCase.Builder builder) -> {
+                        final ClassData.Package pck =
+                            builder.classdata.get(builder.methodref).packageId;
+                        final MethodData meth =
+                            new MethodData(MethodData.Access.PRIVATE,
+                                           MethodData.Context.INSTANCE);
+                        final ClassData withPrivDef =
+                            new ClassData(pck, meth);
+                        final int C3 = builder.methodref;
+                        final int C2 = builder.addClass(emptyClass(pck));
+                        final int I2 = builder.expected;
+                        final int I1 = builder.addInterface(withPrivDef);
+                        final int C1 = builder.addClass(emptyClass(pck));
+                        builder.hier.addInherit(C2, C3);
+                        builder.hier.addInherit(C1, C2);
+                        builder.hier.addInherit(C2, I1);
+                        builder.hier.addInherit(I1, I2);
+                        builder.objectref = C1;
+                    },
+                    /* Case 13: Overlap with objectref's super with new
+                     * interface with static def.
+                     *
+                     * I2[*](res) = expected
+                     * C3[](*) = mref, I1[I2](stat)
+                     * C2[C3,I1]()
+                     * C1[C2]() = oref
+                     */
+                    (final SelectionResolutionTestCase.Builder builder) -> {
+                        final ClassData.Package pck =
+                            builder.classdata.get(builder.methodref).packageId;
+                        final MethodData meth =
+                            new MethodData(MethodData.Access.PUBLIC,
+                                           MethodData.Context.STATIC);
+                        final ClassData withStatDef =
+                            new ClassData(pck, meth);
+                        final int C3 = builder.methodref;
+                        final int C2 = builder.addClass(emptyClass(pck));
+                        final int I2 = builder.expected;
+                        final int I1 = builder.addInterface(withStatDef);
+                        final int C1 = builder.addClass(emptyClass(pck));
+                        builder.hier.addInherit(C2, C3);
+                        builder.hier.addInherit(C1, C2);
+                        builder.hier.addInherit(C2, I1);
+                        builder.hier.addInherit(I1, I2);
+                        builder.objectref = C1;
+                    },
+                    /* Case 14: Overlap with objectref's super with new
+                     * interface double diamond.
+                     *
+                     * I3[*](res) = expected
+                     * C3[](*) = mref, I2[I3]()
+                     * C2[C3,I2](), I1[I2]()
+                     * C1[C2,I1]() = oref
+                     */
+                    (final SelectionResolutionTestCase.Builder builder) -> {
+                        final ClassData.Package pck =
+                            builder.classdata.get(builder.methodref).packageId;
+                        final int C3 = builder.methodref;
+                        final int C2 = builder.addClass(emptyClass(pck));
+                        final int I3 = builder.expected;
+                        final int I2 = builder.addInterface(emptyClass(pck));
+                        final int I1 = builder.addInterface(emptyClass(pck));
+                        final int C1 = builder.addClass(emptyClass(pck));
+                        builder.hier.addInherit(C2, C3);
+                        builder.hier.addInherit(C1, C2);
+                        builder.hier.addInherit(C1, I1);
+                        builder.hier.addInherit(C2, I2);
+                        builder.hier.addInherit(I1, I2);
+                        builder.objectref = C1;
+                    },
+                    /* Case 15: Overlapping with new interface with private def.
+                     *
+                     * C2[*](*) = mref, I1[](priv)
+                     * C1[C2,I2]() = oref
+                     */
+                    (final SelectionResolutionTestCase.Builder builder) -> {
+                        final ClassData.Package pck =
+                            builder.classdata.get(builder.methodref).packageId;
+                        final MethodData meth =
+                            new MethodData(MethodData.Access.PRIVATE,
+                                           MethodData.Context.INSTANCE);
+                        final ClassData withPrivDef =
+                            new ClassData(pck, meth);
+                        final int C2 = builder.methodref;
+                        final int I1 = builder.addInterface(withPrivDef);
+                        final int C1 = builder.addClass(emptyClass(pck));
+                        builder.hier.addInherit(C1, C2);
+                        builder.hier.addInherit(C1, I1);
+                        builder.objectref = C1;
+                    },
+                    /* Case 16: Overlapping with new interface with static def.
+                     *
+                     * C2[*](*) = mref, I1[](stat)
+                     * C1[C2,I2]() = oref
+                     */
+                    (final SelectionResolutionTestCase.Builder builder) -> {
+                        final ClassData.Package pck =
+                            builder.classdata.get(builder.methodref).packageId;
+                        final MethodData meth =
+                            new MethodData(MethodData.Access.PUBLIC,
+                                           MethodData.Context.STATIC);
+                        final ClassData withStatDef =
+                            new ClassData(pck, meth);
+                        final int C2 = builder.methodref;
+                        final int I1 = builder.addInterface(withStatDef);
+                        final int C1 = builder.addClass(emptyClass(pck));
+                        builder.hier.addInherit(C1, C2);
+                        builder.hier.addInherit(C1, I1);
+                        builder.objectref = C1;
+                    });
+
+    public static final Template MethodrefSelectionResolvedIsIface =
+        new Template("MethodrefSelectionResolvedIsIface",
+                     MethodrefSelectionResolvedIsIfaceNoOverride,
+                    /* Case 17: Objectref overrides.
+                     *
+                     * C2[](*) = mref
+                     * C1[C2](res) = oref = expected
+                     */
+                    (final SelectionResolutionTestCase.Builder builder) -> {
+                        final ClassData.Package pck =
+                            builder.classdata.get(builder.methodref).packageId;
+                        final ClassData oldexpected =
+                            builder.classdata.get(builder.expected);
+                        final ClassData withDef =
+                            new ClassData(pck, oldexpected.methoddata);
+                        final int C2 = builder.methodref;
+                        final int C1 = builder.addClass(withDef);
+                        builder.hier.addInherit(C1, C2);
+                        builder.objectref = C1;
+                        builder.expected = C1;
+                    },
+                    /* Case 18: Overlapping with new interface overriding.
+                     *
+                     * I2[*](def) = old expected
+                     * C2[*](*) = mref, I1[I2](res) = expected
+                     * C1[C2,I2]() = oref
+                     */
+                    (final SelectionResolutionTestCase.Builder builder) -> {
+                        final ClassData.Package pck =
+                            builder.classdata.get(builder.methodref).packageId;
+                        final ClassData oldexpected =
+                            builder.classdata.get(builder.expected);
+                        final ClassData withDef =
+                            new ClassData(pck, oldexpected.methoddata);
+                        final int C2 = builder.methodref;
+                        final int I2 = builder.expected;
+                        final int I1 = builder.addInterface(withDef);
+                        final int C1 = builder.addClass(emptyClass(pck));
+                        builder.hier.addInherit(C1, C2);
+                        builder.hier.addInherit(C1, I1);
+                        builder.hier.addInherit(I1, I2);
+                        builder.objectref = C1;
+                        builder.expected = I1;
+                    },
+                    /* Case 19: Objectref's super overrides.
+                     *
+                     * C3[](*) = mref
+                     * C2[C3](res) = expected
+                     * C1[C2]() = oref
+                     */
+                    (final SelectionResolutionTestCase.Builder builder) -> {
+                        final ClassData.Package pck =
+                            builder.classdata.get(builder.methodref).packageId;
+                        final ClassData oldexpected =
+                            builder.classdata.get(builder.expected);
+                        final ClassData withDef =
+                            new ClassData(pck, oldexpected.methoddata);
+                        final int C3 = builder.methodref;
+                        final int C2 = builder.addClass(withDef);
+                        final int C1 = builder.addClass(emptyClass(pck));
+                        builder.hier.addInherit(C2, C3);
+                        builder.hier.addInherit(C1, C2);
+                        builder.objectref = C1;
+                        builder.expected = C2;
+                    },
+                    /* Case 20: Overlap with objectref's super with
+                     * new interface overriding.
+                     *
+                     * I2[*](def) = old expected
+                     * C3[](*) = mref, I1[I2](res) = expected
+                     * C2[C3,I1]()
+                     * C1[C2]() = oref
+                     */
+                    (final SelectionResolutionTestCase.Builder builder) -> {
+                        final ClassData.Package pck =
+                            builder.classdata.get(builder.methodref).packageId;
+                        final ClassData oldexpected =
+                            builder.classdata.get(builder.expected);
+                        final ClassData withDef =
+                            new ClassData(pck, oldexpected.methoddata);
+                        final int C3 = builder.methodref;
+                        final int C2 = builder.addClass(emptyClass(pck));
+                        final int I2 = builder.expected;
+                        final int I1 = builder.addInterface(withDef);
+                        final int C1 = builder.addClass(emptyClass(pck));
+                        builder.hier.addInherit(C2, C3);
+                        builder.hier.addInherit(C1, C2);
+                        builder.hier.addInherit(C2, I1);
+                        builder.hier.addInherit(I1, I2);
+                        builder.objectref = C1;
+                        builder.expected = I1;
+                    },
+                    /* Case 21: Overlap with objectref's super with new
+                     * interface double diamond, overriding.
+                     *
+                     * I3[*](def) = old expected
+                     * C3[](*) = mref, I2[I3](def)
+                     * C2[C3,I2](), I1[I2](res) = expected
+                     * C1[C2,I1]() = oref
+                     */
+                    (final SelectionResolutionTestCase.Builder builder) -> {
+                        final ClassData.Package pck =
+                            builder.classdata.get(builder.methodref).packageId;
+                        final ClassData oldexpected =
+                            builder.classdata.get(builder.expected);
+                        final ClassData withDef =
+                            new ClassData(pck, oldexpected.methoddata);
+                        final int C3 = builder.methodref;
+                        final int C2 = builder.addClass(emptyClass(pck));
+                        final int I3 = builder.expected;
+                        final int I2 = builder.addInterface(withDef);
+                        final int I1 = builder.addInterface(withDef);
+                        final int C1 = builder.addClass(emptyClass(pck));
+                        builder.hier.addInherit(C2, C3);
+                        builder.hier.addInherit(C1, C2);
+                        builder.hier.addInherit(C1, I1);
+                        builder.hier.addInherit(C2, I2);
+                        builder.hier.addInherit(I1, I2);
+                        builder.hier.addInherit(I2, I3);
+                        builder.objectref = C1;
+                        builder.expected = I1;
+                    },
+                    /* Case 22: Objectref's super overrides, skip private.
+                     *
+                     * C3[](*) = mref
+                     * C2[C3](res) = expected
+                     * C1[C2](priv) = oref
+                     */
+                    (final SelectionResolutionTestCase.Builder builder) -> {
+                        final ClassData.Package pck =
+                            builder.classdata.get(builder.methodref).packageId;
+                        final ClassData oldexpected =
+                            builder.classdata.get(builder.expected);
+                        final MethodData meth =
+                            new MethodData(MethodData.Access.PRIVATE,
+                                           MethodData.Context.INSTANCE);
+                        final ClassData withPrivDef =
+                            new ClassData(pck, meth);
+                        final ClassData withDef =
+                            new ClassData(pck, oldexpected.methoddata);
+                        final int C3 = builder.methodref;
+                        final int C2 = builder.addClass(withDef);
+                        final int C1 = builder.addClass(withPrivDef);
+                        builder.hier.addInherit(C2, C3);
+                        builder.hier.addInherit(C1, C2);
+                        builder.objectref = C1;
+                        builder.expected = C2;
+                    },
+                    /* Case 23: Objectref's super overrides, skip static.
+                     *
+                     * C3[](*) = mref
+                     * C2[C3](res) = expected
+                     * C1[C2](stat) = oref
+                     */
+                    (final SelectionResolutionTestCase.Builder builder) -> {
+                        final ClassData.Package pck =
+                            builder.classdata.get(builder.methodref).packageId;
+                        final ClassData oldexpected =
+                            builder.classdata.get(builder.expected);
+                        final MethodData meth =
+                            new MethodData(MethodData.Access.PUBLIC,
+                                           MethodData.Context.STATIC);
+                        final ClassData withStatDef =
+                            new ClassData(pck, meth);
+                        final ClassData withDef =
+                            new ClassData(pck, oldexpected.methoddata);
+                        final int C3 = builder.methodref;
+                        final int C2 = builder.addClass(withDef);
+                        final int C1 = builder.addClass(withStatDef);
+                        builder.hier.addInherit(C2, C3);
+                        builder.hier.addInherit(C1, C2);
+                        builder.objectref = C1;
+                        builder.expected = C2;
+                    },
+                    /* Case 24: Overlap with objectref's super with new
+                     * interface double diamond, overriding, skip private.
+                     *
+                     * I3[*](def) = old expected
+                     * C3[](*) = mref, I2[I3](res) = expected
+                     * C2[C3,I2](), I1[I2](priv)
+                     * C1[C2,I1]() = oref
+                     */
+                    (final SelectionResolutionTestCase.Builder builder) -> {
+                        final ClassData.Package pck =
+                            builder.classdata.get(builder.methodref).packageId;
+                        final ClassData oldexpected =
+                            builder.classdata.get(builder.expected);
+                        final ClassData withDef =
+                            new ClassData(pck, oldexpected.methoddata);
+                        final MethodData meth =
+                            new MethodData(MethodData.Access.PRIVATE,
+                                           MethodData.Context.INSTANCE);
+                        final ClassData withPrivDef =
+                            new ClassData(pck, meth);
+                        final int C3 = builder.methodref;
+                        final int C2 = builder.addClass(emptyClass(pck));
+                        final int I3 = builder.expected;
+                        final int I2 = builder.addInterface(withDef);
+                        final int I1 = builder.addInterface(withPrivDef);
+                        final int C1 = builder.addClass(emptyClass(pck));
+                        builder.hier.addInherit(C2, C3);
+                        builder.hier.addInherit(C1, C2);
+                        builder.hier.addInherit(C1, I1);
+                        builder.hier.addInherit(C2, I2);
+                        builder.hier.addInherit(I1, I2);
+                        builder.hier.addInherit(I2, I3);
+                        builder.objectref = C1;
+                        builder.expected = I2;
+                    },
+                    /* Case 25: Overlap with objectref's super with new
+                     * interface double diamond, overriding, skip static.
+                     *
+                     * I3[*](def) = old expected
+                     * C3[](*) = mref, I2[I3](res) = expected
+                     * C2[C3,I2](), I1[I2](stat)
+                     * C1[C2,I1]() = oref
+                     */
+                    (final SelectionResolutionTestCase.Builder builder) -> {
+                        final ClassData.Package pck =
+                            builder.classdata.get(builder.methodref).packageId;
+                        final ClassData oldexpected =
+                            builder.classdata.get(builder.expected);
+                        final ClassData withDef =
+                            new ClassData(pck, oldexpected.methoddata);
+                        final MethodData meth =
+                            new MethodData(MethodData.Access.PUBLIC,
+                                           MethodData.Context.STATIC);
+                        final ClassData withStatDef =
+                            new ClassData(pck, meth);
+                        final int C3 = builder.methodref;
+                        final int C2 = builder.addClass(emptyClass(pck));
+                        final int I3 = builder.expected;
+                        final int I2 = builder.addInterface(withDef);
+                        final int I1 = builder.addInterface(withStatDef);
+                        final int C1 = builder.addClass(emptyClass(pck));
+                        builder.hier.addInherit(C2, C3);
+                        builder.hier.addInherit(C1, C2);
+                        builder.hier.addInherit(C1, I1);
+                        builder.hier.addInherit(C2, I2);
+                        builder.hier.addInherit(I1, I2);
+                        builder.hier.addInherit(I2, I3);
+                        builder.objectref = C1;
+                        builder.expected = I2;
+                    },
+                    /* Case 26: Skip interface method after class overrides.
+                     *
+                     * C3[](*) = mref
+                     * C2[C3](res) = expected, I[](def)
+                     * C1[C2, I]() = oref
+                     */
+                    (final SelectionResolutionTestCase.Builder builder) -> {
+                        final ClassData.Package pck =
+                            builder.classdata.get(builder.methodref).packageId;
+                        final ClassData oldexpected =
+                            builder.classdata.get(builder.expected);
+                        final ClassData withDef =
+                            new ClassData(pck, oldexpected.methoddata);
+                        final int C3 = builder.methodref;
+                        final int C2 = builder.addClass(withDef);
+                        final int C1 = builder.addClass(emptyClass(pck));
+                        final int I = builder.addInterface(withDef);
+                        builder.hier.addInherit(C2, C3);
+                        builder.hier.addInherit(C1, C2);
+                        builder.hier.addInherit(C1, I);
+                        builder.objectref = C1;
+                        builder.expected = C2;
+                    },
+                    /* Case 27: Skip interface method after class overrides.
+                     *
+                     * C3[](*) = mref, I[](def)
+                     * C2[C3,I](res) = expected
+                     * C1[C2]() = oref
+                     */
+                    (final SelectionResolutionTestCase.Builder builder) -> {
+                        final ClassData.Package pck =
+                            builder.classdata.get(builder.methodref).packageId;
+                        final ClassData oldexpected =
+                            builder.classdata.get(builder.expected);
+                        final ClassData withDef =
+                            new ClassData(pck, oldexpected.methoddata);
+                        final int C3 = builder.methodref;
+                        final int C2 = builder.addClass(withDef);
+                        final int C1 = builder.addClass(emptyClass(pck));
+                        final int I = builder.addInterface(withDef);
+                        builder.hier.addInherit(C2, C3);
+                        builder.hier.addInherit(C1, C2);
+                        builder.hier.addInherit(C2, I);
+                        builder.objectref = C1;
+                        builder.expected = C2;
+                    },
+                    /* Case 28: Overlap with objectref's super with new
+                     * interface double diamond, overriding.
+                     *
+                     * I3[*](def) = old expected
+                     * C3[](*) = mref, I2[I3](def)
+                     * C2[C3,I2](res) = expected, I1[I2](def) = expected
+                     * C1[C2,I1]() = oref
+                     */
+                    (final SelectionResolutionTestCase.Builder builder) -> {
+                        final ClassData.Package pck =
+                            builder.classdata.get(builder.methodref).packageId;
+                        final ClassData oldexpected =
+                            builder.classdata.get(builder.expected);
+                        final ClassData withDef =
+                            new ClassData(pck, oldexpected.methoddata);
+                        final int C3 = builder.methodref;
+                        final int C2 = builder.addClass(withDef);
+                        final int I3 = builder.expected;
+                        final int I2 = builder.addInterface(withDef);
+                        final int I1 = builder.addInterface(withDef);
+                        final int C1 = builder.addClass(emptyClass(pck));
+                        builder.hier.addInherit(C2, C3);
+                        builder.hier.addInherit(C1, C2);
+                        builder.hier.addInherit(C1, I1);
+                        builder.hier.addInherit(C2, I2);
+                        builder.hier.addInherit(I1, I2);
+                        builder.hier.addInherit(I2, I3);
+                        builder.objectref = C1;
+                        builder.expected = C2;
+                    });
+
+    public static final Template IfaceMethodrefSelectionNoOverride =
+        new Template("IfaceMethodrefSelectionNoOverride",
+                     /* Case 1: Inherit from super.
+                      *
+                      * I[](*) = mref
+                      * C[I]() = oref
+                      */
+                     (final SelectionResolutionTestCase.Builder builder) -> {
+                         final ClassData.Package pck =
+                             builder.classdata.get(builder.methodref).packageId;
+                         final int I = builder.methodref;
+                         final int C = builder.addClass(emptyClass(pck));
+                         builder.hier.addInherit(C, I);
+                         builder.objectref = C;
+                     },
+                     /* Case 2: Objectref has static def
+                      *
+                      * I[](*) = mref
+                      * C[I](stat) = oref
+                      */
+                     (final SelectionResolutionTestCase.Builder builder) -> {
+                         final ClassData.Package pck =
+                             builder.classdata.get(builder.methodref).packageId;
+                         final MethodData meth =
+                             new MethodData(MethodData.Access.PUBLIC,
+                                            MethodData.Context.STATIC);
+                         final ClassData withStatDef =
+                             new ClassData(pck, meth);
+                         final int I = builder.methodref;
+                         final int C = builder.addClass(withStatDef);
+                         builder.hier.addInherit(C, I);
+                         builder.objectref = C;
+                     },
+                     /* Case 3: Diamond, methodref at top.
+                      *
+                      * I3[](*) = mref
+                      * I1[I3](), I2[I3]()
+                      * C[I1,I2]() = oref
+                      */
+                     (final SelectionResolutionTestCase.Builder builder) -> {
+                         final ClassData.Package pck =
+                             builder.classdata.get(builder.expected).packageId;
+                         final int I3 = builder.methodref;
+                         final int I2 = builder.addInterface(emptyClass(pck));
+                         final int I1 = builder.addInterface(emptyClass(pck));
+                         final int C = builder.addClass(emptyClass(pck));
+                         builder.hier.addInherit(C, I1);
+                         builder.hier.addInherit(C, I2);
+                         builder.hier.addInherit(I1, I3);
+                         builder.hier.addInherit(I2, I3);
+                         builder.objectref = C;
+                     },
+                     /* Case 4: Diamond, methodref at top, skip private def
+                      *
+                      * I3[](*) = mref
+                      * I1[I3](), I2[I3](priv)
+                      * C[I1,I2]() = oref
+                      */
+                     (final SelectionResolutionTestCase.Builder builder) -> {
+                         final ClassData.Package pck =
+                             builder.classdata.get(builder.expected).packageId;
+                         final MethodData meth =
+                             new MethodData(MethodData.Access.PRIVATE,
+                                            MethodData.Context.INSTANCE);
+                         final ClassData withPrivDef =
+                             new ClassData(pck, meth);
+                         final int I3 = builder.methodref;
+                         final int I2 = builder.addInterface(withPrivDef);
+                         final int I1 = builder.addInterface(emptyClass(pck));
+                         final int C = builder.addClass(emptyClass(pck));
+                         builder.hier.addInherit(C, I1);
+                         builder.hier.addInherit(C, I2);
+                         builder.hier.addInherit(I1, I3);
+                         builder.hier.addInherit(I2, I3);
+                         builder.objectref = C;
+                     },
+                     /* Case 5: Diamond, methodref at top, skip static def
+                      *
+                      * I3[](*) = mref
+                      * I1[I3](), I2[I3](stat)
+                      * C[I1,I2]() = oref
+                      */
+                     (final SelectionResolutionTestCase.Builder builder) -> {
+                         final ClassData.Package pck =
+                             builder.classdata.get(builder.expected).packageId;
+                         final MethodData meth =
+                             new MethodData(MethodData.Access.PUBLIC,
+                                            MethodData.Context.STATIC);
+                         final ClassData withStatDef =
+                             new ClassData(pck, meth);
+                         final int I3 = builder.methodref;
+                         final int I2 = builder.addInterface(withStatDef);
+                         final int I1 = builder.addInterface(emptyClass(pck));
+                         final int C = builder.addClass(emptyClass(pck));
+                         builder.hier.addInherit(C, I1);
+                         builder.hier.addInherit(C, I2);
+                         builder.hier.addInherit(I1, I3);
+                         builder.hier.addInherit(I2, I3);
+                         builder.objectref = C;
+                     },
+                     /* Case 6: Diamond, overlap with resolution.
+                      *
+                      * I3[](res) = expected
+                      * I1[I3](), I2[](*) = mref
+                      * C[I1,I2]() = oref
+                      */
+                     (final SelectionResolutionTestCase.Builder builder) -> {
+                         final ClassData.Package pck =
+                             builder.classdata.get(builder.expected).packageId;
+                         final int I3 = builder.expected;
+                         final int I2 = builder.methodref;
+                         final int I1 = builder.addInterface(emptyClass(pck));
+                         final int C = builder.addClass(emptyClass(pck));
+                         builder.hier.addInherit(C, I1);
+                         builder.hier.addInherit(C, I2);
+                         builder.hier.addInherit(I1, I3);
+                         builder.objectref = C;
+                     },
+                     /* Case 7: Diamond, with superclass, expected at top.
+                      *
+                      * I2[](*) = mref
+                      * C2[I2](), I1[I2]()
+                      * C1[I1,C2]() = oref
+                      */
+                     (final SelectionResolutionTestCase.Builder builder) -> {
+                         final ClassData.Package pck =
+                             builder.classdata.get(builder.expected).packageId;
+                         final int I2 = builder.methodref;
+                         final int I1 = builder.addInterface(emptyClass(pck));
+                         final int C2 = builder.addClass(emptyClass(pck));
+                         final int C1 = builder.addClass(emptyClass(pck));
+                         builder.hier.addInherit(C1, I1);
+                         builder.hier.addInherit(C1, C2);
+                         builder.hier.addInherit(I1, I2);
+                         builder.hier.addInherit(C2, I2);
+                         builder.objectref = C1;
+                     },
+                     /* Case 8: Diamond, with superclass, expected at top,
+                      * class has static def.
+                      *
+                      * I2[](*) = mref
+                      * C2[I2](stat), I1[I2]()
+                      * C1[I1,C2]() = oref
+                      */
+                     (final SelectionResolutionTestCase.Builder builder) -> {
+                         final ClassData.Package pck =
+                             builder.classdata.get(builder.expected).packageId;
+                         final MethodData meth =
+                             new MethodData(MethodData.Access.PUBLIC,
+                                            MethodData.Context.STATIC);
+                         final ClassData withStatDef =
+                             new ClassData(pck, meth);
+                         final int I2 = builder.methodref;
+                         final int I1 = builder.addInterface(emptyClass(pck));
+                         final int C2 = builder.addClass(withStatDef);
+                         final int C1 = builder.addClass(emptyClass(pck));
+                         builder.hier.addInherit(C1, I1);
+                         builder.hier.addInherit(C1, C2);
+                         builder.hier.addInherit(I1, I2);
+                         builder.hier.addInherit(C2, I2);
+                         builder.objectref = C1;
+                     },
+                     /* Case 9: Diamond, with superclass, expected at top,
+                      * interface has private def
+                      *
+                      * I2[](*) = mref
+                      * C2[I2](), I1[I2](priv)
+                      * C1[I1,C2]() = oref
+                      */
+                     (final SelectionResolutionTestCase.Builder builder) -> {
+                         final ClassData.Package pck =
+                             builder.classdata.get(builder.expected).packageId;
+                         final MethodData meth =
+                             new MethodData(MethodData.Access.PRIVATE,
+                                            MethodData.Context.INSTANCE);
+                         final ClassData withPrivDef =
+                             new ClassData(pck, meth);
+                         final int I2 = builder.methodref;
+                         final int I1 = builder.addInterface(withPrivDef);
+                         final int C2 = builder.addClass(emptyClass(pck));
+                         final int C1 = builder.addClass(emptyClass(pck));
+                         builder.hier.addInherit(C1, I1);
+                         builder.hier.addInherit(C1, C2);
+                         builder.hier.addInherit(I1, I2);
+                         builder.hier.addInherit(C2, I2);
+                         builder.objectref = C1;
+                     },
+                     /* Case 10: Diamond, with superclass, expected at top,
+                      * interface has static def
+                      *
+                      * I2[](*) = mref
+                      * C2[I2](), I1[I2](stat)
+                      * C1[I1,C2]() = oref
+                      */
+                     (final SelectionResolutionTestCase.Builder builder) -> {
+                         final ClassData.Package pck =
+                             builder.classdata.get(builder.expected).packageId;
+                         final MethodData meth =
+                             new MethodData(MethodData.Access.PUBLIC,
+                                            MethodData.Context.STATIC);
+                         final ClassData withPrivDef =
+                             new ClassData(pck, meth);
+                         final int I2 = builder.methodref;
+                         final int I1 = builder.addInterface(withPrivDef);
+                         final int C2 = builder.addClass(emptyClass(pck));
+                         final int C1 = builder.addClass(emptyClass(pck));
+                         builder.hier.addInherit(C1, I1);
+                         builder.hier.addInherit(C1, C2);
+                         builder.hier.addInherit(I1, I2);
+                         builder.hier.addInherit(C2, I2);
+                         builder.objectref = C1;
+                     },
+                     /* Case 11: Y, with superclass, expected
+                      * at top.
+                      *
+                      * C2[](), I1[](*) = mref
+                      * C1[I1,C2]() = oref
+                      */
+                     (final SelectionResolutionTestCase.Builder builder) -> {
+                         final ClassData.Package pck =
+                             builder.classdata.get(builder.expected).packageId;
+                         final int I1 = builder.methodref;
+                         final int C2 = builder.addClass(emptyClass(pck));
+                         final int C1 = builder.addClass(emptyClass(pck));
+                         builder.hier.addInherit(C1, I1);
+                         builder.hier.addInherit(C1, C2);
+                         builder.objectref = C1;
+                     },
+                     /* Case 12: Y, with superclass, expected
+                      * at top, class has static def
+                      *
+                      * C2[](stat), I1[](*) = mref
+                      * C1[I1,C2]() = oref
+                      */
+                     (final SelectionResolutionTestCase.Builder builder) -> {
+                         final ClassData.Package pck =
+                             builder.classdata.get(builder.expected).packageId;
+                         final MethodData meth =
+                             new MethodData(MethodData.Access.PUBLIC,
+                                            MethodData.Context.STATIC);
+                         final ClassData withStatDef =
+                             new ClassData(pck, meth);
+                         final int I1 = builder.methodref;
+                         final int C2 = builder.addClass(emptyClass(pck));
+                         final int C1 = builder.addClass(emptyClass(pck));
+                         builder.hier.addInherit(C1, I1);
+                         builder.hier.addInherit(C1, C2);
+                         builder.objectref = C1;
+                     },
+                     /* Case 13: Diamond, with superclass, overlapping, expected
+                      * at top.
+                      *
+                      * I2[](res) = expected
+                      * C2[I2](), I1[](*) = mref
+                      * C1[I1,C2]() = oref
+                      */
+                     (final SelectionResolutionTestCase.Builder builder) -> {
+                         final ClassData.Package pck =
+                             builder.classdata.get(builder.expected).packageId;
+                         final int I2 = builder.expected;
+                         final int I1 = builder.methodref;
+                         final int C2 = builder.addClass(emptyClass(pck));
+                         final int C1 = builder.addClass(emptyClass(pck));
+                         builder.hier.addInherit(C1, I1);
+                         builder.hier.addInherit(C1, C2);
+                         builder.hier.addInherit(C2, I2);
+                         builder.objectref = C1;
+                     },
+                     /* Case 14: Diamond, with superclass, overlapping, expected
+                      * at top, class has static def
+                      *
+                      * I2[](def) = expected
+                      * C2[I2](stat), I1[](*) = mref
+                      * C1[I1,C2]() = oref
+                      */
+                     (final SelectionResolutionTestCase.Builder builder) -> {
+                         final ClassData.Package pck =
+                             builder.classdata.get(builder.expected).packageId;
+                         final MethodData meth =
+                             new MethodData(MethodData.Access.PUBLIC,
+                                            MethodData.Context.STATIC);
+                         final ClassData withStatDef =
+                             new ClassData(pck, meth);
+                         final int I2 = builder.expected;
+                         final int I1 = builder.methodref;
+                         final int C2 = builder.addClass(withStatDef);
+                         final int C1 = builder.addClass(emptyClass(pck));
+                         builder.hier.addInherit(C1, I1);
+                         builder.hier.addInherit(C1, C2);
+                         builder.hier.addInherit(C2, I2);
+                         builder.objectref = C1;
+                     },
+                     /* Case 15: Inherit through superclass.
+                      *
+                      * I[](*) = mref
+                      * C2[I]()
+                      * C1[C2]() = oref
+                      */
+                     (final SelectionResolutionTestCase.Builder builder) -> {
+                         final ClassData.Package pck =
+                             builder.classdata.get(builder.expected).packageId;
+                         final int I = builder.methodref;
+                         final int C2 = builder.addClass(emptyClass(pck));
+                         final int C1 = builder.addClass(emptyClass(pck));
+                         builder.hier.addInherit(C1, I);
+                         builder.hier.addInherit(C1, C2);
+                         builder.hier.addInherit(C2, I);
+                         builder.objectref = C1;
+                     },
+                     /* Case 16: Superclass has static def.
+                      *
+                      * I[](*) = mref
+                      * C2[I](stat) = expected
+                      * C1[C2]() = oref
+                      */
+                     (final SelectionResolutionTestCase.Builder builder) -> {
+                         final ClassData.Package pck =
+                             builder.classdata.get(builder.expected).packageId;
+                         final MethodData meth =
+                             new MethodData(MethodData.Access.PUBLIC,
+                                            MethodData.Context.STATIC);
+                         final ClassData withStatDef =
+                             new ClassData(pck, meth);
+                         final int I = builder.methodref;
+                         final int C2 = builder.addClass(withStatDef);
+                         final int C1 = builder.addClass(emptyClass(pck));
+                         builder.hier.addInherit(C1, I);
+                         builder.hier.addInherit(C1, C2);
+                         builder.hier.addInherit(C2, I);
+                         builder.objectref = C1;
+                     },
+                     /* Case 17: Diamond, inherit through superclass,
+                      * methodref at top.
+                      *
+                      * I3[](*) = mref
+                      * I1[I3](), I2[I3]()
+                      * C2[I1,I2]()
+                      * C1[C2]() = oref
+                      */
+                     (final SelectionResolutionTestCase.Builder builder) -> {
+                         final ClassData.Package pck =
+                             builder.classdata.get(builder.expected).packageId;
+                         final int I3 = builder.methodref;
+                         final int I2 = builder.addInterface(emptyClass(pck));
+                         final int I1 = builder.addInterface(emptyClass(pck));
+                         final int C2 = builder.addClass(emptyClass(pck));
+                         final int C1 = builder.addClass(emptyClass(pck));
+                         builder.hier.addInherit(C2, I1);
+                         builder.hier.addInherit(C2, I2);
+                         builder.hier.addInherit(I1, I3);
+                         builder.hier.addInherit(I2, I3);
+                         builder.hier.addInherit(C1, C2);
+                         builder.objectref = C1;
+                     },
+                     /* Case 18: Diamond, with superclass, inherit through
+                      * superclass, methodref at top.
+                      *
+                      * I2[](*) = mref
+                      * C3[I2](), I1[I2]()
+                      * C2[I1,C3]()
+                      * C1[C2]() = oref
+                      */
+                     (final SelectionResolutionTestCase.Builder builder) -> {
+                         final ClassData.Package pck =
+                             builder.classdata.get(builder.expected).packageId;
+                         final int I2 = builder.methodref;
+                         final int I1 = builder.addInterface(emptyClass(pck));
+                         final int C3 = builder.addClass(emptyClass(pck));
+                         final int C2 = builder.addClass(emptyClass(pck));
+                         final int C1 = builder.addClass(emptyClass(pck));
+                         builder.hier.addInherit(C2, I1);
+                         builder.hier.addInherit(C2, C3);
+                         builder.hier.addInherit(I1, I2);
+                         builder.hier.addInherit(C3, I2);
+                         builder.hier.addInherit(C1, C2);
+                         builder.objectref = C1;
+                     },
+                     /* Case 19: Diamond, inherit through superclass,
+                      * expected at top, skip private.
+                      *
+                      * I3[](*) = mref
+                      * I1[I3](), I2[I3](priv)
+                      * C2[I1,I2]()
+                      * C1[C2]() = oref
+                      */
+                     (final SelectionResolutionTestCase.Builder builder) -> {
+                         final ClassData.Package pck =
+                             builder.classdata.get(builder.expected).packageId;
+                         final MethodData meth =
+                             new MethodData(MethodData.Access.PRIVATE,
+                                            MethodData.Context.INSTANCE);
+                         final ClassData withPrivDef =
+                             new ClassData(pck, meth);
+                         final int I3 = builder.methodref;
+                         final int I2 = builder.addInterface(withPrivDef);
+                         final int I1 = builder.addInterface(emptyClass(pck));
+                         final int C2 = builder.addClass(emptyClass(pck));
+                         final int C1 = builder.addClass(emptyClass(pck));
+                         builder.hier.addInherit(C2, I1);
+                         builder.hier.addInherit(C2, I2);
+                         builder.hier.addInherit(I1, I3);
+                         builder.hier.addInherit(I2, I3);
+                         builder.hier.addInherit(C1, C2);
+                         builder.objectref = C1;
+                     },
+                     /* Case 20: Diamond, inherit through superclass,
+                      * expected at top, skip static.
+                      *
+                      * I3[](*) = mref
+                      * I1[I3](), I2[I3](stat)
+                      * C2[I1,I2]()
+                      * C1[C2]() = oref
+                      */
+                     (final SelectionResolutionTestCase.Builder builder) -> {
+                         final ClassData.Package pck =
+                             builder.classdata.get(builder.expected).packageId;
+                         final MethodData meth =
+                             new MethodData(MethodData.Access.PUBLIC,
+                                            MethodData.Context.STATIC);
+                         final ClassData withStatDef =
+                             new ClassData(pck, meth);
+                         final int I3 = builder.methodref;
+                         final int I2 = builder.addInterface(withStatDef);
+                         final int I1 = builder.addInterface(emptyClass(pck));
+                         final int C2 = builder.addClass(emptyClass(pck));
+                         final int C1 = builder.addClass(emptyClass(pck));
+                         builder.hier.addInherit(C2, I1);
+                         builder.hier.addInherit(C2, I2);
+                         builder.hier.addInherit(I1, I3);
+                         builder.hier.addInherit(I2, I3);
+                         builder.hier.addInherit(C1, C2);
+                         builder.objectref = C1;
+                     },
+                     /* Case 21: Diamond, inherit through superclass,
+                      * overlapping, expected at top.
+                      *
+                      * I3[](res) = expected
+                      * I1[I3](), I2[*](*) = mref
+                      * C2[I1,I2]()
+                      * C1[C2]() = oref
+                      */
+                     (final SelectionResolutionTestCase.Builder builder) -> {
+                         final ClassData.Package pck =
+                             builder.classdata.get(builder.expected).packageId;
+                         final int I3 = builder.expected;
+                         final int I2 = builder.methodref;
+                         final int I1 = builder.addInterface(emptyClass(pck));
+                         final int C2 = builder.addClass(emptyClass(pck));
+                         final int C1 = builder.addClass(emptyClass(pck));
+                         builder.hier.addInherit(C2, I1);
+                         builder.hier.addInherit(C2, I2);
+                         builder.hier.addInherit(I1, I3);
+                         builder.hier.addInherit(C1, C2);
+                         builder.objectref = C1;
+                     },
+                     /* Case 22: Y, with superclass, inherit through
+                      * superclass, expected at top.
+                      *
+                      * C3[](), I1[*](*) = mref
+                      * C2[I1,C3]()
+                      * C1[C2]() = oref
+                      */
+                     (final SelectionResolutionTestCase.Builder builder) -> {
+                         final ClassData.Package pck =
+                             builder.classdata.get(builder.expected).packageId;
+                         final int I1 = builder.methodref;
+                         final int C3 = builder.addClass(emptyClass(pck));
+                         final int C2 = builder.addClass(emptyClass(pck));
+                         final int C1 = builder.addClass(emptyClass(pck));
+                         builder.hier.addInherit(C2, I1);
+                         builder.hier.addInherit(C2, C3);
+                         builder.hier.addInherit(C1, C2);
+                         builder.objectref = C1;
+                     },
+                     /* Case 23: Diamond, with superclass, inherit through
+                      * superclass, overlapping, expected at top.
+                      *
+                      * I2[](res) = expected
+                      * C3[I2](), I1[*](*) = mref
+                      * C2[I1,C3]()
+                      * C1[C2]() = oref
+                      */
+                     (final SelectionResolutionTestCase.Builder builder) -> {
+                         final ClassData.Package pck =
+                             builder.classdata.get(builder.expected).packageId;
+                         final int I2 = builder.expected;
+                         final int I1 = builder.methodref;
+                         final int C3 = builder.addClass(emptyClass(pck));
+                         final int C2 = builder.addClass(emptyClass(pck));
+                         final int C1 = builder.addClass(emptyClass(pck));
+                         builder.hier.addInherit(C2, I1);
+                         builder.hier.addInherit(C2, C3);
+                         builder.hier.addInherit(C3, I2);
+                         builder.hier.addInherit(C1, C2);
+                         builder.objectref = C1;
+                     },
+                     /* Case 24: Double diamond, with superclass, inherit through
+                      * superclass, overlapping expected at top.
+                      *
+                      * I3[](res) = expected
+                      * C3[I3](), I2[*](*) = mref
+                      * C2[I2,C3](), I1[I2]()
+                      * C1[C2,I1]() = oref
+                      */
+                     (final SelectionResolutionTestCase.Builder builder) -> {
+                         final ClassData.Package pck =
+                             builder.classdata.get(builder.expected).packageId;
+                         final int I3 = builder.expected;
+                         final int I2 = builder.methodref;
+                         final int I1 = builder.addInterface(emptyClass(pck));
+                         final int C3 = builder.addClass(emptyClass(pck));
+                         final int C2 = builder.addClass(emptyClass(pck));
+                         final int C1 = builder.addClass(emptyClass(pck));
+                         builder.hier.addInherit(C2, I2);
+                         builder.hier.addInherit(C2, C3);
+                         builder.hier.addInherit(C3, I3);
+                         builder.hier.addInherit(C1, C2);
+                         builder.hier.addInherit(I1, I2);
+                         builder.hier.addInherit(C1, I1);
+                         builder.objectref = C1;
+                     },
+                     /* Case 25: Double diamond, with superclass, inherit through
+                      * superclass, skip private.
+                      *
+                      * I3[](def) = old expected
+                      * C3[I3](), I2[*](*) = mref
+                      * C2[I2,C3](), I1[I2](priv)
+                      * C1[C2,I1]() = oref
+                      */
+                     (final SelectionResolutionTestCase.Builder builder) -> {
+                         final ClassData.Package pck =
+                             builder.classdata.get(builder.expected).packageId;
+                         final MethodData meth =
+                             new MethodData(MethodData.Access.PRIVATE,
+                                            MethodData.Context.INSTANCE);
+                         final ClassData withPrivDef =
+                             new ClassData(pck, meth);
+                         final int I3 = builder.expected;
+                         final int I2 = builder.methodref;
+                         final int I1 = builder.addInterface(withPrivDef);
+                         final int C3 = builder.addClass(emptyClass(pck));
+                         final int C2 = builder.addClass(emptyClass(pck));
+                         final int C1 = builder.addClass(emptyClass(pck));
+                         builder.hier.addInherit(C2, I2);
+                         builder.hier.addInherit(C2, C3);
+                         builder.hier.addInherit(C3, I3);
+                         builder.hier.addInherit(C1, C2);
+                         builder.hier.addInherit(I1, I2);
+                         builder.hier.addInherit(C1, I1);
+                         builder.objectref = C1;
+                     },
+                     /* Case 26: Double diamond, with superclass, inherit through
+                      * superclass, skip static.
+                      *
+                      * I3[](def) = old expected
+                      * C3[I3](), I2[*](*) = mref
+                      * C2[I2,C3](), I1[I2](stat)
+                      * C1[C2,I1]() = oref
+                      */
+                     (final SelectionResolutionTestCase.Builder builder) -> {
+                         final ClassData.Package pck =
+                             builder.classdata.get(builder.expected).packageId;
+                         final MethodData meth =
+                             new MethodData(MethodData.Access.PUBLIC,
+                                            MethodData.Context.STATIC);
+                         final ClassData withStatDef =
+                             new ClassData(pck, meth);
+                         final int I3 = builder.expected;
+                         final int I2 = builder.methodref;
+                         final int I1 = builder.addInterface(withStatDef);
+                         final int C3 = builder.addClass(emptyClass(pck));
+                         final int C2 = builder.addClass(emptyClass(pck));
+                         final int C1 = builder.addClass(emptyClass(pck));
+                         builder.hier.addInherit(C2, I2);
+                         builder.hier.addInherit(C2, C3);
+                         builder.hier.addInherit(C3, I3);
+                         builder.hier.addInherit(C1, C2);
+                         builder.hier.addInherit(I1, I2);
+                         builder.hier.addInherit(C1, I1);
+                         builder.objectref = C1;
+                     });
+
+    public static final Template IfaceMethodrefSelection =
+        new Template("IfaceMethodrefSelection",
+                     IfaceMethodrefSelectionNoOverride,
+                     /* Case 27: Objectref overrides.
+                      *
+                      * I[](*) = mref
+                      * C[I](res) = oref = expected
+                      */
+                     (final SelectionResolutionTestCase.Builder builder) -> {
+                         final ClassData.Package pck =
+                             builder.classdata.get(builder.methodref).packageId;
+                        final ClassData oldexpected =
+                            builder.classdata.get(builder.expected);
+                        final ClassData withDef =
+                            new ClassData(pck, oldexpected.methoddata);
+                         final int I = builder.methodref;
+                         final int C = builder.addClass(withDef);
+                         builder.hier.addInherit(C, I);
+                         builder.objectref = C;
+                         builder.expected = C;
+                     },
+                     /* Case 28: Diamond, methodref at top, overriding.
+                      *
+                      * I3[](*) = mref
+                      * I1[I3](), I2[I3](res) = expected
+                      * C[I1,I2]() = oref
+                      */
+                     (final SelectionResolutionTestCase.Builder builder) -> {
+                         final ClassData.Package pck =
+                             builder.classdata.get(builder.expected).packageId;
+                        final ClassData oldexpected =
+                            builder.classdata.get(builder.expected);
+                        final ClassData withDef =
+                            new ClassData(pck, oldexpected.methoddata);
+                         final int I3 = builder.methodref;
+                         final int I2 = builder.addInterface(withDef);
+                         final int I1 = builder.addInterface(emptyClass(pck));
+                         final int C = builder.addClass(emptyClass(pck));
+                         builder.hier.addInherit(C, I1);
+                         builder.hier.addInherit(C, I2);
+                         builder.hier.addInherit(I1, I3);
+                         builder.hier.addInherit(I2, I3);
+                         builder.objectref = C;
+                         builder.expected = I2;
+                     },
+                     /* Case 29: Diamond, with superclass, expected at top,
+                      * class overriding.
+                      *
+                      * I2[](*) = mref
+                      * C2[I2](res) = expected, I1[I2]()
+                      * C1[I1,C2]() = oref
+                      */
+                     (final SelectionResolutionTestCase.Builder builder) -> {
+                         final ClassData.Package pck =
+                             builder.classdata.get(builder.expected).packageId;
+                        final ClassData oldexpected =
+                            builder.classdata.get(builder.expected);
+                        final ClassData withDef =
+                            new ClassData(pck, oldexpected.methoddata);
+                         final int I2 = builder.methodref;
+                         final int I1 = builder.addInterface(emptyClass(pck));
+                         final int C2 = builder.addClass(withDef);
+                         final int C1 = builder.addClass(emptyClass(pck));
+                         builder.hier.addInherit(C1, I1);
+                         builder.hier.addInherit(C1, C2);
+                         builder.hier.addInherit(I1, I2);
+                         builder.hier.addInherit(C2, I2);
+                         builder.objectref = C1;
+                         builder.expected = C2;
+                     },
+                     /* Case 30: Diamond, with superclass, expected at top,
+                      * interface overriding
+                      *
+                      * I2[](*) = mref
+                      * C2[I2](), I1[I2](res) = expected
+                      * C1[I1,C2]() = oref
+                      */
+                     (final SelectionResolutionTestCase.Builder builder) -> {
+                         final ClassData.Package pck =
+                             builder.classdata.get(builder.expected).packageId;
+                        final ClassData oldexpected =
+                            builder.classdata.get(builder.expected);
+                        final ClassData withDef =
+                            new ClassData(pck, oldexpected.methoddata);
+                         final int I2 = builder.methodref;
+                         final int I1 = builder.addInterface(withDef);
+                         final int C2 = builder.addClass(emptyClass(pck));
+                         final int C1 = builder.addClass(emptyClass(pck));
+                         builder.hier.addInherit(C1, I1);
+                         builder.hier.addInherit(C1, C2);
+                         builder.hier.addInherit(I1, I2);
+                         builder.hier.addInherit(C2, I2);
+                         builder.objectref = C1;
+                         builder.expected = I1;
+                     },
+                     /* Case 31: Y, with superclass, overlaping, expected
+                      * at top, class overrides
+                      *
+                      * C2[](res) = expected, I1[](*) = mref
+                      * C1[I1,C2]() = oref
+                      */
+                     (final SelectionResolutionTestCase.Builder builder) -> {
+                         final ClassData.Package pck =
+                             builder.classdata.get(builder.expected).packageId;
+                        final ClassData oldexpected =
+                            builder.classdata.get(builder.expected);
+                        final ClassData withDef =
+                            new ClassData(pck, oldexpected.methoddata);
+                         final int I1 = builder.methodref;
+                         final int C2 = builder.addClass(withDef);
+                         final int C1 = builder.addClass(emptyClass(pck));
+                         builder.hier.addInherit(C1, I1);
+                         builder.hier.addInherit(C1, C2);
+                         builder.objectref = C1;
+                         builder.expected = C2;
+                     },
+                     /* Case 32: Diamond, with superclass, overlaping, expected
+                      * at top, class overrides
+                      *
+                      * I2[](def) = old expected
+                      * C2[I2](res) = expected, I1[](*) = mref
+                      * C1[I1,C2]() = oref
+                      */
+                     (final SelectionResolutionTestCase.Builder builder) -> {
+                         final ClassData.Package pck =
+                             builder.classdata.get(builder.expected).packageId;
+                        final ClassData oldexpected =
+                            builder.classdata.get(builder.expected);
+                        final ClassData withDef =
+                            new ClassData(pck, oldexpected.methoddata);
+                         final int I2 = builder.expected;
+                         final int I1 = builder.methodref;
+                         final int C2 = builder.addClass(withDef);
+                         final int C1 = builder.addClass(emptyClass(pck));
+                         builder.hier.addInherit(C1, I1);
+                         builder.hier.addInherit(C1, C2);
+                         builder.hier.addInherit(C2, I2);
+                         builder.objectref = C1;
+                         builder.expected = C2;
+                     },
+                     /* Case 33: Superclass overrides.
+                      *
+                      * I[](*) = mref
+                      * C2[I](res) = expected
+                      * C1[C2]() = oref
+                      */
+                     (final SelectionResolutionTestCase.Builder builder) -> {
+                         final ClassData.Package pck =
+                             builder.classdata.get(builder.expected).packageId;
+                        final ClassData oldexpected =
+                            builder.classdata.get(builder.expected);
+                        final ClassData withDef =
+                            new ClassData(pck, oldexpected.methoddata);
+                         final int I = builder.methodref;
+                         final int C2 = builder.addClass(withDef);
+                         final int C1 = builder.addClass(emptyClass(pck));
+                         builder.hier.addInherit(C1, I);
+                         builder.hier.addInherit(C1, C2);
+                         builder.hier.addInherit(C2, I);
+                         builder.expected = C2;
+                         builder.objectref = C1;
+                     },
+                     /* Case 34: Diamond, inherit through superclass,
+                      * expected at top, override.
+                      *
+                      * I3[](*) = mref
+                      * I1[I3](), I2[I3](res) = expected
+                      * C2[I1,I2]()
+                      * C1[C2]() = oref
+                      */
+                     (final SelectionResolutionTestCase.Builder builder) -> {
+                         final ClassData.Package pck =
+                             builder.classdata.get(builder.expected).packageId;
+                         final ClassData oldexpected =
+                             builder.classdata.get(builder.expected);
+                         final ClassData withDef =
+                             new ClassData(pck, oldexpected.methoddata);
+                         final int I3 = builder.methodref;
+                         final int I2 = builder.addInterface(withDef);
+                         final int I1 = builder.addInterface(emptyClass(pck));
+                         final int C2 = builder.addClass(emptyClass(pck));
+                         final int C1 = builder.addClass(emptyClass(pck));
+                         builder.hier.addInherit(C2, I1);
+                         builder.hier.addInherit(C2, I2);
+                         builder.hier.addInherit(I1, I3);
+                         builder.hier.addInherit(I2, I3);
+                         builder.hier.addInherit(C1, C2);
+                         builder.objectref = C1;
+                         builder.expected = I2;
+                     },
+                     /* Case 35: Y, with superclass, inherit through
+                      * superclass, overlapping, expected at top.
+                      *
+                      * C3[](res) = expected, I1[*](*) = mref
+                      * C2[I1,C3]()
+                      * C1[C2]() = oref
+                      */
+                     (final SelectionResolutionTestCase.Builder builder) -> {
+                         final ClassData.Package pck =
+                             builder.classdata.get(builder.expected).packageId;
+                         final ClassData oldexpected =
+                             builder.classdata.get(builder.expected);
+                         final ClassData withDef =
+                             new ClassData(pck, oldexpected.methoddata);
+                         final int I1 = builder.methodref;
+                         final int C3 = builder.addClass(withDef);
+                         final int C2 = builder.addClass(emptyClass(pck));
+                         final int C1 = builder.addClass(emptyClass(pck));
+                         builder.hier.addInherit(C2, I1);
+                         builder.hier.addInherit(C2, C3);
+                         builder.hier.addInherit(C1, C2);
+                         builder.objectref = C1;
+                         builder.expected = C3;
+                     },
+                     /* Case 36: Diamond, with superclass, inherit through
+                      * superclass, overlapping, expected at top.
+                      *
+                      * I2[](*) = oldexpected
+                      * C3[I2](res) = expected, I1[*](*) = mref
+                      * C2[I1,C3]()
+                      * C1[C2]() = oref
+                      */
+                     (final SelectionResolutionTestCase.Builder builder) -> {
+                         final ClassData.Package pck =
+                             builder.classdata.get(builder.expected).packageId;
+                         final ClassData oldexpected =
+                             builder.classdata.get(builder.expected);
+                         final ClassData withDef =
+                             new ClassData(pck, oldexpected.methoddata);
+                         final int I2 = builder.expected;
+                         final int I1 = builder.methodref;
+                         final int C3 = builder.addClass(withDef);
+                         final int C2 = builder.addClass(emptyClass(pck));
+                         final int C1 = builder.addClass(emptyClass(pck));
+                         builder.hier.addInherit(C2, I1);
+                         builder.hier.addInherit(C2, C3);
+                         builder.hier.addInherit(C3, I2);
+                         builder.hier.addInherit(C1, C2);
+                         builder.objectref = C1;
+                         builder.expected = C3;
+                     },
+                     /* Case 37: Double diamond, with superclass, inherit through
+                      * superclass, overriding.
+                      *
+                      * I3[](def) = old expected
+                      * C3[I3](), I2[*](*) = mref
+                      * C2[I2,C3](), I1[I2](res) = expected
+                      * C1[C2,I1]() = oref
+                      */
+                     (final SelectionResolutionTestCase.Builder builder) -> {
+                         final ClassData.Package pck =
+                             builder.classdata.get(builder.expected).packageId;
+                         final ClassData oldexpected =
+                             builder.classdata.get(builder.expected);
+                         final ClassData withDef =
+                             new ClassData(pck, oldexpected.methoddata);
+                         final int I3 = builder.expected;
+                         final int I2 = builder.methodref;
+                         final int I1 = builder.addInterface(withDef);
+                         final int C3 = builder.addClass(emptyClass(pck));
+                         final int C2 = builder.addClass(emptyClass(pck));
+                         final int C1 = builder.addClass(emptyClass(pck));
+                         builder.hier.addInherit(C2, I2);
+                         builder.hier.addInherit(C2, C3);
+                         builder.hier.addInherit(C3, I3);
+                         builder.hier.addInherit(C1, C2);
+                         builder.hier.addInherit(I1, I2);
+                         builder.hier.addInherit(C1, I1);
+                         builder.objectref = C1;
+                         builder.expected = I1;
+                     },
+                     /* Case 38: Double diamond, with superclass, inherit through
+                      * superclass, skip private.
+                      *
+                      * I3[](def) = old expected
+                      * C3[I3](), I2[*](*) = mref
+                      * C2[I2,C3](), I1[I2](priv)
+                      * C1[C2,I1]() = oref
+                      */
+                     (final SelectionResolutionTestCase.Builder builder) -> {
+                         final ClassData.Package pck =
+                             builder.classdata.get(builder.expected).packageId;
+                         final ClassData oldexpected =
+                             builder.classdata.get(builder.expected);
+                         final ClassData withDef =
+                             new ClassData(pck, oldexpected.methoddata);
+                         final MethodData meth =
+                             new MethodData(MethodData.Access.PRIVATE,
+                                            MethodData.Context.INSTANCE);
+                         final ClassData withPrivDef =
+                             new ClassData(pck, meth);
+                         final int I3 = builder.expected;
+                         final int I2 = builder.methodref;
+                         final int I1 = builder.addInterface(withPrivDef);
+                         final int C3 = builder.addClass(emptyClass(pck));
+                         final int C2 = builder.addClass(emptyClass(pck));
+                         final int C1 = builder.addClass(emptyClass(pck));
+                         builder.hier.addInherit(C2, I2);
+                         builder.hier.addInherit(C2, C3);
+                         builder.hier.addInherit(C3, I3);
+                         builder.hier.addInherit(C1, C2);
+                         builder.hier.addInherit(I1, I2);
+                         builder.hier.addInherit(C1, I1);
+                         builder.objectref = C1;
+                     },
+                     /* Case 39: Double diamond, with superclass, inherit through
+                      * superclass, skip static.
+                      *
+                      * I3[](def) = old expected
+                      * C3[I3](), I2[*](*) = mref
+                      * C2[I2,C3](), I1[I2](stat)
+                      * C1[C2,I1]() = oref
+                      */
+                     (final SelectionResolutionTestCase.Builder builder) -> {
+                         final ClassData.Package pck =
+                             builder.classdata.get(builder.expected).packageId;
+                         final ClassData oldexpected =
+                             builder.classdata.get(builder.expected);
+                         final ClassData withDef =
+                             new ClassData(pck, oldexpected.methoddata);
+                         final MethodData meth =
+                             new MethodData(MethodData.Access.PUBLIC,
+                                            MethodData.Context.STATIC);
+                         final ClassData withStatDef =
+                             new ClassData(pck, meth);
+                         final int I3 = builder.expected;
+                         final int I2 = builder.methodref;
+                         final int I1 = builder.addInterface(withStatDef);
+                         final int C3 = builder.addClass(emptyClass(pck));
+                         final int C2 = builder.addClass(emptyClass(pck));
+                         final int C1 = builder.addClass(emptyClass(pck));
+                         builder.hier.addInherit(C2, I2);
+                         builder.hier.addInherit(C2, C3);
+                         builder.hier.addInherit(C3, I3);
+                         builder.hier.addInherit(C1, C2);
+                         builder.hier.addInherit(I1, I2);
+                         builder.hier.addInherit(C1, I1);
+                         builder.objectref = C1;
+                     },
+                     /* Case 40: Superclass overrides.
+                      *
+                      * I[](*) = mref
+                      * C3[I](res) = expected
+                      * C2[C3](stat) = expected
+                      * C1[C2]() = oref
+                      */
+                     (final SelectionResolutionTestCase.Builder builder) -> {
+                         final ClassData.Package pck =
+                             builder.classdata.get(builder.expected).packageId;
+                        final ClassData oldexpected =
+                            builder.classdata.get(builder.expected);
+                         final ClassData withDef =
+                             new ClassData(pck, oldexpected.methoddata);
+                         final MethodData meth =
+                             new MethodData(MethodData.Access.PUBLIC,
+                                            MethodData.Context.STATIC);
+                         final ClassData withStatDef =
+                             new ClassData(pck, meth);
+                         final int I = builder.methodref;
+                         final int C3 = builder.addClass(withDef);
+                         final int C2 = builder.addClass(withStatDef);
+                         final int C1 = builder.addClass(emptyClass(pck));
+                         builder.hier.addInherit(C1, I);
+                         builder.hier.addInherit(C1, C2);
+                         builder.hier.addInherit(C2, C3);
+                         builder.hier.addInherit(C2, I);
+                         builder.expected = C3;
+                         builder.objectref = C1;
+                     });
+
+    public static final Template IfaceMethodrefSelectionOverrideNonPublic =
+        new Template("IfaceMethodrefSelection",
+                     /* Case 1: Objectref overrides.
+                      *
+                      * I[](*) = mref
+                      * C[I](priv) = oref = expected
+                      */
+                     (final SelectionResolutionTestCase.Builder builder) -> {
+                         final ClassData.Package pck =
+                             builder.classdata.get(builder.methodref).packageId;
+                         final ClassData oldexpected =
+                             builder.classdata.get(builder.expected);
+                         final MethodData meth =
+                             new MethodData(MethodData.Access.PRIVATE,
+                                            MethodData.Context.INSTANCE);
+                         final ClassData withDef =
+                             new ClassData(pck, meth);
+                         final int I = builder.methodref;
+                         final int C = builder.addClass(withDef);
+                         builder.hier.addInherit(C, I);
+                         builder.objectref = C;
+                         builder.expected = C;
+                     },
+                     /* Case 2: Objectref overrides.
+                      *
+                      * I[](*) = mref
+                      * C[I](prot) = oref = expected
+                      */
+                     (final SelectionResolutionTestCase.Builder builder) -> {
+                         final ClassData.Package pck =
+                             builder.classdata.get(builder.methodref).packageId;
+                         final ClassData oldexpected =
+                             builder.classdata.get(builder.expected);
+                         final MethodData meth =
+                             new MethodData(MethodData.Access.PROTECTED,
+                                            MethodData.Context.INSTANCE);
+                         final ClassData withDef =
+                             new ClassData(pck, meth);
+                         final int I = builder.methodref;
+                         final int C = builder.addClass(withDef);
+                         builder.hier.addInherit(C, I);
+                         builder.objectref = C;
+                         builder.expected = C;
+                     },
+                     /* Case 3: Objectref overrides package private.
+                      *
+                      * I[](*) = mref
+                      * C[I](pack) = oref = expected
+                      */
+                     (final SelectionResolutionTestCase.Builder builder) -> {
+                         final ClassData.Package pck =
+                             builder.classdata.get(builder.methodref).packageId;
+                         final ClassData oldexpected =
+                             builder.classdata.get(builder.expected);
+                         final MethodData meth =
+                             new MethodData(MethodData.Access.PACKAGE,
+                                            MethodData.Context.INSTANCE);
+                         final ClassData withDef =
+                             new ClassData(pck, meth);
+                         final int I = builder.methodref;
+                         final int C = builder.addClass(withDef);
+                         builder.hier.addInherit(C, I);
+                         builder.objectref = C;
+                         builder.expected = C;
+                     },
+                     /* Case 4: Diamond, with superclass, expected at top,
+                      * class overriding with private.
+                      *
+                      * I2[](*) = mref
+                      * C2[I2](priv) = expected, I1[I2]()
+                      * C1[I1,C2]() = oref
+                      */
+                     (final SelectionResolutionTestCase.Builder builder) -> {
+                         final ClassData.Package pck =
+                             builder.classdata.get(builder.expected).packageId;
+                         final ClassData oldexpected =
+                             builder.classdata.get(builder.expected);
+                         final MethodData meth =
+                             new MethodData(MethodData.Access.PRIVATE,
+                                            MethodData.Context.INSTANCE);
+                         final ClassData withDef =
+                             new ClassData(pck, meth);
+                         final int I2 = builder.methodref;
+                         final int I1 = builder.addInterface(emptyClass(pck));
+                         final int C2 = builder.addClass(withDef);
+                         final int C1 = builder.addClass(emptyClass(pck));
+                         builder.hier.addInherit(C1, I1);
+                         builder.hier.addInherit(C1, C2);
+                         builder.hier.addInherit(I1, I2);
+                         builder.hier.addInherit(C2, I2);
+                         builder.objectref = C1;
+                         builder.expected = C2;
+                     },
+                     /* Case 5: Diamond, with superclass, expected at top,
+                      * class overriding with package private.
+                      *
+                      * I2[](*) = mref
+                      * C2[I2](pack) = expected, I1[I2]()
+                      * C1[I1,C2]() = oref
+                      */
+                     (final SelectionResolutionTestCase.Builder builder) -> {
+                         final ClassData.Package pck =
+                             builder.classdata.get(builder.expected).packageId;
+                         final ClassData oldexpected =
+                             builder.classdata.get(builder.expected);
+                         final MethodData meth =
+                             new MethodData(MethodData.Access.PACKAGE,
+                                            MethodData.Context.INSTANCE);
+                         final ClassData withDef =
+                             new ClassData(pck, meth);
+                         final int I2 = builder.methodref;
+                         final int I1 = builder.addInterface(emptyClass(pck));
+                         final int C2 = builder.addClass(withDef);
+                         final int C1 = builder.addClass(emptyClass(pck));
+                         builder.hier.addInherit(C1, I1);
+                         builder.hier.addInherit(C1, C2);
+                         builder.hier.addInherit(I1, I2);
+                         builder.hier.addInherit(C2, I2);
+                         builder.objectref = C1;
+                         builder.expected = C2;
+                     },
+                     /* Case 6: Diamond, with superclass, expected at top,
+                      * class overriding with protected.
+                      *
+                      * I2[](*) = mref
+                      * C2[I2](prot) = expected, I1[I2]()
+                      * C1[I1,C2]() = oref
+                      */
+                     (final SelectionResolutionTestCase.Builder builder) -> {
+                         final ClassData.Package pck =
+                             builder.classdata.get(builder.expected).packageId;
+                         final ClassData oldexpected =
+                             builder.classdata.get(builder.expected);
+                         final MethodData meth =
+                             new MethodData(MethodData.Access.PROTECTED,
+                                            MethodData.Context.INSTANCE);
+                         final ClassData withDef =
+                             new ClassData(pck, meth);
+                         final int I2 = builder.methodref;
+                         final int I1 = builder.addInterface(emptyClass(pck));
+                         final int C2 = builder.addClass(withDef);
+                         final int C1 = builder.addClass(emptyClass(pck));
+                         builder.hier.addInherit(C1, I1);
+                         builder.hier.addInherit(C1, C2);
+                         builder.hier.addInherit(I1, I2);
+                         builder.hier.addInherit(C2, I2);
+                         builder.objectref = C1;
+                         builder.expected = C2;
+                     },
+                     /* Case 7: Y, with superclass, overlaping, expected
+                      * at top, class overrides
+                      *
+                      * C2[](priv) = expected, I1[](*) = mref
+                      * C1[I1,C2]() = oref
+                      */
+                     (final SelectionResolutionTestCase.Builder builder) -> {
+                         final ClassData.Package pck =
+                             builder.classdata.get(builder.expected).packageId;
+                        final ClassData oldexpected =
+                            builder.classdata.get(builder.expected);
+                         final MethodData meth =
+                             new MethodData(MethodData.Access.PRIVATE,
+                                            MethodData.Context.INSTANCE);
+                        final ClassData withDef =
+                            new ClassData(pck, meth);
+                         final int I1 = builder.methodref;
+                         final int C2 = builder.addClass(withDef);
+                         final int C1 = builder.addClass(emptyClass(pck));
+                         builder.hier.addInherit(C1, I1);
+                         builder.hier.addInherit(C1, C2);
+                         builder.objectref = C1;
+                         builder.expected = C2;
+                     },
+                     /* Case 8: Y, with superclass, overlaping, expected
+                      * at top, class overrides
+                      *
+                      * C2[](prot) = expected, I1[](*) = mref
+                      * C1[I1,C2]() = oref
+                      */
+                     (final SelectionResolutionTestCase.Builder builder) -> {
+                         final ClassData.Package pck =
+                             builder.classdata.get(builder.expected).packageId;
+                        final ClassData oldexpected =
+                            builder.classdata.get(builder.expected);
+                         final MethodData meth =
+                             new MethodData(MethodData.Access.PROTECTED,
+                                            MethodData.Context.INSTANCE);
+                        final ClassData withDef =
+                            new ClassData(pck, meth);
+                         final int I1 = builder.methodref;
+                         final int C2 = builder.addClass(withDef);
+                         final int C1 = builder.addClass(emptyClass(pck));
+                         builder.hier.addInherit(C1, I1);
+                         builder.hier.addInherit(C1, C2);
+                         builder.objectref = C1;
+                         builder.expected = C2;
+                     },
+                     /* Case 9: Y, with superclass, overlaping, expected
+                      * at top, class overrides
+                      *
+                      * C2[](pack) = expected, I1[](*) = mref
+                      * C1[I1,C2]() = oref
+                      */
+                     (final SelectionResolutionTestCase.Builder builder) -> {
+                         final ClassData.Package pck =
+                             builder.classdata.get(builder.expected).packageId;
+                         final ClassData oldexpected =
+                             builder.classdata.get(builder.expected);
+                         final MethodData meth =
+                             new MethodData(MethodData.Access.PACKAGE,
+                                            MethodData.Context.INSTANCE);
+                         final ClassData withDef =
+                             new ClassData(pck, meth);
+                         final int I1 = builder.methodref;
+                         final int C2 = builder.addClass(withDef);
+                         final int C1 = builder.addClass(emptyClass(pck));
+                         builder.hier.addInherit(C1, I1);
+                         builder.hier.addInherit(C1, C2);
+                         builder.objectref = C1;
+                         builder.expected = C2;
+                     },
+                     /* Case 10: Diamond, with superclass, overlaping, expected
+                      * at top, class overrides
+                      *
+                      * I2[](def) = old expected
+                      * C2[I2](priv) = expected, I1[](*) = mref
+                      * C1[I1,C2]() = oref
+                      */
+                     (final SelectionResolutionTestCase.Builder builder) -> {
+                         final ClassData.Package pck =
+                             builder.classdata.get(builder.expected).packageId;
+                         final ClassData oldexpected =
+                             builder.classdata.get(builder.expected);
+                         final MethodData meth =
+                             new MethodData(MethodData.Access.PRIVATE,
+                                            MethodData.Context.INSTANCE);
+                         final ClassData withDef =
+                             new ClassData(pck, meth);
+                         final int I2 = builder.expected;
+                         final int I1 = builder.methodref;
+                         final int C2 = builder.addClass(withDef);
+                         final int C1 = builder.addClass(emptyClass(pck));
+                         builder.hier.addInherit(C1, I1);
+                         builder.hier.addInherit(C1, C2);
+                         builder.hier.addInherit(C2, I2);
+                         builder.objectref = C1;
+                         builder.expected = C2;
+                     },
+                     /* Case 11: Diamond, with superclass, overlaping, expected
+                      * at top, class overrides
+                      *
+                      * I2[](def) = old expected
+                      * C2[I2](pack) = expected, I1[](*) = mref
+                      * C1[I1,C2]() = oref
+                      */
+                     (final SelectionResolutionTestCase.Builder builder) -> {
+                         final ClassData.Package pck =
+                             builder.classdata.get(builder.expected).packageId;
+                         final ClassData oldexpected =
+                             builder.classdata.get(builder.expected);
+                         final MethodData meth =
+                             new MethodData(MethodData.Access.PACKAGE,
+                                            MethodData.Context.INSTANCE);
+                         final ClassData withDef =
+                             new ClassData(pck, meth);
+                         final int I2 = builder.expected;
+                         final int I1 = builder.methodref;
+                         final int C2 = builder.addClass(withDef);
+                         final int C1 = builder.addClass(emptyClass(pck));
+                         builder.hier.addInherit(C1, I1);
+                         builder.hier.addInherit(C1, C2);
+                         builder.hier.addInherit(C2, I2);
+                         builder.objectref = C1;
+                         builder.expected = C2;
+                     },
+                     /* Case 12: Diamond, with superclass, overlaping, expected
+                      * at top, class overrides
+                      *
+                      * I2[](def) = old expected
+                      * C2[I2](prot) = expected, I1[](*) = mref
+                      * C1[I1,C2]() = oref
+                      */
+                     (final SelectionResolutionTestCase.Builder builder) -> {
+                         final ClassData.Package pck =
+                             builder.classdata.get(builder.expected).packageId;
+                         final ClassData oldexpected =
+                             builder.classdata.get(builder.expected);
+                         final MethodData meth =
+                             new MethodData(MethodData.Access.PROTECTED,
+                                            MethodData.Context.INSTANCE);
+                         final ClassData withDef =
+                             new ClassData(pck, meth);
+                         final int I2 = builder.expected;
+                         final int I1 = builder.methodref;
+                         final int C2 = builder.addClass(withDef);
+                         final int C1 = builder.addClass(emptyClass(pck));
+                         builder.hier.addInherit(C1, I1);
+                         builder.hier.addInherit(C1, C2);
+                         builder.hier.addInherit(C2, I2);
+                         builder.objectref = C1;
+                         builder.expected = C2;
+                     },
+                     /* Case 13: Superclass overrides.
+                      *
+                      * I[](*) = mref
+                      * C2[I](priv) = expected
+                      * C1[C2]() = oref
+                      */
+                     (final SelectionResolutionTestCase.Builder builder) -> {
+                         final ClassData.Package pck =
+                             builder.classdata.get(builder.expected).packageId;
+                         final ClassData oldexpected =
+                             builder.classdata.get(builder.expected);
+                         final MethodData meth =
+                             new MethodData(MethodData.Access.PRIVATE,
+                                            MethodData.Context.INSTANCE);
+                         final ClassData withDef =
+                             new ClassData(pck, meth);
+                         final int I = builder.methodref;
+                         final int C2 = builder.addClass(withDef);
+                         final int C1 = builder.addClass(emptyClass(pck));
+                         builder.hier.addInherit(C1, I);
+                         builder.hier.addInherit(C1, C2);
+                         builder.hier.addInherit(C2, I);
+                         builder.expected = C2;
+                         builder.objectref = C1;
+                     },
+                     /* Case 14: Superclass overrides.
+                      *
+                      * I[](*) = mref
+                      * C2[I](prot) = expected
+                      * C1[C2]() = oref
+                      */
+                     (final SelectionResolutionTestCase.Builder builder) -> {
+                         final ClassData.Package pck =
+                             builder.classdata.get(builder.expected).packageId;
+                         final ClassData oldexpected =
+                             builder.classdata.get(builder.expected);
+                         final MethodData meth =
+                             new MethodData(MethodData.Access.PROTECTED,
+                                            MethodData.Context.INSTANCE);
+                         final ClassData withDef =
+                             new ClassData(pck, meth);
+                         final int I = builder.methodref;
+                         final int C2 = builder.addClass(withDef);
+                         final int C1 = builder.addClass(emptyClass(pck));
+                         builder.hier.addInherit(C1, I);
+                         builder.hier.addInherit(C1, C2);
+                         builder.hier.addInherit(C2, I);
+                         builder.expected = C2;
+                         builder.objectref = C1;
+                     },
+                     /* Case 15: Superclass overrides.
+                      *
+                      * I[](*) = mref
+                      * C2[I](pack) = expected
+                      * C1[C2]() = oref
+                      */
+                     (final SelectionResolutionTestCase.Builder builder) -> {
+                         final ClassData.Package pck =
+                             builder.classdata.get(builder.expected).packageId;
+                         final ClassData oldexpected =
+                             builder.classdata.get(builder.expected);
+                         final MethodData meth =
+                             new MethodData(MethodData.Access.PACKAGE,
+                                            MethodData.Context.INSTANCE);
+                         final ClassData withDef =
+                             new ClassData(pck, meth);
+                         final int I = builder.methodref;
+                         final int C2 = builder.addClass(withDef);
+                         final int C1 = builder.addClass(emptyClass(pck));
+                         builder.hier.addInherit(C1, I);
+                         builder.hier.addInherit(C1, C2);
+                         builder.hier.addInherit(C2, I);
+                         builder.expected = C2;
+                         builder.objectref = C1;
+                     });
+
+    /***********************
+     * Ambiguous selection *
+     ***********************/
+
+    public static final Template MethodrefAmbiguousResolvedIsIface =
+        new Template("MethodrefAmbiguousResolvedIsIface",
+                    /* Inherit from interface.
+                     *
+                     * C2[](*) = mref, I[](any)
+                     * C1[C2,I]() = oref
+                     */
+                    (final SelectionResolutionTestCase.Builder builder) -> {
+                        final ClassData oldexpected =
+                            builder.classdata.get(builder.expected);
+                        final ClassData.Package pck = oldexpected.packageId;
+                        final MethodData.Context ctx = oldexpected.methoddata.context;
+                        final MethodData mdata =
+                            new MethodData(MethodData.Access.PUBLIC, ctx);
+                        final ClassData withDef = new ClassData(pck, mdata);
+                        final int C2 = builder.methodref;
+                        final int C1 = builder.addClass(emptyClass(pck));
+                        final int I = builder.addInterface(withDef);
+                        builder.hier.addInherit(C1, C2);
+                        builder.hier.addInherit(C1, I);
+                        builder.objectref = C1;
+                    });
+
+    public static final Template IfaceMethodrefAmbiguousResolvedIsIface =
+        new Template("IfaceMethodrefAmbiguousResolvedIsIface",
+                    /* Inherit from interface.
+                     *
+                     * I1[](*) = mref, I2[](any)
+                     * C1[I1,I2]() = oref
+                     */
+                    (final SelectionResolutionTestCase.Builder builder) -> {
+                        final ClassData oldexpected =
+                            builder.classdata.get(builder.expected);
+                        final ClassData.Package pck = oldexpected.packageId;
+                        final MethodData.Context ctx = oldexpected.methoddata.context;
+                        final MethodData mdata =
+                            new MethodData(MethodData.Access.PUBLIC, ctx);
+                        final ClassData withDef = new ClassData(pck, mdata);
+                        final int I1 = builder.methodref;
+                        final int C = builder.addClass(emptyClass(pck));
+                        final int I2 = builder.addInterface(withDef);
+                        builder.hier.addInherit(C, I1);
+                        builder.hier.addInherit(C, I2);
+                        builder.objectref = C;
+                    });
+
+    public static final Template InvokespecialAmbiguousResolvedIsIface =
+        new Template("InvokespecialAmbiguousResolvedIsIface",
+                    /* Inherit from interface.
+                     *
+                     * C2[](*) = csite, I[](any)
+                     * C1[C2,I]() = oref
+                     */
+                    (final SelectionResolutionTestCase.Builder builder) -> {
+                        final ClassData oldexpected =
+                            builder.classdata.get(builder.expected);
+                        final ClassData.Package pck = oldexpected.packageId;
+                        final MethodData.Context ctx = oldexpected.methoddata.context;
+                        final MethodData mdata =
+                            new MethodData(MethodData.Access.PUBLIC, ctx);
+                        final ClassData withDef = new ClassData(pck, mdata);
+                        final int C2 = builder.callsite;
+                        final int C1 = builder.addClass(emptyClass(pck));
+                        final int I = builder.addInterface(withDef);
+                        builder.hier.addInherit(C1, C2);
+                        builder.hier.addInherit(C1, I);
+                        builder.objectref = C1;
+                    });
+
+    /******************************
+     *   invokespecial Templates  *
+     ******************************/
+
+    // Create this by taking MethodrefSelection and replacing
+    // methodref with callsite.
+    public static final Template ObjectrefAssignableToCallsite =
+        new Template("ObjectrefAssignableToCallsite",
+                    /* Case 1: Objectref equals callsite
+                     *
+                     * C[](*) = csite = oref
+                     */
+                    (builder) -> {
+                        builder.objectref = builder.callsite;
+                    },
+                    /* Case 2: Inherit from super.
+                     *
+                     * C2[](*) = csite
+                     * C1[C2]() = oref
+                     */
+                    (final SelectionResolutionTestCase.Builder builder) -> {
+                        final ClassData.Package pck =
+                            builder.classdata.get(builder.callsite).packageId;
+                        final int C2 = builder.callsite;
+                        final int C1 = builder.addClass(emptyClass(pck));
+                        builder.hier.addInherit(C1, C2);
+                        builder.objectref = C1;
+                    });
+
+    public static final Template ObjectrefExactSubclassOfCallsite =
+        new Template("ObjectrefSubclassOfCallsite",
+                    /* Inherit from super.
+                     *
+                     * C2[](*) = csite
+                     * C1[C2]() = oref
+                     */
+                    (final SelectionResolutionTestCase.Builder builder) -> {
+                        final ClassData.Package pck =
+                            builder.classdata.get(builder.callsite).packageId;
+                        final int C2 = builder.callsite;
+                        final int C1 = builder.addClass(emptyClass(pck));
+                        builder.hier.addInherit(C1, C2);
+                        builder.objectref = C1;
+                    });
+
+    public static final Template ObjectrefEqualsOrExactSubclassOfCallsite =
+        new Template("ObjectrefEqualsOrExactSubclassOfCallsite",
+                     (final SelectionResolutionTestCase.Builder builder) -> {
+                         builder.objectref = builder.callsite;
+                     },
+                    /* Inherit from super.
+                     *
+                     * C2[](*) = csite
+                     * C1[C2]() = oref
+                     */
+                    (final SelectionResolutionTestCase.Builder builder) -> {
+                        final ClassData.Package pck =
+                            builder.classdata.get(builder.callsite).packageId;
+                        final int C2 = builder.callsite;
+                        final int C1 = builder.addClass(emptyClass(pck));
+                        builder.hier.addInherit(C1, C2);
+                        builder.objectref = C1;
+                    });
+
+    public static final Template ObjectrefEqualsCallsite =
+        new Template("TrivialObjectref",
+                     Collections.singleton((builder) -> {
+                             builder.objectref = builder.callsite;
+                         }));
+
+    public static final Template ObjectrefSubclassOfSubclassOfCallsite =
+        new Template("ObjectrefSubclassOfCallsite",
+                    /* Inherit from super.
+                     *
+                     * C3[](*) = csite
+                     * C2[C3]()
+                     * C1[C2]() = oref
+                     */
+                    (final SelectionResolutionTestCase.Builder builder) -> {
+                        final ClassData.Package pck =
+                            builder.classdata.get(builder.callsite).packageId;
+                        final int C3 = builder.callsite;
+                        final int C2 = builder.addClass(emptyClass(pck));
+                        final int C1 = builder.addClass(emptyClass(pck));
+                        builder.hier.addInherit(C2, C3);
+                        builder.hier.addInherit(C1, C2);
+                        builder.objectref = C1;
+                    });
+
+    private static class Placeholder extends ClassData {
+        private final String placeholder;
+
+
+        private Placeholder(final String placeholder,
+                            final MethodData methoddata) {
+            super(ClassData.Package.PLACEHOLDER, methoddata);
+            this.placeholder = placeholder;
+        }
+
+        private Placeholder(final String placeholder) {
+            this(placeholder, null);
+        }
+
+        public String toString() {
+            return " = <Placeholder for " + placeholder + ">\n\n";
+        }
+
+        public static final Placeholder objectref = new Placeholder("objectref");
+        public static final Placeholder methodref = new Placeholder("methodref");
+        public static final Placeholder callsite = new Placeholder("callsite");
+        public static final Placeholder expected =
+            new Placeholder("expected",
+                            new MethodData(MethodData.Access.PLACEHOLDER,
+                                           MethodData.Context.PLACEHOLDER));
+    }
+
+    public static void main(String... args) {
+
+        System.err.println("*** Resolution Templates ***\n");
+        final SelectionResolutionTestCase.Builder withExpectedIface =
+            new SelectionResolutionTestCase.Builder();
+        withExpectedIface.expected =
+            withExpectedIface.addInterface(Placeholder.expected);
+        final SelectionResolutionTestCase.Builder withExpectedClass =
+            new SelectionResolutionTestCase.Builder();
+        withExpectedClass.expected =
+            withExpectedClass.addClass(Placeholder.expected);
+
+        MethodrefNotEqualsExpectedClass.printCases(withExpectedClass);
+        MethodrefNotEqualsExpectedIface.printCases(withExpectedIface);
+        IfaceMethodrefNotEqualsExpected.printCases(withExpectedIface);
+        MethodrefAmbiguous.printCases(withExpectedIface);
+        IfaceMethodrefAmbiguous.printCases(withExpectedIface);
+        ReabstractExpectedIface.printCases(withExpectedIface);
+        ReabstractExpectedClass.printCases(withExpectedClass);
+
+        final SelectionResolutionTestCase.Builder methodrefExpectedIface =
+            withExpectedIface.copy();
+        methodrefExpectedIface.methodref =
+            methodrefExpectedIface.addClass(Placeholder.methodref);
+        final SelectionResolutionTestCase.Builder methodrefExpectedClass =
+            withExpectedClass.copy();
+        methodrefExpectedClass.methodref =
+            methodrefExpectedClass.addClass(Placeholder.methodref);
+        final SelectionResolutionTestCase.Builder ifaceMethodref =
+            withExpectedIface.copy();
+        ifaceMethodref.methodref =
+            ifaceMethodref.addInterface(Placeholder.methodref);
+
+        IgnoredAbstract.printCases(methodrefExpectedIface);
+        MethodrefSelectionResolvedIsClass.printCases(methodrefExpectedClass);
+        MethodrefSelectionResolvedIsIface.printCases(methodrefExpectedIface);
+        IfaceMethodrefSelection.printCases(ifaceMethodref);
+        IfaceMethodrefSelectionOverrideNonPublic.printCases(ifaceMethodref);
+
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/SelectionResolution/classes/selectionresolution/TestBuilder.java	Sat Apr 02 05:39:25 2016 +0200
@@ -0,0 +1,75 @@
+/*
+ * 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.
+ *
+ */
+
+package selectionresolution;
+
+import jdk.internal.org.objectweb.asm.Opcodes;
+
+import static jdk.internal.org.objectweb.asm.Opcodes.ACC_PUBLIC;
+import static jdk.internal.org.objectweb.asm.Opcodes.ACC_STATIC;
+
+class TestBuilder extends Builder {
+    private final ClassConstruct testClass;
+    private final Method mainMethod;
+
+    public TestBuilder(int classId, SelectionResolutionTestCase testcase) {
+        super(testcase);
+
+        // Make a public class Test that contains all our test methods
+        testClass = new Clazz("Test", null, -1, ACC_PUBLIC);
+
+        // Add a main method
+        mainMethod = testClass.addMethod("main", "([Ljava/lang/String;)V", ACC_PUBLIC + ACC_STATIC);
+
+    }
+
+    public ClassConstruct getMainTestClass() {
+        mainMethod.done();
+        return testClass;
+    }
+
+    public void addTest(ClassConstruct clazz, ClassBuilder.ExecutionMode execMode) {
+        Method m = clazz.addMethod("test", "()Ljava/lang/Integer;", ACC_PUBLIC + ACC_STATIC, execMode);
+        m.defaultInvoke(getInvokeInstruction(testcase.invoke),
+                    getName(testcase.methodref),
+                    getName(testcase.objectref));
+
+        mainMethod.makeStaticCall(clazz.getName(), "test", "()Ljava/lang/Integer;").done();
+    }
+
+    private static int getInvokeInstruction(SelectionResolutionTestCase.InvokeInstruction instr) {
+        switch (instr) {
+            case INVOKESTATIC:
+                return Opcodes.INVOKESTATIC;
+            case INVOKESPECIAL:
+                return Opcodes.INVOKESPECIAL;
+            case INVOKEINTERFACE:
+                return Opcodes.INVOKEINTERFACE;
+            case INVOKEVIRTUAL:
+                return Opcodes.INVOKEVIRTUAL;
+            default:
+                throw new AssertionError(instr.name());
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/Throwable/StackTraceLogging.java	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Sat Apr 02 05:39:25 2016 +0200
@@ -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();
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/Unsafe/PrimitiveHostClass.java	Sat Apr 02 05:39:25 2016 +0200
@@ -0,0 +1,99 @@
+/*
+ * 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.awt.Component;
+import java.lang.reflect.Field;
+import static jdk.internal.org.objectweb.asm.Opcodes.*;
+import jdk.internal.org.objectweb.asm.*;
+import sun.misc.Unsafe;
+
+/*
+ * @test PrimitiveHostClass
+ * @bug 8140665
+ * @summary Throws IllegalArgumentException if host class is a primitive class.
+ * @library /testlibrary
+ * @modules java.base/jdk.internal.org.objectweb.asm
+ *          java.base/sun.misc
+ * @compile -XDignore.symbol.file PrimitiveHostClass.java
+ * @run main/othervm PrimitiveHostClass
+ */
+
+public class PrimitiveHostClass {
+
+    static final Unsafe U;
+    static {
+        try {
+            Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe");
+            theUnsafe.setAccessible(true);
+            U = (Unsafe) theUnsafe.get(null);
+        } catch (Exception e) {
+            throw new AssertionError(e);
+        }
+    }
+
+    public static void testVMAnonymousClass(Class<?> hostClass) {
+
+        // choose a class name in the same package as the host class
+        String prefix = packageName(hostClass);
+        if (prefix.length() > 0)
+            prefix = prefix.replace('.', '/') + "/";
+        String className = prefix + "Anon";
+
+        // create the class
+        String superName = "java/lang/Object";
+        ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS
+                                         + ClassWriter.COMPUTE_FRAMES);
+        cw.visit(V1_8, ACC_PUBLIC + ACC_FINAL + ACC_SUPER,
+                 className, null, superName, null);
+        byte[] classBytes = cw.toByteArray();
+        int cpPoolSize = constantPoolSize(classBytes);
+        Class<?> anonClass =
+            U.defineAnonymousClass(hostClass, classBytes, new Object[cpPoolSize]);
+    }
+
+    private static String packageName(Class<?> c) {
+        if (c.isArray()) {
+            return packageName(c.getComponentType());
+        } else {
+            String name = c.getName();
+            int dot = name.lastIndexOf('.');
+            if (dot == -1) return "";
+            return name.substring(0, dot);
+        }
+    }
+
+    private static int constantPoolSize(byte[] classFile) {
+        return ((classFile[8] & 0xFF) << 8) | (classFile[9] & 0xFF);
+    }
+
+    public static void main(String args[]) {
+        testVMAnonymousClass(PrimitiveHostClass.class);
+        try {
+            testVMAnonymousClass(int.class);
+            throw new RuntimeException(
+                "Expected IllegalArgumentException not thrown");
+        } catch (IllegalArgumentException e) {
+            // Expected
+        }
+    }
+}
--- a/hotspot/test/runtime/logging/ClassInitializationTest.java	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/test/runtime/logging/ClassInitializationTest.java	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/test/runtime/logging/ClassResolutionTest.java	Sat Apr 02 05:39:25 2016 +0200
@@ -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]");
 
+    };
 
-    };
 }
--- a/hotspot/test/runtime/logging/ExceptionsTest.java	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/test/runtime/logging/ExceptionsTest.java	Sat Apr 02 05:39:25 2016 +0200
@@ -45,7 +45,7 @@
 
     static void analyzeOutputOn(ProcessBuilder pb) throws Exception {
         OutputAnalyzer output = new OutputAnalyzer(pb.start());
-        output.shouldContain("<a 'java/lang/RuntimeException': Test exception 1 for logging>");
+        output.shouldContain("<a 'java/lang/RuntimeException'").shouldContain(": Test exception 1 for logging>");
         output.shouldContain(" thrown in interpreter method ");
         output.shouldHaveExitValue(0);
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/logging/LoaderConstraintsTest.java	Sat Apr 02 05:39:25 2016 +0200
@@ -0,0 +1,88 @@
+/*
+ * 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 LoaderConstraintsTest
+ * @bug 8149996
+ * @library /testlibrary /runtime/testlibrary
+ * @library classes
+ * @build ClassUnloadCommon test.Empty jdk.test.lib.* jdk.test.lib.OutputAnalyzer jdk.test.lib.ProcessTools
+ * @run driver LoaderConstraintsTest
+ */
+
+import jdk.test.lib.*;
+import java.lang.ref.WeakReference;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+public class LoaderConstraintsTest {
+    private static OutputAnalyzer out;
+    private static ProcessBuilder pb;
+    private static class ClassUnloadTestMain {
+        public static void main(String... args) throws Exception {
+            String className = "test.Empty";
+            ClassLoader cl = ClassUnloadCommon.newClassLoader();
+            Class<?> c = cl.loadClass(className);
+            cl = null; c = null;
+            ClassUnloadCommon.triggerUnloading();
+        }
+    }
+
+    // Use the same command-line heap size setting as ../ClassUnload/UnloadTest.java
+    static ProcessBuilder exec(String... args) throws Exception {
+        List<String> argsList = new ArrayList<>();
+        Collections.addAll(argsList, args);
+        Collections.addAll(argsList, "-Xmn8m");
+        Collections.addAll(argsList, "-Dtest.classes=" + System.getProperty("test.classes","."));
+        Collections.addAll(argsList, ClassUnloadTestMain.class.getName());
+        return ProcessTools.createJavaProcessBuilder(argsList.toArray(new String[argsList.size()]));
+    }
+
+    public static void main(String... args) throws Exception {
+
+        // -XX:+TraceLoaderConstraints
+        pb = exec("-XX:+TraceLoaderConstraints");
+        out = new OutputAnalyzer(pb.start());
+        out.getOutput();
+        out.shouldContain("[classload,constraints] adding new constraint for name: java/lang/Class, loader[0]: jdk/internal/loader/ClassLoaders$AppClassLoader, loader[1]: <bootloader>");
+
+        // -Xlog:classload+constraints=info
+        pb = exec("-Xlog:classload+constraints=info");
+        out = new OutputAnalyzer(pb.start());
+        out.shouldContain("[classload,constraints] adding new constraint for name: java/lang/Class, loader[0]: jdk/internal/loader/ClassLoaders$AppClassLoader, loader[1]: <bootloader>");
+
+        // -XX:-TraceLoaderConstraints
+        pb = exec("-XX:-TraceLoaderConstraints");
+        out = new OutputAnalyzer(pb.start());
+        out.shouldNotContain("[classload,constraints]");
+
+        // -Xlog:classload+constraints=off
+        pb = exec("-Xlog:classload+constraints=off");
+        out = new OutputAnalyzer(pb.start());
+        out.shouldNotContain("[classload,constraints]");
+
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/logging/MonitorMismatchHelper.jasm	Sat Apr 02 05:39:25 2016 +0200
@@ -0,0 +1,114 @@
+/*
+ * 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.
+ */
+
+super public class MonitorMismatchHelper
+	version 52:0
+{
+
+private Field c:I;
+
+public Method "<init>":"()V"
+	stack 2 locals 1
+{
+		aload_0;
+		invokespecial	Method java/lang/Object."<init>":"()V";
+		aload_0;
+		iconst_0;
+		putfield	Field c:"I";
+		return;
+}
+
+public synchronized Method increment:"()V"
+	stack 3 locals 1
+{
+		aload_0;
+		dup;
+		getfield	Field c:"I";
+		iconst_1;
+		iadd;
+		putfield	Field c:"I";
+		return;
+}
+
+public synchronized Method decrement:"()V"
+	stack 3 locals 1
+{
+		aload_0;
+		dup;
+		getfield	Field c:"I";
+		iconst_1;
+		isub;
+		putfield	Field c:"I";
+		return;
+}
+
+public synchronized Method value:"()I"
+	stack 1 locals 1
+{
+		aload_0;
+		getfield	Field c:"I";
+		ireturn;
+}
+
+public static varargs Method main:"([Ljava/lang/String;)V"
+	stack 2 locals 4
+{
+		new	class MonitorMismatchHelper;
+		dup;
+		invokespecial	Method "<init>":"()V";
+		astore_1;
+		aload_1;
+		dup;
+		astore_2;
+		monitorenter;
+		try t0;
+		aload_1;
+		invokevirtual	Method increment:"()V";
+		aload_1;
+		invokevirtual	Method increment:"()V";
+		aload_1;
+		invokevirtual	Method decrement:"()V";
+		getstatic	Field java/lang/System.out:"Ljava/io/PrintStream;";
+		aload_1;
+		invokevirtual	Method value:"()I";
+		invokevirtual	Method java/io/PrintStream.print:"(I)V";
+		aload_2;
+		monitorexit;
+		endtry t0;
+		goto	L44;
+		catch t0 #0;
+		catch t1 #0;
+		try t1;
+		stack_frame_type full;
+		locals_map class "[Ljava/lang/String;", class MonitorMismatchHelper, class java/lang/Object;
+		stack_map class java/lang/Throwable;
+		astore_3;
+		aload_2;
+		endtry t1;
+		aload_3;
+		athrow;
+	L44:	stack_frame_type chop1;
+		return;
+}
+
+} // end Class MonitorMismatchHelper
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/logging/MonitorMismatchTest.java	Sat Apr 02 05:39:25 2016 +0200
@@ -0,0 +1,60 @@
+/*
+ * 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 MonitorMismatchTest
+ * @bug 8150084
+ * @library /testlibrary
+ * @compile MonitorMismatchHelper.jasm
+ * @build jdk.test.lib.OutputAnalyzer jdk.test.lib.ProcessTools jdk.test.lib.Platform
+ * @run driver MonitorMismatchTest
+ */
+
+import jdk.test.lib.OutputAnalyzer;
+import jdk.test.lib.ProcessTools;
+import jdk.test.lib.Platform;
+
+public class MonitorMismatchTest {
+
+    public static void main(String... args) throws Exception {
+        if (!Platform.isEmbedded()){
+            // monitormismatch should turn on.
+            ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-Xcomp",
+                                                                      "-XX:+TieredCompilation",
+                                                                      "-Xlog:monitormismatch=info",
+                                                                      "MonitorMismatchHelper");
+            OutputAnalyzer o = new OutputAnalyzer(pb.start());
+            o.shouldContain("[monitormismatch] Monitor mismatch in method");
+
+            // monitormismatch should turn off.
+            pb = ProcessTools.createJavaProcessBuilder("-Xcomp",
+                                                       "-XX:+TieredCompilation",
+                                                       "-Xlog:monitormismatch=off",
+                                                       "MonitorMismatchHelper");
+            o = new OutputAnalyzer(pb.start());
+            o.shouldNotContain("[monitormismatch]");
+        }
+    };
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/logging/RemovedDevelopFlagsTest.java	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Sat Apr 02 05:39:25 2016 +0200
@@ -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	Sat Apr 02 05:39:25 2016 +0200
@@ -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/serviceability/tmtools/jstack/JstackThreadTest.java	Sat Apr 02 05:39:25 2016 +0200
@@ -0,0 +1,75 @@
+/*
+ * 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.util.Arrays;
+import jdk.test.lib.JDKToolLauncher;
+import jdk.test.lib.OutputAnalyzer;
+import jdk.test.lib.ProcessTools;
+
+/*
+ * @test JstackThreadTest
+ * @bug 8151442
+ * @summary jstack doesn't close quotation marks properly with threads' name greater than 1996 characters
+ * @library /testlibrary
+ * @build jdk.test.lib.*
+ * @run main JstackThreadTest
+ */
+public class JstackThreadTest {
+  static class NamedThread extends Thread {
+    NamedThread(String name) {
+      setName(name);
+    }
+    @Override
+    public void run() {
+      try {
+            Thread.sleep(2000);
+          } catch(Exception e){
+            e.printStackTrace();
+          }
+        }
+    }
+
+  public static void main(String[] args) throws Exception {
+    StringBuilder sb = new StringBuilder();
+     /*create a string more than 1996 character */
+    for(int i = 0; i < 1998; i++){
+      sb.append("a");
+    }
+    testWithName(sb.toString());
+  }
+
+  private static void testWithName(String name) throws Exception {
+    // Start a thread with a long thread name
+    NamedThread thread = new NamedThread(name);
+    thread.start();
+    ProcessBuilder processBuilder = new ProcessBuilder();
+    JDKToolLauncher launcher = JDKToolLauncher.createUsingTestJDK("jstack");
+    launcher.addToolArg("-l");
+    launcher.addToolArg(Long.toString(ProcessTools.getProcessId()));
+    processBuilder.command(launcher.getCommand());
+    System.out.println(Arrays.toString(processBuilder.command().toArray()).replace(",", ""));
+    OutputAnalyzer output = ProcessTools.executeProcess(processBuilder);
+    System.out.println(output.getOutput());
+    output.shouldContain("\""+ name + "\"");
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/stress/gc/TestMultiThreadStressRSet.java	Sat Apr 02 05:39:25 2016 +0200
@@ -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();
+            }
+        }
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/stress/gc/TestStressIHOPMultiThread.java	Sat Apr 02 05:39:25 2016 +0200
@@ -0,0 +1,216 @@
+/*
+ * 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 TestStressIHOPMultiThread
+ * @bug 8148397
+ * @key stress
+ * @summary Stress test for IHOP
+ * @requires vm.gc=="G1" | vm.gc=="null"
+ * @run main/othervm/timeout=200 -Xmx128m -XX:G1HeapWastePercent=0 -XX:G1MixedGCCountTarget=1
+ *              -XX:+UseG1GC -XX:G1HeapRegionSize=1m -XX:+G1UseAdaptiveIHOP
+ *              -Xlog:gc+ihop=debug,gc+ihop+ergo=debug,gc+ergo=debug:TestStressIHOPMultiThread1.log
+ *              -Dtimeout=2 -DheapUsageMinBound=30 -DheapUsageMaxBound=80
+ *              -Dthreads=2 TestStressIHOPMultiThread
+ * @run main/othervm/timeout=200 -Xmx256m -XX:G1HeapWastePercent=0 -XX:G1MixedGCCountTarget=1
+ *              -XX:+UseG1GC -XX:G1HeapRegionSize=2m -XX:+G1UseAdaptiveIHOP
+ *              -Xlog:gc+ihop=debug,gc+ihop+ergo=debug,gc+ergo=debug:TestStressIHOPMultiThread2.log
+ *              -Dtimeout=2 -DheapUsageMinBound=60 -DheapUsageMaxBound=90
+ *              -Dthreads=3 TestStressIHOPMultiThread
+ * @run main/othervm/timeout=200 -Xmx256m -XX:G1HeapWastePercent=0 -XX:G1MixedGCCountTarget=1
+ *              -XX:+UseG1GC -XX:G1HeapRegionSize=4m -XX:-G1UseAdaptiveIHOP
+ *              -Xlog:gc+ihop=debug,gc+ihop+ergo=debug,gc+ergo=debug:TestStressIHOPMultiThread3.log
+ *              -Dtimeout=2 -DheapUsageMinBound=40 -DheapUsageMaxBound=90
+ *              -Dthreads=5 TestStressIHOPMultiThread
+ * @run main/othervm/timeout=200 -Xmx128m -XX:G1HeapWastePercent=0 -XX:G1MixedGCCountTarget=1
+ *              -XX:+UseG1GC -XX:G1HeapRegionSize=8m -XX:+G1UseAdaptiveIHOP
+ *              -Xlog:gc+ihop=debug,gc+ihop+ergo=debug,gc+ergo=debug:TestStressIHOPMultiThread4.log
+ *              -Dtimeout=2 -DheapUsageMinBound=20 -DheapUsageMaxBound=90
+ *              -Dthreads=10 TestStressIHOPMultiThread
+ * @run main/othervm/timeout=200 -Xmx512m -XX:G1HeapWastePercent=0 -XX:G1MixedGCCountTarget=1
+ *              -XX:+UseG1GC -XX:G1HeapRegionSize=16m -XX:+G1UseAdaptiveIHOP
+ *              -Xlog:gc+ihop=debug,gc+ihop+ergo=debug,gc+ergo=debug:TestStressIHOPMultiThread5.log
+ *              -Dtimeout=2 -DheapUsageMinBound=20 -DheapUsageMaxBound=90
+ *              -Dthreads=17 TestStressIHOPMultiThread
+ */
+
+import java.util.ArrayList;
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * Stress test for Adaptive IHOP. Starts a number of threads that fill and free
+ * specified amount of memory. Tests work with enabled IHOP logging.
+ *
+ */
+public class TestStressIHOPMultiThread {
+
+    public final static List<Object> GARBAGE = new LinkedList<>();
+
+    private final long HEAP_SIZE;
+    // Amount of memory to be allocated before iterations start
+    private final long HEAP_PREALLOC_SIZE;
+    // Amount of memory to be allocated and freed during iterations
+    private final long HEAP_ALLOC_SIZE;
+    private final int CHUNK_SIZE = 100000;
+
+    private final int TIMEOUT;
+    private final int THREADS;
+    private final int HEAP_LOW_BOUND;
+    private final int HEAP_HIGH_BOUND;
+
+    private volatile boolean running = true;
+    private final List<AllocationThread> threads;
+
+    public static void main(String[] args) throws InterruptedException {
+        new TestStressIHOPMultiThread().start();
+
+    }
+
+    TestStressIHOPMultiThread() {
+
+        TIMEOUT = Integer.getInteger("timeout") * 60;
+        THREADS = Integer.getInteger("threads");
+        HEAP_LOW_BOUND = Integer.getInteger("heapUsageMinBound");
+        HEAP_HIGH_BOUND = Integer.getInteger("heapUsageMaxBound");
+        HEAP_SIZE = Runtime.getRuntime().maxMemory();
+
+        HEAP_PREALLOC_SIZE = HEAP_SIZE * HEAP_LOW_BOUND / 100;
+        HEAP_ALLOC_SIZE = HEAP_SIZE * (HEAP_HIGH_BOUND - HEAP_LOW_BOUND) / 100;
+
+        threads = new ArrayList<>(THREADS);
+    }
+
+    public void start() throws InterruptedException {
+        fill();
+        createThreads();
+        waitForStress();
+        stressDone();
+        waitForFinish();
+    }
+
+    /**
+     * Fills HEAP_PREALLOC_SIZE bytes of garbage.
+     */
+    private void fill() {
+        long allocated = 0;
+        while (allocated < HEAP_PREALLOC_SIZE) {
+            GARBAGE.add(new byte[CHUNK_SIZE]);
+            allocated += CHUNK_SIZE;
+        }
+    }
+
+    /**
+     * Creates a number of threads which will fill and free amount of memory.
+     */
+    private void createThreads() {
+        for (int i = 0; i < THREADS; ++i) {
+            System.out.println("Create thread " + i);
+            AllocationThread thread =new TestStressIHOPMultiThread.AllocationThread(i, HEAP_ALLOC_SIZE / THREADS);
+            // Put reference to thread garbage into common garbage for avoiding possible optimization.
+            GARBAGE.add(thread.getList());
+            threads.add(thread);
+        }
+        threads.forEach(t -> t.start());
+    }
+
+    /**
+     * Wait each thread for finishing
+     */
+    private void waitForFinish() {
+        threads.forEach(thread -> {
+            thread.silentJoin();
+        });
+    }
+
+    private boolean isRunning() {
+        return running;
+    }
+
+    private void stressDone() {
+        running = false;
+    }
+
+    private void waitForStress() throws InterruptedException {
+        Thread.sleep(TIMEOUT * 1000);
+    }
+
+    private class AllocationThread extends Thread {
+
+        private final List<Object> garbage;
+
+        private final long amountOfGarbage;
+        private final int threadId;
+
+        public AllocationThread(int id, long amount) {
+            super("Thread " + id);
+            threadId = id;
+            amountOfGarbage = amount;
+            garbage = new LinkedList<>();
+        }
+
+        /**
+         * Returns list of garbage.
+         * @return List with thread garbage.
+         */
+        public List<Object> getList(){
+            return garbage;
+        }
+
+        @Override
+        public void run() {
+            System.out.println("Start the thread " + threadId);
+            while (TestStressIHOPMultiThread.this.isRunning()) {
+                allocate(amountOfGarbage);
+                free();
+            }
+        }
+
+        private void silentJoin() {
+            System.out.println("Join the thread " + threadId);
+            try {
+                join();
+            } catch (InterruptedException ie) {
+                throw new RuntimeException(ie);
+            }
+        }
+
+        /**
+         * Allocates thread local garbage
+         */
+        private void allocate(long amount) {
+            long allocated = 0;
+            while (allocated < amount && TestStressIHOPMultiThread.this.isRunning()) {
+                garbage.add(new byte[CHUNK_SIZE]);
+                allocated += CHUNK_SIZE;
+            }
+        }
+
+        /**
+         * Frees thread local garbage
+         */
+        private void free() {
+            garbage.clear();
+        }
+    }
+}