Merge jdk8-b38
authorduke
Wed, 05 Jul 2017 18:10:27 +0200
changeset 12579 4cc5610a6dd6
parent 12578 cf47ce2b7787 (diff)
parent 12492 2e8c637e1ab6 (current diff)
child 12580 8c06650e5d4b
child 12581 f99c8eb5eb17
child 12582 46d24df71c5d
child 12585 6b56109b3528
child 12603 926e0735f658
child 12604 4b1837b6c764
child 12608 999611eec364
child 12610 a70d185bcc77
child 12612 b5e60661b9a2
child 12614 679d89b6a21a
child 12646 fa5227d43363
Merge
--- a/.hgtags-top-repo	Wed Jul 05 18:09:43 2017 +0200
+++ b/.hgtags-top-repo	Wed Jul 05 18:10:27 2017 +0200
@@ -158,3 +158,4 @@
 894a478d2c4819a1a0f230bd7bdd09f3b2de9a8c jdk8-b34
 5285317ebb4e8e4f6d8d52b5616fa801e2ea844d jdk8-b35
 6a6ba0a07f33d37a2f97b1107e60c6a9a69ec84d jdk8-b36
+b2972095a4b1e2a97409b7c3df61f3b263a5ce14 jdk8-b37
--- a/README-builds.html	Wed Jul 05 18:09:43 2017 +0200
+++ b/README-builds.html	Wed Jul 05 18:10:27 2017 +0200
@@ -65,6 +65,7 @@
                         <li><a href="#linux">Basic Linux System Setup</a> </li>
                         <li><a href="#solaris">Basic Solaris System Setup</a> </li>
                         <li><a href="#windows">Basic Windows System Setup</a> </li>
+                        <li><a href="#macosx">Basic Mac OS X System Setup</a></li>
                         <li><a href="#dependencies">Build Dependencies</a>
                             <ul>
                                 <li><a href="#bootjdk">Bootstrap JDK</a> </li>
@@ -230,6 +231,12 @@
                         <td>Microsoft Visual Studio C++ 2010 Professional Edition</td>
                         <td>JDK 6u18</td>
                     </tr>
+                    <tr>
+                        <td>Mac OS X X64 (64-bit)</td>
+                        <td>Mac OS X 10.7.3 "Lion"</td>
+                        <td>XCode 4.1 or later</td>
+                        <td>Java for OS X Lion Update 1</td>
+                    </tr>
                 </tbody>
             </table>
             <p>
@@ -951,6 +958,36 @@
         </blockquote>
         <!-- ------------------------------------------------------ -->
         <hr>
+        <h3><a name="macosx">Basic Mac OS X System Setup</a></h3>
+        <blockquote> 
+            <strong>X64 only:</strong>
+            The minimum recommended hardware for building
+            the Mac OS X version is any 64-bit capable Intel processor, at least 2
+            GB of RAM, and approximately 3 GB of free disk space. You should also
+            have OS X Lion 10.7.3 installed.
+        </blockquote>
+        <!-- ------------------------------------------------------ -->
+
+        <h4><a name="macosx_checklist">Basic Mac OS X Check List</a></h4>
+        <blockquote>
+            <ol>
+                <li>
+                    Install <a href="https://developer.apple.com/xcode/">XCode 4.1</a> or newer. 
+		    If you install XCode 4.3 or newer, make sure you also install 
+		    "Command line tools" found under the preferences pane "Downloads".
+                </li>
+                <li>
+                    Install <a href="http://support.apple.com/kb/dl1421" target="_blank">"Java for OS X Lion Update 1"</a>, 
+                    set <tt><a href="#ALT_BOOTDIR">ALT_BOOTDIR</a> to <code>`/usr/libexec/java_home -v 1.6`</code></tt>
+                </li>
+                <li>
+                    <a href="#importjdk">Optional Import JDK</a>, set
+                    <tt><a href="#ALT_JDK_IMPORT_PATH">ALT_JDK_IMPORT_PATH</a></tt>.
+                </li>
+            </ol>
+        </blockquote>
+        <!-- ------------------------------------------------------ -->
+        <hr>
         <h3><a name="dependencies">Build Dependencies</a></h3>
         <blockquote>
             Depending on the platform, the OpenJDK build process has some basic
@@ -1194,6 +1231,10 @@
     set INCLUDE=%VSINSTALLDIR%\vc\include;%WindowsSdkDir%\include
     set LIB=%VSINSTALLDIR%\vc\lib\amd64;%WindowsSdkDir%\lib\x64
                 </pre>
+                <strong><a name="llvmgcc">OS X Lion 10.7.3: LLVM GCC</a></strong>
+                <blockquote>
+                   LLVM GCC is bundled with XCode. The version should be at least 4.2.1.
+                </blockquote>
             </blockquote>
             <!-- ------------------------------------------------------ --> 
             <h4><a name="zip">Zip and Unzip</a></h4>
--- a/corba/.hgtags	Wed Jul 05 18:09:43 2017 +0200
+++ b/corba/.hgtags	Wed Jul 05 18:10:27 2017 +0200
@@ -158,3 +158,4 @@
 e24c5cc8b0f7cc48374eef0f995838fb4823e0eb jdk8-b34
 e3d735914edd0a621b16bb85417423f8e6af5d51 jdk8-b35
 a5a61f259961a7f46b002e5cc50b4a9bf86927b6 jdk8-b36
+83fac66442cf680bb59ec9e3a71cc4729322b595 jdk8-b37
--- a/corba/make/common/shared/Platform.gmk	Wed Jul 05 18:09:43 2017 +0200
+++ b/corba/make/common/shared/Platform.gmk	Wed Jul 05 18:10:27 2017 +0200
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
@@ -275,7 +275,7 @@
                     echo sparc \
                     ;; \
                 x86_64) \
-                    echo amd64 \
+                    echo x86_64 \
                     ;; \
                 "Power Macintosh") \
                     echo ppc \
@@ -287,12 +287,13 @@
   ARCH        := $(shell $(archExpr) )
   ARCH_FAMILY := $(ARCH)
 
-  # Darwin x86 builds are i386/amd64 universal.
-  ifeq ($(SYSTEM_UNAME), Darwin)
-    ifneq ($(ARCH), ppc)
-      ARCH=universal
-    endif
-  endif
+  # Darwin builds are currently universal but only include 64-bit
+  # 
+  # ifeq ($(SYSTEM_UNAME), Darwin)
+  #  ifneq ($(ARCH), ppc)
+  #    ARCH=universal
+  #  endif
+  # endif
 
   # i586, sparc, and ppc are 32 bit, amd64 and sparc64 are 64
   ifneq (,$(findstring $(ARCH), i586 sparc ppc universal))
--- a/corba/src/share/classes/com/sun/corba/se/impl/orbutil/DefineWrapper.sjava	Wed Jul 05 18:09:43 2017 +0200
+++ b/corba/src/share/classes/com/sun/corba/se/impl/orbutil/DefineWrapper.sjava	Wed Jul 05 18:10:27 2017 +0200
@@ -1,3 +1,28 @@
+/*
+ * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
 package com.sun.corba.se.impl.orbutil ;
 
 import java.lang.reflect.Method;
--- a/corba/src/share/classes/com/sun/corba/se/impl/presentation/rmi/IDLTypesUtil_save.sjava	Wed Jul 05 18:09:43 2017 +0200
+++ b/corba/src/share/classes/com/sun/corba/se/impl/presentation/rmi/IDLTypesUtil_save.sjava	Wed Jul 05 18:10:27 2017 +0200
@@ -1,3 +1,27 @@
+/*
+ * Copyright (c) 2004, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
 
 package com.sun.corba.se.impl.presentation.rmi ;
 
--- a/hotspot/.hgtags	Wed Jul 05 18:09:43 2017 +0200
+++ b/hotspot/.hgtags	Wed Jul 05 18:10:27 2017 +0200
@@ -242,3 +242,5 @@
 f621660a297baa48fab9dca28e99d318826e8304 jdk8-b35
 dff6e3459210f8dd0430b9b03ccc99280560da30 hs24-b08
 50b4400ca1ecb2ac2fde35f5e53ec8f04b86be7f jdk8-b36
+bfcf92bfefb82da00f7fdbf0d9273feaa0a9456d jdk8-b37
+7d5ec8bf38d1b12e0e09ec381f10976b8beede3b hs24-b09
--- a/hotspot/agent/src/os/linux/ps_core.c	Wed Jul 05 18:09:43 2017 +0200
+++ b/hotspot/agent/src/os/linux/ps_core.c	Wed Jul 05 18:10:27 2017 +0200
@@ -440,7 +440,7 @@
       int j = 0;
       print_debug("---- sorted virtual address map ----\n");
       for (j = 0; j < ph->core->num_maps; j++) {
-        print_debug("base = 0x%lx\tsize = %zd\n", ph->core->map_array[j]->vaddr,
+        print_debug("base = 0x%lx\tsize = %zu\n", ph->core->map_array[j]->vaddr,
                                          ph->core->map_array[j]->memsz);
       }
    }
--- a/hotspot/make/Makefile	Wed Jul 05 18:09:43 2017 +0200
+++ b/hotspot/make/Makefile	Wed Jul 05 18:10:27 2017 +0200
@@ -136,31 +136,36 @@
 ifeq ($(OSNAME),windows)
 	@$(ECHO) "No docs ($(VM_TARGET)) for windows"
 else
+# We specify 'BUILD_FLAVOR=product' so that the proper
+# ENABLE_FULL_DEBUG_SYMBOLS value is used.
 	$(CD) $(OUTPUTDIR); \
 	    $(MAKE) -f $(ABS_OS_MAKEFILE) \
-		      $(MAKE_ARGS) docs
+		      $(MAKE_ARGS) BUILD_FLAVOR=product docs
 endif
 
 # Build variation of hotspot
 $(C1_VM_TARGETS):
 	$(CD) $(GAMMADIR)/make; \
-	$(MAKE) VM_TARGET=$@ generic_build1 $(ALT_OUT)
+	$(MAKE) BUILD_FLAVOR=$(@:%1=%) VM_TARGET=$@ generic_build1 $(ALT_OUT)
 
 $(C2_VM_TARGETS):
 	$(CD) $(GAMMADIR)/make; \
-	$(MAKE) VM_TARGET=$@ generic_build2 $(ALT_OUT)
+	$(MAKE) BUILD_FLAVOR=$@ VM_TARGET=$@ generic_build2 $(ALT_OUT)
 
 $(KERNEL_VM_TARGETS):
 	$(CD) $(GAMMADIR)/make; \
-	$(MAKE) VM_TARGET=$@ generic_buildkernel $(ALT_OUT)
+	$(MAKE) BUILD_FLAVOR=$(@:%kernel=%) VM_TARGET=$@ \
+	  generic_buildkernel $(ALT_OUT)
 
 $(ZERO_VM_TARGETS):
 	$(CD) $(GAMMADIR)/make; \
-	$(MAKE) VM_TARGET=$@ generic_buildzero $(ALT_OUT)
+	$(MAKE) BUILD_FLAVOR=$(@:%zero=%) VM_TARGET=$@ \
+	  generic_buildzero $(ALT_OUT)
 
 $(SHARK_VM_TARGETS):
 	$(CD) $(GAMMADIR)/make; \
-	$(MAKE) VM_TARGET=$@ generic_buildshark $(ALT_OUT)
+	$(MAKE) BUILD_FLAVOR=$(@:%shark=%) VM_TARGET=$@ \
+	  generic_buildshark $(ALT_OUT)
 
 # Build compiler1 (client) rule, different for platforms
 generic_build1:
@@ -237,25 +242,37 @@
 # Export file rule
 generic_export: $(EXPORT_LIST)
 export_product:
-	$(MAKE) VM_SUBDIR=product                            generic_export
+	$(MAKE) BUILD_FLAVOR=$(@:export_%=%) VM_SUBDIR=$(@:export_%=%) \
+          generic_export
 export_fastdebug:
-	$(MAKE) VM_SUBDIR=fastdebug EXPORT_SUBDIR=/fastdebug generic_export
+	$(MAKE) BUILD_FLAVOR=$(@:export_%=%) VM_SUBDIR=$(@:export_%=%) \
+	  EXPORT_SUBDIR=/$(@:export_%=%) \
+	  generic_export
 export_debug:
-	$(MAKE) VM_SUBDIR=${VM_DEBUG} EXPORT_SUBDIR=/debug   generic_export
+	$(MAKE) BUILD_FLAVOR=$(@:export_%=%) VM_SUBDIR=${VM_DEBUG} \
+	  EXPORT_SUBDIR=/$(@:export_%=%) \
+	  generic_export
 export_optimized:
-	$(MAKE) VM_SUBDIR=optimized EXPORT_SUBDIR=/optimized generic_export
+	$(MAKE) BUILD_FLAVOR=$(@:export_%=%) VM_SUBDIR=$(@:export_%=%) \
+	  EXPORT_SUBDIR=/$(@:export_%=%) \
+	  generic_export
 export_product_jdk::
-	$(MAKE) ALT_EXPORT_PATH=$(JDK_IMAGE_DIR) \
-		VM_SUBDIR=product                            generic_export
+	$(MAKE) BUILD_FLAVOR=$(@:export_%_jdk=%) \
+	  VM_SUBDIR=$(@:export_%_jdk=%) ALT_EXPORT_PATH=$(JDK_IMAGE_DIR) \
+	  generic_export
 export_optimized_jdk::
-	$(MAKE) ALT_EXPORT_PATH=$(JDK_IMAGE_DIR) \
-		VM_SUBDIR=optimized                          generic_export
+	$(MAKE) BUILD_FLAVOR=$(@:export_%_jdk=%) \
+	  VM_SUBDIR=$(@:export_%_jdk=%) ALT_EXPORT_PATH=$(JDK_IMAGE_DIR) \
+	  generic_export
 export_fastdebug_jdk::
-	$(MAKE) ALT_EXPORT_PATH=$(JDK_IMAGE_DIR)/fastdebug \
-		VM_SUBDIR=fastdebug                          generic_export
+	$(MAKE) BUILD_FLAVOR=$(@:export_%_jdk=%) \
+	  VM_SUBDIR=$(@:export_%_jdk=%)  \
+	  ALT_EXPORT_PATH=$(JDK_IMAGE_DIR)/$(@:export_%_jdk=%) \
+	  generic_export
 export_debug_jdk::
-	$(MAKE) ALT_EXPORT_PATH=$(JDK_IMAGE_DIR)/debug \
-		VM_SUBDIR=${VM_DEBUG}                        generic_export
+	$(MAKE) BUILD_FLAVOR=$(@:export_%_jdk=%) VM_SUBDIR=${VM_DEBUG} \
+	  ALT_EXPORT_PATH=$(JDK_IMAGE_DIR)/$(@:export_%_jdk=%) \
+	  generic_export
 
 # Export file copy rules
 XUSAGE=$(HS_SRC_DIR)/share/vm/Xusage.txt
@@ -300,6 +317,8 @@
 	$(install-file)
 
 # Other libraries (like SA)
+$(EXPORT_JRE_BIN_DIR)/%.diz: $(MISC_DIR)/%.diz
+	$(install-file)
 $(EXPORT_JRE_BIN_DIR)/%.dll: $(MISC_DIR)/%.dll
 	$(install-file)
 $(EXPORT_JRE_BIN_DIR)/%.pdb: $(MISC_DIR)/%.pdb
@@ -308,6 +327,8 @@
 	$(install-file)
 
 # Client files always come from C1 area
+$(EXPORT_CLIENT_DIR)/%.diz:  $(C1_DIR)/%.diz
+	$(install-file)
 $(EXPORT_CLIENT_DIR)/%.dll:  $(C1_DIR)/%.dll
 	$(install-file)
 $(EXPORT_CLIENT_DIR)/%.pdb:  $(C1_DIR)/%.pdb
@@ -316,6 +337,8 @@
 	$(install-file)
 
 # Server files always come from C2 area
+$(EXPORT_SERVER_DIR)/%.diz:  $(C2_DIR)/%.diz
+	$(install-file)
 $(EXPORT_SERVER_DIR)/%.dll:  $(C2_DIR)/%.dll
 	$(install-file)
 $(EXPORT_SERVER_DIR)/%.pdb:  $(C2_DIR)/%.pdb
@@ -324,6 +347,8 @@
 	$(install-file)
 
 # Kernel files always come from kernel area
+$(EXPORT_KERNEL_DIR)/%.diz:  $(KERNEL_DIR)/%.diz
+	$(install-file)
 $(EXPORT_KERNEL_DIR)/%.dll:  $(KERNEL_DIR)/%.dll
 	$(install-file)
 $(EXPORT_KERNEL_DIR)/%.pdb:  $(KERNEL_DIR)/%.pdb
@@ -347,6 +372,12 @@
 		$(install-file)
         $(EXPORT_SERVER_DIR)/64/%.debuginfo:    		$(C2_DIR)/%.debuginfo
 		$(install-file)
+        $(EXPORT_JRE_LIB_ARCH_DIR)/%.diz: 			$(C2_DIR)/%.diz
+		$(install-file)
+        $(EXPORT_SERVER_DIR)/%.diz:       			$(C2_DIR)/%.diz
+		$(install-file)
+        $(EXPORT_SERVER_DIR)/64/%.diz:    			$(C2_DIR)/%.diz
+		$(install-file)
     endif
     ifeq ($(JVM_VARIANT_CLIENT), true)
         $(EXPORT_JRE_LIB_ARCH_DIR)/%.$(LIBRARY_SUFFIX): $(C1_DIR)/%.$(LIBRARY_SUFFIX)
@@ -361,6 +392,12 @@
 		$(install-file)
         $(EXPORT_CLIENT_DIR)/64/%.debuginfo:    		$(C1_DIR)/%.debuginfo
 		$(install-file)
+        $(EXPORT_JRE_LIB_ARCH_DIR)/%.diz: 			$(C1_DIR)/%.diz
+		$(install-file)
+        $(EXPORT_CLIENT_DIR)/%.diz:       			$(C1_DIR)/%.diz
+		$(install-file)
+        $(EXPORT_CLIENT_DIR)/64/%.diz:    			$(C1_DIR)/%.diz
+		$(install-file)
     endif
     ifeq ($(JVM_VARIANT_ZEROSHARK), true)
         $(EXPORT_JRE_LIB_ARCH_DIR)/%.$(LIBRARY_SUFFIX): $(SHARK_DIR)/%.$(LIBRARY_SUFFIX)
--- a/hotspot/make/hotspot_version	Wed Jul 05 18:09:43 2017 +0200
+++ b/hotspot/make/hotspot_version	Wed Jul 05 18:10:27 2017 +0200
@@ -35,7 +35,7 @@
 
 HS_MAJOR_VER=24
 HS_MINOR_VER=0
-HS_BUILD_NUMBER=08
+HS_BUILD_NUMBER=09
 
 JDK_MAJOR_VER=1
 JDK_MINOR_VER=8
--- a/hotspot/make/linux/Makefile	Wed Jul 05 18:09:43 2017 +0200
+++ b/hotspot/make/linux/Makefile	Wed Jul 05 18:10:27 2017 +0200
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
@@ -210,7 +210,7 @@
 BUILDTREE_MAKE    = $(GAMMADIR)/make/$(OSNAME)/makefiles/buildtree.make
 BUILDTREE_VARS    = GAMMADIR=$(GAMMADIR) OS_FAMILY=$(OSNAME) SRCARCH=$(SRCARCH) BUILDARCH=$(BUILDARCH) LIBARCH=$(LIBARCH)
 BUILDTREE_VARS   += HOTSPOT_RELEASE_VERSION=$(HOTSPOT_RELEASE_VERSION) HOTSPOT_BUILD_VERSION=$(HOTSPOT_BUILD_VERSION) JRE_RELEASE_VERSION=$(JRE_RELEASE_VERSION)
-BUILDTREE_VARS   += OBJCOPY=$(OBJCOPY) STRIP_POLICY=$(STRIP_POLICY)
+BUILDTREE_VARS   += ENABLE_FULL_DEBUG_SYMBOLS=$(ENABLE_FULL_DEBUG_SYMBOLS) OBJCOPY=$(OBJCOPY) STRIP_POLICY=$(STRIP_POLICY) ZIP_DEBUGINFO_FILES=$(ZIP_DEBUGINFO_FILES) ZIPEXE=$(ZIPEXE)
 
 BUILDTREE         = $(MAKE) -f $(BUILDTREE_MAKE) $(BUILDTREE_VARS)
 
@@ -337,9 +337,11 @@
 
 # Doc target.  This is the same for all build options.
 #     Hence create a docs directory beside ...$(ARCH)_[...]
+# We specify 'BUILD_FLAVOR=product' so that the proper
+# ENABLE_FULL_DEBUG_SYMBOLS value is used.
 docs: checks
 	$(QUIETLY) mkdir -p $(SUBDIR_DOCS)
-	$(MAKE) -f $(GAMMADIR)/make/$(OSNAME)/makefiles/jvmti.make $(MFLAGS) $(BUILDTREE_VARS) JvmtiOutDir=$(SUBDIR_DOCS) jvmtidocs
+	$(MAKE) -f $(GAMMADIR)/make/$(OSNAME)/makefiles/jvmti.make $(MFLAGS) $(BUILDTREE_VARS) JvmtiOutDir=$(SUBDIR_DOCS) BUILD_FLAVOR=product jvmtidocs
 
 # Synonyms for win32-like targets.
 compiler2:  jvmg product
--- a/hotspot/make/linux/makefiles/buildtree.make	Wed Jul 05 18:09:43 2017 +0200
+++ b/hotspot/make/linux/makefiles/buildtree.make	Wed Jul 05 18:10:27 2017 +0200
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
@@ -236,10 +236,16 @@
 	echo "$(call gamma-path,commonsrc,os/posix/vm)"; \
 	[ -n "$(CFLAGS_BROWSE)" ] && \
 	    echo && echo "CFLAGS_BROWSE = $(CFLAGS_BROWSE)"; \
+	[ -n "$(ENABLE_FULL_DEBUG_SYMBOLS)" ] && \
+	    echo && echo "ENABLE_FULL_DEBUG_SYMBOLS = $(ENABLE_FULL_DEBUG_SYMBOLS)"; \
 	[ -n "$(OBJCOPY)" ] && \
 	    echo && echo "OBJCOPY = $(OBJCOPY)"; \
 	[ -n "$(STRIP_POLICY)" ] && \
 	    echo && echo "STRIP_POLICY = $(STRIP_POLICY)"; \
+	[ -n "$(ZIP_DEBUGINFO_FILES)" ] && \
+	    echo && echo "ZIP_DEBUGINFO_FILES = $(ZIP_DEBUGINFO_FILES)"; \
+	[ -n "$(ZIPEXE)" ] && \
+	    echo && echo "ZIPEXE = $(ZIPEXE)"; \
 	[ -n "$(HOTSPOT_EXTRA_SYSDEFS)" ] && \
 	    echo && \
 	    echo "HOTSPOT_EXTRA_SYSDEFS\$$(HOTSPOT_EXTRA_SYSDEFS) = $(HOTSPOT_EXTRA_SYSDEFS)" && \
--- a/hotspot/make/linux/makefiles/defs.make	Wed Jul 05 18:09:43 2017 +0200
+++ b/hotspot/make/linux/makefiles/defs.make	Wed Jul 05 18:10:27 2017 +0200
@@ -141,32 +141,70 @@
 endif
 
 ifeq ($(JDK6_OR_EARLIER),0)
-  # Full Debug Symbols is supported on JDK7 or newer
+  # Full Debug Symbols is supported on JDK7 or newer.
+  # The Full Debug Symbols (FDS) default for BUILD_FLAVOR == product
+  # builds is enabled with debug info files ZIP'ed to save space. For
+  # BUILD_FLAVOR != product builds, FDS is always enabled, after all a
+  # debug build without debug info isn't very useful.
+  # The ZIP_DEBUGINFO_FILES option only has meaning when FDS is enabled.
+  #
+  # If you invoke a build with FULL_DEBUG_SYMBOLS=0, then FDS will be
+  # disabled for a BUILD_FLAVOR == product build.
+  #
+  # Note: Use of a different variable name for the FDS override option
+  # versus the FDS enabled check is intentional (FULL_DEBUG_SYMBOLS
+  # versus ENABLE_FULL_DEBUG_SYMBOLS). For auto build systems that pass
+  # in options via environment variables, use of distinct variables
+  # prevents strange behaviours. For example, in a BUILD_FLAVOR !=
+  # product build, the FULL_DEBUG_SYMBOLS environment variable will be
+  # 0, but the ENABLE_FULL_DEBUG_SYMBOLS make variable will be 1. If
+  # the same variable name is used, then different values can be picked
+  # up by different parts of the build. Just to be clear, we only need
+  # two variable names because the incoming option value can be
+  # overridden in some situations, e.g., a BUILD_FLAVOR != product
+  # build.
 
-  # Default OBJCOPY comes from GNU Binutils on Linux:
-  DEF_OBJCOPY=/usr/bin/objcopy
-  ifdef CROSS_COMPILE_ARCH
-    # don't try to generate .debuginfo files when cross compiling
-    _JUNK_ := $(shell \
-      echo >&2 "INFO: cross compiling for ARCH $(CROSS_COMPILE_ARCH)," \
-        "skipping .debuginfo generation.")
+  ifeq ($(BUILD_FLAVOR), product)
+    FULL_DEBUG_SYMBOLS ?= 1
+    ENABLE_FULL_DEBUG_SYMBOLS = $(FULL_DEBUG_SYMBOLS)
+  else
+    # debug variants always get Full Debug Symbols (if available)
+    ENABLE_FULL_DEBUG_SYMBOLS = 1
+  endif
+  _JUNK_ := $(shell \
+    echo >&2 "INFO: ENABLE_FULL_DEBUG_SYMBOLS=$(ENABLE_FULL_DEBUG_SYMBOLS)")
+  # since objcopy is optional, we set ZIP_DEBUGINFO_FILES later
+
+  ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1)
+    # Default OBJCOPY comes from GNU Binutils on Linux:
+    DEF_OBJCOPY=/usr/bin/objcopy
+    ifdef CROSS_COMPILE_ARCH
+      # don't try to generate .debuginfo files when cross compiling
+      _JUNK_ := $(shell \
+        echo >&2 "INFO: cross compiling for ARCH $(CROSS_COMPILE_ARCH)," \
+          "skipping .debuginfo generation.")
+      OBJCOPY=
+    else
+      OBJCOPY=$(shell test -x $(DEF_OBJCOPY) && echo $(DEF_OBJCOPY))
+      ifneq ($(ALT_OBJCOPY),)
+        _JUNK_ := $(shell echo >&2 "INFO: ALT_OBJCOPY=$(ALT_OBJCOPY)")
+        OBJCOPY=$(shell test -x $(ALT_OBJCOPY) && echo $(ALT_OBJCOPY))
+      endif
+    endif
+  else
     OBJCOPY=
-  else
-    OBJCOPY=$(shell test -x $(DEF_OBJCOPY) && echo $(DEF_OBJCOPY))
-    ifneq ($(ALT_OBJCOPY),)
-      _JUNK_ := $(shell echo >&2 "INFO: ALT_OBJCOPY=$(ALT_OBJCOPY)")
-      # disable .debuginfo support by setting ALT_OBJCOPY to a non-existent path
-      OBJCOPY=$(shell test -x $(ALT_OBJCOPY) && echo $(ALT_OBJCOPY))
-    endif
   endif
-  
+
   ifeq ($(OBJCOPY),)
     _JUNK_ := $(shell \
       echo >&2 "INFO: no objcopy cmd found so cannot create .debuginfo files.")
+    ENABLE_FULL_DEBUG_SYMBOLS=0
+    _JUNK_ := $(shell \
+      echo >&2 "INFO: ENABLE_FULL_DEBUG_SYMBOLS=$(ENABLE_FULL_DEBUG_SYMBOLS)")
   else
     _JUNK_ := $(shell \
       echo >&2 "INFO: $(OBJCOPY) cmd found so will create .debuginfo files.")
-  
+
     # Library stripping policies for .debuginfo configs:
     #   all_strip - strips everything from the library
     #   min_strip - strips most stuff from the library; leaves minimum symbols
@@ -175,15 +213,17 @@
     # Oracle security policy requires "all_strip". A waiver was granted on
     # 2011.09.01 that permits using "min_strip" in the Java JDK and Java JRE.
     #
-    DEF_STRIP_POLICY="min_strip"
-    ifeq ($(ALT_STRIP_POLICY),)
-      STRIP_POLICY=$(DEF_STRIP_POLICY)
-    else
-      STRIP_POLICY=$(ALT_STRIP_POLICY)
-    endif
-  
+    # Currently, STRIP_POLICY is only used when Full Debug Symbols is enabled.
+    #
+    STRIP_POLICY ?= min_strip
+
     _JUNK_ := $(shell \
       echo >&2 "INFO: STRIP_POLICY=$(STRIP_POLICY)")
+
+    ZIP_DEBUGINFO_FILES ?= 1
+
+    _JUNK_ := $(shell \
+      echo >&2 "INFO: ZIP_DEBUGINFO_FILES=$(ZIP_DEBUGINFO_FILES)")
   endif
 endif
 
@@ -199,8 +239,12 @@
 
 # client and server subdirectories have symbolic links to ../libjsig.so
 EXPORT_LIST += $(EXPORT_JRE_LIB_ARCH_DIR)/libjsig.$(LIBRARY_SUFFIX)
-ifneq ($(OBJCOPY),)
-  EXPORT_LIST += $(EXPORT_JRE_LIB_ARCH_DIR)/libjsig.debuginfo
+ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1)
+  ifeq ($(ZIP_DEBUGINFO_FILES),1)
+    EXPORT_LIST += $(EXPORT_JRE_LIB_ARCH_DIR)/libjsig.diz
+  else
+    EXPORT_LIST += $(EXPORT_JRE_LIB_ARCH_DIR)/libjsig.debuginfo
+  endif
 endif
 EXPORT_SERVER_DIR = $(EXPORT_JRE_LIB_ARCH_DIR)/server
 EXPORT_CLIENT_DIR = $(EXPORT_JRE_LIB_ARCH_DIR)/client
@@ -210,16 +254,24 @@
 ifeq ($(findstring true, $(JVM_VARIANT_SERVER) $(JVM_VARIANT_ZERO) $(JVM_VARIANT_ZEROSHARK)), true)
   EXPORT_LIST += $(EXPORT_SERVER_DIR)/Xusage.txt
   EXPORT_LIST += $(EXPORT_SERVER_DIR)/libjvm.$(LIBRARY_SUFFIX)
-  ifneq ($(OBJCOPY),)
-    EXPORT_LIST += $(EXPORT_SERVER_DIR)/libjvm.debuginfo
+  ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1)
+    ifeq ($(ZIP_DEBUGINFO_FILES),1)
+      EXPORT_LIST += $(EXPORT_SERVER_DIR)/libjvm.diz
+    else
+      EXPORT_LIST += $(EXPORT_SERVER_DIR)/libjvm.debuginfo
+    endif
   endif
 endif
 
 ifeq ($(JVM_VARIANT_CLIENT),true)
   EXPORT_LIST += $(EXPORT_CLIENT_DIR)/Xusage.txt
   EXPORT_LIST += $(EXPORT_CLIENT_DIR)/libjvm.$(LIBRARY_SUFFIX)
-  ifneq ($(OBJCOPY),)
-    EXPORT_LIST += $(EXPORT_CLIENT_DIR)/libjvm.debuginfo
+  ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1)
+    ifeq ($(ZIP_DEBUGINFO_FILES),1)
+      EXPORT_LIST += $(EXPORT_CLIENT_DIR)/libjvm.diz
+    else
+      EXPORT_LIST += $(EXPORT_CLIENT_DIR)/libjvm.debuginfo
+    endif
   endif 
 endif
 
@@ -229,9 +281,14 @@
                         $(EXPORT_LIB_DIR)/sa-jdi.jar 
 ADD_SA_BINARIES/sparc = $(EXPORT_JRE_LIB_ARCH_DIR)/libsaproc.$(LIBRARY_SUFFIX) \
                         $(EXPORT_LIB_DIR)/sa-jdi.jar 
-ifneq ($(OBJCOPY),)
-  ADD_SA_BINARIES/x86   += $(EXPORT_JRE_LIB_ARCH_DIR)/libsaproc.debuginfo
-  ADD_SA_BINARIES/sparc += $(EXPORT_JRE_LIB_ARCH_DIR)/libsaproc.debuginfo
+ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1)
+  ifeq ($(ZIP_DEBUGINFO_FILES),1)
+    ADD_SA_BINARIES/x86   += $(EXPORT_JRE_LIB_ARCH_DIR)/libsaproc.diz
+    ADD_SA_BINARIES/sparc += $(EXPORT_JRE_LIB_ARCH_DIR)/libsaproc.diz
+  else
+    ADD_SA_BINARIES/x86   += $(EXPORT_JRE_LIB_ARCH_DIR)/libsaproc.debuginfo
+    ADD_SA_BINARIES/sparc += $(EXPORT_JRE_LIB_ARCH_DIR)/libsaproc.debuginfo
+  endif
 endif
 ADD_SA_BINARIES/ppc   = 
 ADD_SA_BINARIES/ia64  = 
--- a/hotspot/make/linux/makefiles/gcc.make	Wed Jul 05 18:09:43 2017 +0200
+++ b/hotspot/make/linux/makefiles/gcc.make	Wed Jul 05 18:10:27 2017 +0200
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
@@ -230,7 +230,7 @@
 DEBUG_CFLAGS += -gstabs
 endif
 
-ifneq ($(OBJCOPY),)
+ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1)
   FASTDEBUG_CFLAGS/ia64  = -g
   FASTDEBUG_CFLAGS/amd64 = -g
   FASTDEBUG_CFLAGS/arm   = -g
--- a/hotspot/make/linux/makefiles/jsig.make	Wed Jul 05 18:09:43 2017 +0200
+++ b/hotspot/make/linux/makefiles/jsig.make	Wed Jul 05 18:10:27 2017 +0200
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
@@ -32,12 +32,15 @@
 LIBJSIG_G = lib$(JSIG_G).so
 
 LIBJSIG_DEBUGINFO   = lib$(JSIG).debuginfo
+LIBJSIG_DIZ         = lib$(JSIG).diz
 LIBJSIG_G_DEBUGINFO = lib$(JSIG_G).debuginfo
+LIBJSIG_G_DIZ       = lib$(JSIG_G).diz
 
 JSIGSRCDIR = $(GAMMADIR)/src/os/$(Platform_os_family)/vm
 
 DEST_JSIG           = $(JDK_LIBDIR)/$(LIBJSIG)
 DEST_JSIG_DEBUGINFO = $(JDK_LIBDIR)/$(LIBJSIG_DEBUGINFO)
+DEST_JSIG_DIZ       = $(JDK_LIBDIR)/$(LIBJSIG_DIZ)
 
 LIBJSIG_MAPFILE = $(MAKEFILES_DIR)/mapfile-vers-jsig
 
@@ -58,7 +61,7 @@
 	$(QUIETLY) $(CC) $(SYMFLAG) $(ARCHFLAG) $(SHARED_FLAG) $(PICFLAG) \
                          $(LFLAGS_JSIG) $(JSIG_DEBUG_CFLAGS) -o $@ $< -ldl
 	$(QUIETLY) [ -f $(LIBJSIG_G) ] || { ln -s $@ $(LIBJSIG_G); }
-ifneq ($(OBJCOPY),)
+ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1)
 	$(QUIETLY) $(OBJCOPY) --only-keep-debug $@ $(LIBJSIG_DEBUGINFO)
 	$(QUIETLY) $(OBJCOPY) --add-gnu-debuglink=$(LIBJSIG_DEBUGINFO) $@
   ifeq ($(STRIP_POLICY),all_strip)
@@ -70,12 +73,19 @@
     endif
   endif
 	[ -f $(LIBJSIG_G_DEBUGINFO) ] || { ln -s $(LIBJSIG_DEBUGINFO) $(LIBJSIG_G_DEBUGINFO); }
+  ifeq ($(ZIP_DEBUGINFO_FILES),1)
+	$(ZIPEXE) -q -y $(LIBJSIG_DIZ) $(LIBJSIG_DEBUGINFO) $(LIBJSIG_G_DEBUGINFO)
+	$(RM) $(LIBJSIG_DEBUGINFO) $(LIBJSIG_G_DEBUGINFO)
+	[ -f $(LIBJSIG_G_DIZ) ] || { ln -s $(LIBJSIG_DIZ) $(LIBJSIG_G_DIZ); }
+  endif
 endif
 
 install_jsig: $(LIBJSIG)
 	@echo "Copying $(LIBJSIG) to $(DEST_JSIG)"
 	$(QUIETLY) test -f $(LIBJSIG_DEBUGINFO) && \
 	    cp -f $(LIBJSIG_DEBUGINFO) $(DEST_JSIG_DEBUGINFO)
+	$(QUIETLY) test -f $(LIBJSIG_DIZ) && \
+	    cp -f $(LIBJSIG_DIZ) $(DEST_JSIG_DIZ)
 	$(QUIETLY) cp -f $(LIBJSIG) $(DEST_JSIG) && echo "Done"
 
 .PHONY: install_jsig
--- a/hotspot/make/linux/makefiles/saproc.make	Wed Jul 05 18:09:43 2017 +0200
+++ b/hotspot/make/linux/makefiles/saproc.make	Wed Jul 05 18:10:27 2017 +0200
@@ -33,7 +33,9 @@
 LIBSAPROC_G = lib$(SAPROC_G).so
 
 LIBSAPROC_DEBUGINFO   = lib$(SAPROC).debuginfo
+LIBSAPROC_DIZ         = lib$(SAPROC).diz
 LIBSAPROC_G_DEBUGINFO = lib$(SAPROC_G).debuginfo
+LIBSAPROC_G_DIZ       = lib$(SAPROC_G).diz
 
 AGENT_DIR = $(GAMMADIR)/agent
 
@@ -50,6 +52,7 @@
 
 DEST_SAPROC           = $(JDK_LIBDIR)/$(LIBSAPROC)
 DEST_SAPROC_DEBUGINFO = $(JDK_LIBDIR)/$(LIBSAPROC_DEBUGINFO)
+DEST_SAPROC_DIZ       = $(JDK_LIBDIR)/$(LIBSAPROC_DIZ)
 
 # DEBUG_BINARIES overrides everything, use full -g debug information
 ifeq ($(DEBUG_BINARIES), true)
@@ -87,7 +90,7 @@
 	           -o $@                                                \
 	           -lthread_db
 	$(QUIETLY) [ -f $(LIBSAPROC_G) ] || { ln -s $@ $(LIBSAPROC_G); }
-ifneq ($(OBJCOPY),)
+ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1)
 	$(QUIETLY) $(OBJCOPY) --only-keep-debug $@ $(LIBSAPROC_DEBUGINFO)
 	$(QUIETLY) $(OBJCOPY) --add-gnu-debuglink=$(LIBSAPROC_DEBUGINFO) $@
   ifeq ($(STRIP_POLICY),all_strip)
@@ -99,6 +102,11 @@
     endif
   endif
 	[ -f $(LIBSAPROC_G_DEBUGINFO) ] || { ln -s $(LIBSAPROC_DEBUGINFO) $(LIBSAPROC_G_DEBUGINFO); }
+  ifeq ($(ZIP_DEBUGINFO_FILES),1)
+	$(ZIPEXE) -q -y $(LIBSAPROC_DIZ) $(LIBSAPROC_DEBUGINFO) $(LIBSAPROC_G_DEBUGINFO)
+	$(RM) $(LIBSAPROC_DEBUGINFO) $(LIBSAPROC_G_DEBUGINFO)
+	[ -f $(LIBSAPROC_G_DIZ) ] || { ln -s $(LIBSAPROC_DIZ) $(LIBSAPROC_G_DIZ); }
+  endif
 endif
 
 install_saproc: $(BUILDLIBSAPROC)
@@ -106,6 +114,8 @@
 	  echo "Copying $(LIBSAPROC) to $(DEST_SAPROC)";     \
 	  test -f $(LIBSAPROC_DEBUGINFO) &&                  \
 	    cp -f $(LIBSAPROC_DEBUGINFO) $(DEST_SAPROC_DEBUGINFO); \
+	  test -f $(LIBSAPROC_DIZ) &&                  \
+	    cp -f $(LIBSAPROC_DIZ) $(DEST_SAPROC_DIZ); \
 	  cp -f $(LIBSAPROC) $(DEST_SAPROC) && echo "Done";  \
 	fi
 
--- a/hotspot/make/linux/makefiles/vm.make	Wed Jul 05 18:09:43 2017 +0200
+++ b/hotspot/make/linux/makefiles/vm.make	Wed Jul 05 18:10:27 2017 +0200
@@ -61,7 +61,7 @@
 INCLUDES += $(PRECOMPILED_HEADER_DIR:%=-I%) $(Src_Dirs_I:%=-I%)
 
 # SYMFLAG is used by {jsig,saproc}.make
-ifneq ($(OBJCOPY),)
+ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1)
   # always build with debug info when we can create .debuginfo files
   SYMFLAG = -g
 else
@@ -139,7 +139,9 @@
 LIBJVM_G = lib$(JVM)$(G_SUFFIX).so
 
 LIBJVM_DEBUGINFO   = lib$(JVM).debuginfo
+LIBJVM_DIZ         = lib$(JVM).diz
 LIBJVM_G_DEBUGINFO = lib$(JVM)$(G_SUFFIX).debuginfo
+LIBJVM_G_DIZ       = lib$(JVM)$(G_SUFFIX).diz
 
 SPECIAL_PATHS:=adlc c1 gc_implementation opto shark libadt
 
@@ -331,7 +333,7 @@
             fi 								\
 	}
 ifeq ($(CROSS_COMPILE_ARCH),)
-  ifneq ($(OBJCOPY),)
+  ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1)
 	$(QUIETLY) $(OBJCOPY) --only-keep-debug $@ $(LIBJVM_DEBUGINFO)
 	$(QUIETLY) $(OBJCOPY) --add-gnu-debuglink=$(LIBJVM_DEBUGINFO) $@
     ifeq ($(STRIP_POLICY),all_strip)
@@ -343,17 +345,25 @@
       endif
     endif
 	$(QUIETLY) [ -f $(LIBJVM_G_DEBUGINFO) ] || ln -s $(LIBJVM_DEBUGINFO) $(LIBJVM_G_DEBUGINFO)
+    ifeq ($(ZIP_DEBUGINFO_FILES),1)
+	$(ZIPEXE) -q -y $(LIBJVM_DIZ) $(LIBJVM_DEBUGINFO) $(LIBJVM_G_DEBUGINFO)
+	$(RM) $(LIBJVM_DEBUGINFO) $(LIBJVM_G_DEBUGINFO)
+	[ -f $(LIBJVM_G_DIZ) ] || { ln -s $(LIBJVM_DIZ) $(LIBJVM_G_DIZ); }
+    endif
   endif
 endif
 
 DEST_SUBDIR        = $(JDK_LIBDIR)/$(VM_SUBDIR)
 DEST_JVM           = $(DEST_SUBDIR)/$(LIBJVM)
 DEST_JVM_DEBUGINFO = $(DEST_SUBDIR)/$(LIBJVM_DEBUGINFO)
+DEST_JVM_DIZ       = $(DEST_SUBDIR)/$(LIBJVM_DIZ)
 
 install_jvm: $(LIBJVM)
 	@echo "Copying $(LIBJVM) to $(DEST_JVM)"
 	$(QUIETLY) test -f $(LIBJVM_DEBUGINFO) && \
 	    cp -f $(LIBJVM_DEBUGINFO) $(DEST_JVM_DEBUGINFO)
+	$(QUIETLY) test -f $(LIBJVM_DIZ) && \
+	    cp -f $(LIBJVM_DIZ) $(DEST_JVM_DIZ)
 	$(QUIETLY) cp -f $(LIBJVM) $(DEST_JVM) && echo "Done"
 
 #----------------------------------------------------------------------
--- a/hotspot/make/solaris/Makefile	Wed Jul 05 18:09:43 2017 +0200
+++ b/hotspot/make/solaris/Makefile	Wed Jul 05 18:10:27 2017 +0200
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
@@ -168,7 +168,7 @@
 BUILDTREE_MAKE    = $(GAMMADIR)/make/$(OSNAME)/makefiles/buildtree.make
 BUILDTREE_VARS    = GAMMADIR=$(GAMMADIR) OS_FAMILY=$(OSNAME) ARCH=$(SRCARCH) BUILDARCH=$(BUILDARCH) LIBARCH=$(LIBARCH)
 BUILDTREE_VARS   += HOTSPOT_RELEASE_VERSION=$(HOTSPOT_RELEASE_VERSION) HOTSPOT_BUILD_VERSION=$(HOTSPOT_BUILD_VERSION) JRE_RELEASE_VERSION=$(JRE_RELEASE_VERSION)
-BUILDTREE_VARS   += OBJCOPY=$(OBJCOPY) STRIP_POLICY=$(STRIP_POLICY)
+BUILDTREE_VARS   += ENABLE_FULL_DEBUG_SYMBOLS=$(ENABLE_FULL_DEBUG_SYMBOLS) OBJCOPY=$(OBJCOPY) STRIP_POLICY=$(STRIP_POLICY) ZIP_DEBUGINFO_FILES=$(ZIP_DEBUGINFO_FILES) ZIPEXE=$(ZIPEXE)
 
 BUILDTREE         = $(MAKE) -f $(BUILDTREE_MAKE) $(BUILDTREE_VARS)
 
@@ -278,9 +278,11 @@
 
 # Doc target.  This is the same for all build options.
 #     Hence create a docs directory beside ...$(ARCH)_[...]
+# We specify 'BUILD_FLAVOR=product' so that the proper
+# ENABLE_FULL_DEBUG_SYMBOLS value is used.
 docs: checks
 	$(QUIETLY) mkdir -p $(SUBDIR_DOCS)
-	$(MAKE) -f $(GAMMADIR)/make/$(OSNAME)/makefiles/jvmti.make $(MFLAGS) $(BUILDTREE_VARS) JvmtiOutDir=$(SUBDIR_DOCS) jvmtidocs
+	$(MAKE) -f $(GAMMADIR)/make/$(OSNAME)/makefiles/jvmti.make $(MFLAGS) $(BUILDTREE_VARS) JvmtiOutDir=$(SUBDIR_DOCS) BUILD_FLAVOR=product jvmtidocs
 
 # Synonyms for win32-like targets.
 compiler2:  jvmg product
--- a/hotspot/make/solaris/makefiles/buildtree.make	Wed Jul 05 18:09:43 2017 +0200
+++ b/hotspot/make/solaris/makefiles/buildtree.make	Wed Jul 05 18:10:27 2017 +0200
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
@@ -229,10 +229,16 @@
 	echo "$(call gamma-path,commonsrc,os/posix/vm)"; \
 	[ -n "$(CFLAGS_BROWSE)" ] && \
 	    echo && echo "CFLAGS_BROWSE = $(CFLAGS_BROWSE)"; \
+	[ -n "$(ENABLE_FULL_DEBUG_SYMBOLS)" ] && \
+	    echo && echo "ENABLE_FULL_DEBUG_SYMBOLS = $(ENABLE_FULL_DEBUG_SYMBOLS)"; \
 	[ -n "$(OBJCOPY)" ] && \
 	    echo && echo "OBJCOPY = $(OBJCOPY)"; \
 	[ -n "$(STRIP_POLICY)" ] && \
 	    echo && echo "STRIP_POLICY = $(STRIP_POLICY)"; \
+	[ -n "$(ZIP_DEBUGINFO_FILES)" ] && \
+	    echo && echo "ZIP_DEBUGINFO_FILES = $(ZIP_DEBUGINFO_FILES)"; \
+	[ -n "$(ZIPEXE)" ] && \
+	    echo && echo "ZIPEXE = $(ZIPEXE)"; \
 	[ -n "$(HOTSPOT_EXTRA_SYSDEFS)" ] && \
 	    echo && \
 	    echo "HOTSPOT_EXTRA_SYSDEFS\$$(HOTSPOT_EXTRA_SYSDEFS) = $(HOTSPOT_EXTRA_SYSDEFS)" && \
--- a/hotspot/make/solaris/makefiles/defs.make	Wed Jul 05 18:09:43 2017 +0200
+++ b/hotspot/make/solaris/makefiles/defs.make	Wed Jul 05 18:10:27 2017 +0200
@@ -86,45 +86,83 @@
 endif
 
 ifeq ($(JDK6_OR_EARLIER),0)
-  # Full Debug Symbols is supported on JDK7 or newer
+  # Full Debug Symbols is supported on JDK7 or newer.
+  # The Full Debug Symbols (FDS) default for BUILD_FLAVOR == product
+  # builds is enabled with debug info files ZIP'ed to save space. For
+  # BUILD_FLAVOR != product builds, FDS is always enabled, after all a
+  # debug build without debug info isn't very useful.
+  # The ZIP_DEBUGINFO_FILES option only has meaning when FDS is enabled.
+  #
+  # If you invoke a build with FULL_DEBUG_SYMBOLS=0, then FDS will be
+  # disabled for a BUILD_FLAVOR == product build.
+  #
+  # Note: Use of a different variable name for the FDS override option
+  # versus the FDS enabled check is intentional (FULL_DEBUG_SYMBOLS
+  # versus ENABLE_FULL_DEBUG_SYMBOLS). For auto build systems that pass
+  # in options via environment variables, use of distinct variables
+  # prevents strange behaviours. For example, in a BUILD_FLAVOR !=
+  # product build, the FULL_DEBUG_SYMBOLS environment variable will be
+  # 0, but the ENABLE_FULL_DEBUG_SYMBOLS make variable will be 1. If
+  # the same variable name is used, then different values can be picked
+  # up by different parts of the build. Just to be clear, we only need
+  # two variable names because the incoming option value can be
+  # overridden in some situations, e.g., a BUILD_FLAVOR != product
+  # build.
 
-ifdef ENABLE_FULL_DEBUG_SYMBOLS
-  # Only check for Full Debug Symbols support on Solaris if it is
-  # specifically enabled. Hopefully, it can be enabled by default
-  # once the .debuginfo size issues are worked out.
-  
-  # Default OBJCOPY comes from the SUNWbinutils package:
-  DEF_OBJCOPY=/usr/sfw/bin/gobjcopy
-  ifeq ($(VM_PLATFORM),solaris_amd64)
-    # On Solaris AMD64/X64, gobjcopy is not happy and fails:
-    #
-    # usr/sfw/bin/gobjcopy --add-gnu-debuglink=<lib>.debuginfo <lib>.so
-    # BFD: stKPaiop: Not enough room for program headers, try linking with -N
-    # /usr/sfw/bin/gobjcopy: stKPaiop: Bad value
-    # BFD: stKPaiop: Not enough room for program headers, try linking with -N
-    # /usr/sfw/bin/gobjcopy: libsaproc.debuginfo: Bad value
-    # BFD: stKPaiop: Not enough room for program headers, try linking with -N
-    # /usr/sfw/bin/gobjcopy: stKPaiop: Bad value
-    _JUNK_ := $(shell \
-      echo >&2 "INFO: $(DEF_OBJCOPY) is not working on Solaris AMD64/X64")
+  # Disable FULL_DEBUG_SYMBOLS by default because dtrace tests are
+  # failing in nightly when the debug info files are ZIP'ed. On
+  # Solaris debug info files need to be ZIP'ed to reduce the impact
+  # on disk space footprint.
+  FULL_DEBUG_SYMBOLS ?= 0
+  ifeq ($(BUILD_FLAVOR), product)
+    # FULL_DEBUG_SYMBOLS ?= 1
+    ENABLE_FULL_DEBUG_SYMBOLS = $(FULL_DEBUG_SYMBOLS)
+  else
+    # debug variants always get Full Debug Symbols (if available)
+    # ENABLE_FULL_DEBUG_SYMBOLS = 1
+    ENABLE_FULL_DEBUG_SYMBOLS = $(FULL_DEBUG_SYMBOLS)
+  endif
+  _JUNK_ := $(shell \
+    echo >&2 "INFO: ENABLE_FULL_DEBUG_SYMBOLS=$(ENABLE_FULL_DEBUG_SYMBOLS)")
+  # since objcopy is optional, we set ZIP_DEBUGINFO_FILES later
+
+  ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1)
+    # Default OBJCOPY comes from the SUNWbinutils package:
+    DEF_OBJCOPY=/usr/sfw/bin/gobjcopy
+    ifeq ($(VM_PLATFORM),solaris_amd64)
+      # On Solaris AMD64/X64, gobjcopy is not happy and fails:
+      #
+      # usr/sfw/bin/gobjcopy --add-gnu-debuglink=<lib>.debuginfo <lib>.so
+      # BFD: stKPaiop: Not enough room for program headers, try linking with -N
+      # /usr/sfw/bin/gobjcopy: stKPaiop: Bad value
+      # BFD: stKPaiop: Not enough room for program headers, try linking with -N
+      # /usr/sfw/bin/gobjcopy: libsaproc.debuginfo: Bad value
+      # BFD: stKPaiop: Not enough room for program headers, try linking with -N
+      # /usr/sfw/bin/gobjcopy: stKPaiop: Bad value
+      _JUNK_ := $(shell \
+        echo >&2 "INFO: $(DEF_OBJCOPY) is not working on Solaris AMD64/X64")
+      OBJCOPY=
+    else
+      OBJCOPY=$(shell test -x $(DEF_OBJCOPY) && echo $(DEF_OBJCOPY))
+      ifneq ($(ALT_OBJCOPY),)
+        _JUNK_ := $(shell echo >&2 "INFO: ALT_OBJCOPY=$(ALT_OBJCOPY)")
+        OBJCOPY=$(shell test -x $(ALT_OBJCOPY) && echo $(ALT_OBJCOPY))
+      endif
+    endif
+  else
     OBJCOPY=
-  else
-    OBJCOPY=$(shell test -x $(DEF_OBJCOPY) && echo $(DEF_OBJCOPY))
-    ifneq ($(ALT_OBJCOPY),)
-      _JUNK_ := $(shell echo >&2 "INFO: ALT_OBJCOPY=$(ALT_OBJCOPY)")
-      # disable .debuginfo support by setting ALT_OBJCOPY to a non-existent path
-      OBJCOPY=$(shell test -x $(ALT_OBJCOPY) && echo $(ALT_OBJCOPY))
-    endif
   endif
-endif
-  
+
   ifeq ($(OBJCOPY),)
     _JUNK_ := $(shell \
       echo >&2 "INFO: no objcopy cmd found so cannot create .debuginfo files.")
+    ENABLE_FULL_DEBUG_SYMBOLS=0
+    _JUNK_ := $(shell \
+      echo >&2 "INFO: ENABLE_FULL_DEBUG_SYMBOLS=$(ENABLE_FULL_DEBUG_SYMBOLS)")
   else
     _JUNK_ := $(shell \
       echo >&2 "INFO: $(OBJCOPY) cmd found so will create .debuginfo files.")
-  
+
     # Library stripping policies for .debuginfo configs:
     #   all_strip - strips everything from the library
     #   min_strip - strips most stuff from the library; leaves minimum symbols
@@ -133,14 +171,19 @@
     # Oracle security policy requires "all_strip". A waiver was granted on
     # 2011.09.01 that permits using "min_strip" in the Java JDK and Java JRE.
     #
-    DEF_STRIP_POLICY="min_strip"
-    ifeq ($(ALT_STRIP_POLICY),)
-      STRIP_POLICY=$(DEF_STRIP_POLICY)
-    else
-      STRIP_POLICY=$(ALT_STRIP_POLICY)
-    endif
+    # Currently, STRIP_POLICY is only used when Full Debug Symbols is enabled.
+    #
+    STRIP_POLICY ?= min_strip
+
     _JUNK_ := $(shell \
       echo >&2 "INFO: STRIP_POLICY=$(STRIP_POLICY)")
+
+    # Disable ZIP_DEBUGINFO_FILES by default because dtrace tests are
+    # failing in nightly when the debug info files are ZIP'ed.
+    ZIP_DEBUGINFO_FILES ?= 0
+
+    _JUNK_ := $(shell \
+      echo >&2 "INFO: ZIP_DEBUGINFO_FILES=$(ZIP_DEBUGINFO_FILES)")
   endif
 endif
 
@@ -156,8 +199,12 @@
 
 # client and server subdirectories have symbolic links to ../libjsig.$(LIBRARY_SUFFIX)
 EXPORT_LIST += $(EXPORT_JRE_LIB_ARCH_DIR)/libjsig.$(LIBRARY_SUFFIX)
-ifneq ($(OBJCOPY),)
-  EXPORT_LIST += $(EXPORT_JRE_LIB_ARCH_DIR)/libjsig.debuginfo
+ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1)
+  ifeq ($(ZIP_DEBUGINFO_FILES),1)
+    EXPORT_LIST += $(EXPORT_JRE_LIB_ARCH_DIR)/libjsig.diz
+  else
+    EXPORT_LIST += $(EXPORT_JRE_LIB_ARCH_DIR)/libjsig.debuginfo
+  endif
 endif
 
 EXPORT_LIST += $(EXPORT_JRE_LIB_DIR)/wb.jar
@@ -174,10 +221,16 @@
     EXPORT_LIST += $(EXPORT_SERVER_DIR)/64/libjvm_db.$(LIBRARY_SUFFIX)
     EXPORT_LIST += $(EXPORT_SERVER_DIR)/64/libjvm_dtrace.$(LIBRARY_SUFFIX)
   endif
-  ifneq ($(OBJCOPY),)
-    EXPORT_LIST += $(EXPORT_SERVER_DIR)/libjvm.debuginfo
-    EXPORT_LIST += $(EXPORT_SERVER_DIR)/libjvm_db.debuginfo
-    EXPORT_LIST += $(EXPORT_SERVER_DIR)/libjvm_dtrace.debuginfo
+  ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1)
+    ifeq ($(ZIP_DEBUGINFO_FILES),1)
+      EXPORT_LIST += $(EXPORT_SERVER_DIR)/libjvm.diz
+      EXPORT_LIST += $(EXPORT_SERVER_DIR)/libjvm_db.diz
+      EXPORT_LIST += $(EXPORT_SERVER_DIR)/libjvm_dtrace.diz
+    else
+      EXPORT_LIST += $(EXPORT_SERVER_DIR)/libjvm.debuginfo
+      EXPORT_LIST += $(EXPORT_SERVER_DIR)/libjvm_db.debuginfo
+      EXPORT_LIST += $(EXPORT_SERVER_DIR)/libjvm_dtrace.debuginfo
+    endif
   endif
 endif
 ifeq ($(JVM_VARIANT_CLIENT),true)
@@ -189,19 +242,33 @@
     EXPORT_LIST += $(EXPORT_CLIENT_DIR)/64/libjvm_db.$(LIBRARY_SUFFIX)
     EXPORT_LIST += $(EXPORT_CLIENT_DIR)/64/libjvm_dtrace.$(LIBRARY_SUFFIX)
   endif
-  ifneq ($(OBJCOPY),)
-    EXPORT_LIST += $(EXPORT_CLIENT_DIR)/libjvm.debuginfo
-    EXPORT_LIST += $(EXPORT_CLIENT_DIR)/libjvm_db.debuginfo
-    EXPORT_LIST += $(EXPORT_CLIENT_DIR)/libjvm_dtrace.debuginfo
-    ifeq ($(ARCH_DATA_MODEL),32)
-      EXPORT_LIST += $(EXPORT_CLIENT_DIR)/64/libjvm_db.debuginfo
-      EXPORT_LIST += $(EXPORT_CLIENT_DIR)/64/libjvm_dtrace.debuginfo
+  ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1)
+    ifeq ($(ZIP_DEBUGINFO_FILES),1)
+      EXPORT_LIST += $(EXPORT_CLIENT_DIR)/libjvm.diz
+      EXPORT_LIST += $(EXPORT_CLIENT_DIR)/libjvm_db.diz
+      EXPORT_LIST += $(EXPORT_CLIENT_DIR)/libjvm_dtrace.diz
+      ifeq ($(ARCH_DATA_MODEL),32)
+        EXPORT_LIST += $(EXPORT_CLIENT_DIR)/64/libjvm_db.diz
+        EXPORT_LIST += $(EXPORT_CLIENT_DIR)/64/libjvm_dtrace.diz
+      endif
+    else
+      EXPORT_LIST += $(EXPORT_CLIENT_DIR)/libjvm.debuginfo
+      EXPORT_LIST += $(EXPORT_CLIENT_DIR)/libjvm_db.debuginfo
+      EXPORT_LIST += $(EXPORT_CLIENT_DIR)/libjvm_dtrace.debuginfo
+      ifeq ($(ARCH_DATA_MODEL),32)
+        EXPORT_LIST += $(EXPORT_CLIENT_DIR)/64/libjvm_db.debuginfo
+        EXPORT_LIST += $(EXPORT_CLIENT_DIR)/64/libjvm_dtrace.debuginfo
+      endif
     endif
   endif
 endif
 
 EXPORT_LIST += $(EXPORT_JRE_LIB_ARCH_DIR)/libsaproc.$(LIBRARY_SUFFIX)
-ifneq ($(OBJCOPY),)
-  EXPORT_LIST += $(EXPORT_JRE_LIB_ARCH_DIR)/libsaproc.debuginfo
+ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1)
+  ifeq ($(ZIP_DEBUGINFO_FILES),1)
+    EXPORT_LIST += $(EXPORT_JRE_LIB_ARCH_DIR)/libsaproc.diz
+  else
+    EXPORT_LIST += $(EXPORT_JRE_LIB_ARCH_DIR)/libsaproc.debuginfo
+  endif
 endif
 EXPORT_LIST += $(EXPORT_LIB_DIR)/sa-jdi.jar 
--- a/hotspot/make/solaris/makefiles/dtrace.make	Wed Jul 05 18:09:43 2017 +0200
+++ b/hotspot/make/solaris/makefiles/dtrace.make	Wed Jul 05 18:10:27 2017 +0200
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
@@ -41,15 +41,19 @@
 LIBJVM_DB = libjvm_db.so
 LIBJVM_DB_G = libjvm$(G_SUFFIX)_db.so
 
-LIBJVM_DB_DEBUGINFO = libjvm_db.debuginfo
+LIBJVM_DB_DEBUGINFO   = libjvm_db.debuginfo
+LIBJVM_DB_DIZ         = libjvm_db.diz
 LIBJVM_DB_G_DEBUGINFO = libjvm$(G_SUFFIX)_db.debuginfo
+LIBJVM_DB_G_DIZ       = libjvm$(G_SUFFIX)_db.diz
 
 JVM_DTRACE = jvm_dtrace
 LIBJVM_DTRACE = libjvm_dtrace.so
 LIBJVM_DTRACE_G = libjvm$(G_SUFFIX)_dtrace.so
 
-LIBJVM_DTRACE_DEBUGINFO = libjvm_dtrace.debuginfo
+LIBJVM_DTRACE_DEBUGINFO   = libjvm_dtrace.debuginfo
+LIBJVM_DTRACE_DIZ         = libjvm_dtrace.diz
 LIBJVM_DTRACE_G_DEBUGINFO = libjvm$(G_SUFFIX)_dtrace.debuginfo
+LIBJVM_DTRACE_G_DIZ       = libjvm$(G_SUFFIX)_dtrace.diz
 
 JVMOFFS = JvmOffsets
 JVMOFFS.o = $(JVMOFFS).o
@@ -95,10 +99,14 @@
 XLIBJVM_DTRACE = 64/$(LIBJVM_DTRACE)
 XLIBJVM_DTRACE_G = 64/$(LIBJVM_DTRACE_G)
 
-XLIBJVM_DB_DEBUGINFO = 64/$(LIBJVM_DB_DEBUGINFO)
-XLIBJVM_DB_G_DEBUGINFO = 64/$(LIBJVM_DB_G_DEBUGINFO)
-XLIBJVM_DTRACE_DEBUGINFO = 64/$(LIBJVM_DTRACE_DEBUGINFO)
+XLIBJVM_DB_DEBUGINFO       = 64/$(LIBJVM_DB_DEBUGINFO)
+XLIBJVM_DB_DIZ             = 64/$(LIBJVM_DB_DIZ)
+XLIBJVM_DB_G_DEBUGINFO     = 64/$(LIBJVM_DB_G_DEBUGINFO)
+XLIBJVM_DB_G_DIZ           = 64/$(LIBJVM_DB_G_DIZ)
+XLIBJVM_DTRACE_DEBUGINFO   = 64/$(LIBJVM_DTRACE_DEBUGINFO)
+XLIBJVM_DTRACE_DIZ         = 64/$(LIBJVM_DTRACE_DIZ)
 XLIBJVM_DTRACE_G_DEBUGINFO = 64/$(LIBJVM_DTRACE_G_DEBUGINFO)
+XLIBJVM_DTRACE_G_DIZ       = 64/$(LIBJVM_DTRACE_G_DIZ)
 
 $(XLIBJVM_DB): $(DTRACE_SRCDIR)/$(JVM_DB).c $(JVMOFFS).h $(LIBJVM_DB_MAPFILE)
 	@echo Making $@
@@ -106,7 +114,7 @@
 	$(CC) $(SYMFLAG) $(ARCHFLAG/$(ISA)) -D$(TYPE) -I. -I$(GENERATED) \
 		$(SHARED_FLAG) $(LFLAGS_JVM_DB) -o $@ $(DTRACE_SRCDIR)/$(JVM_DB).c -lc
 	[ -f $(XLIBJVM_DB_G) ] || { ln -s $(LIBJVM_DB) $(XLIBJVM_DB_G); }
-ifneq ($(OBJCOPY),)
+ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1)
 	$(QUIETLY) $(OBJCOPY) --only-keep-debug $@ $(XLIBJVM_DB_DEBUGINFO)
 	$(QUIETLY) $(OBJCOPY) --add-gnu-debuglink=$(XLIBJVM_DB_DEBUGINFO) $@
   ifeq ($(STRIP_POLICY),all_strip)
@@ -117,7 +125,12 @@
     # implied else here is no stripping at all
     endif
   endif
-	[ -f $(XLIBJVM_DB_G_DEBUGINFO) ] || { ln -s $(LIBJVM_DB_DEBUGINFO) $(XLIBJVM_DB_G_DEBUGINFO); }
+	[ -f $(XLIBJVM_DB_G_DEBUGINFO) ] || { ln -s $(XLIBJVM_DB_DEBUGINFO) $(XLIBJVM_DB_G_DEBUGINFO); }
+  ifeq ($(ZIP_DEBUGINFO_FILES),1)
+	$(ZIPEXE) -q -y $(XLIBJVM_DB_DIZ) $(XLIBJVM_DB_DEBUGINFO) $(XLIBJVM_DB_G_DEBUGINFO)
+	$(RM) $(XLIBJVM_DB_DEBUGINFO) $(XLIBJVM_DB_G_DEBUGINFO)
+	[ -f $(XLIBJVM_DB_G_DIZ) ] || { ln -s $(XLIBJVM_DB_DIZ) $(XLIBJVM_DB_G_DIZ); }
+  endif
 endif
 
 $(XLIBJVM_DTRACE): $(DTRACE_SRCDIR)/$(JVM_DTRACE).c $(DTRACE_SRCDIR)/$(JVM_DTRACE).h $(LIBJVM_DTRACE_MAPFILE)
@@ -126,7 +139,7 @@
 	$(CC) $(SYMFLAG) $(ARCHFLAG/$(ISA)) -D$(TYPE) -I. \
 		$(SHARED_FLAG) $(LFLAGS_JVM_DTRACE) -o $@ $(DTRACE_SRCDIR)/$(JVM_DTRACE).c -lc -lthread -ldoor
 	[ -f $(XLIBJVM_DTRACE_G) ] || { ln -s $(LIBJVM_DTRACE) $(XLIBJVM_DTRACE_G); }
-ifneq ($(OBJCOPY),)
+ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1)
 	$(QUIETLY) $(OBJCOPY) --only-keep-debug $@ $(XLIBJVM_DTRACE_DEBUGINFO)
 	$(QUIETLY) $(OBJCOPY) --add-gnu-debuglink=$(XLIBJVM_DTRACE_DEBUGINFO) $@
   ifeq ($(STRIP_POLICY),all_strip)
@@ -137,7 +150,12 @@
     # implied else here is no stripping at all
     endif
   endif
-	[ -f $(XLIBJVM_DTRACE_G_DEBUGINFO) ] || { ln -s $(LIBJVM_DTRACE_DEBUGINFO) $(XLIBJVM_DTRACE_G_DEBUGINFO); }
+	[ -f $(XLIBJVM_DTRACE_G_DEBUGINFO) ] || { ln -s $(XLIBJVM_DTRACE_DEBUGINFO) $(XLIBJVM_DTRACE_G_DEBUGINFO); }
+  ifeq ($(ZIP_DEBUGINFO_FILES),1)
+	$(ZIPEXE) -q -y $(XLIBJVM_DTRACE_DIZ) $(XLIBJVM_DTRACE_DEBUGINFO) $(XLIBJVM_DTRACE_G_DEBUGINFO)
+	$(RM) $(XLIBJVM_DTRACE_DEBUGINFO) $(XLIBJVM_DTRACE_G_DEBUGINFO)
+	[ -f $(XLIBJVM_DTRACE_G_DIZ) ] || { ln -s $(XLIBJVM_DTRACE_DIZ) $(XLIBJVM_DTRACE_G_DIZ); }
+  endif
 endif
 
 endif # ifneq ("${ISA}","${BUILDARCH}")
@@ -185,7 +203,7 @@
 	$(QUIETLY) $(CC) $(SYMFLAG) $(ARCHFLAG) -D$(TYPE) -I. -I$(GENERATED) \
 		$(SHARED_FLAG) $(LFLAGS_JVM_DB) -o $@ $(DTRACE_SRCDIR)/$(JVM_DB).c -lc
 	[ -f $(LIBJVM_DB_G) ] || { ln -s $@ $(LIBJVM_DB_G); }
-ifneq ($(OBJCOPY),)
+ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1)
 	$(QUIETLY) $(OBJCOPY) --only-keep-debug $@ $(LIBJVM_DB_DEBUGINFO)
 	$(QUIETLY) $(OBJCOPY) --add-gnu-debuglink=$(LIBJVM_DB_DEBUGINFO) $@
   ifeq ($(STRIP_POLICY),all_strip)
@@ -197,6 +215,11 @@
     endif
   endif
 	[ -f $(LIBJVM_DB_G_DEBUGINFO) ] || { ln -s $(LIBJVM_DB_DEBUGINFO) $(LIBJVM_DB_G_DEBUGINFO); }
+  ifeq ($(ZIP_DEBUGINFO_FILES),1)
+	$(ZIPEXE) -q -y $(LIBJVM_DB_DIZ) $(LIBJVM_DB_DEBUGINFO) $(LIBJVM_DB_G_DEBUGINFO)
+	$(RM) $(LIBJVM_DB_DEBUGINFO) $(LIBJVM_DB_G_DEBUGINFO)
+	[ -f $(LIBJVM_DB_G_DIZ) ] || { ln -s $(LIBJVM_DB_DIZ) $(LIBJVM_DB_G_DIZ); }
+  endif
 endif
 
 $(LIBJVM_DTRACE): $(DTRACE_SRCDIR)/$(JVM_DTRACE).c $(XLIBJVM_DTRACE) $(DTRACE_SRCDIR)/$(JVM_DTRACE).h $(LIBJVM_DTRACE_MAPFILE)
@@ -204,7 +227,7 @@
 	$(QUIETLY) $(CC) $(SYMFLAG) $(ARCHFLAG) -D$(TYPE) -I.  \
 		$(SHARED_FLAG) $(LFLAGS_JVM_DTRACE) -o $@ $(DTRACE_SRCDIR)/$(JVM_DTRACE).c -lc -lthread -ldoor
 	[ -f $(LIBJVM_DTRACE_G) ] || { ln -s $@ $(LIBJVM_DTRACE_G); }
-ifneq ($(OBJCOPY),)
+ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1)
 	$(QUIETLY) $(OBJCOPY) --only-keep-debug $@ $(LIBJVM_DTRACE_DEBUGINFO)
 	$(QUIETLY) $(OBJCOPY) --add-gnu-debuglink=$(LIBJVM_DTRACE_DEBUGINFO) $@
   ifeq ($(STRIP_POLICY),all_strip)
@@ -216,6 +239,11 @@
     endif
   endif
 	[ -f $(LIBJVM_DTRACE_G_DEBUGINFO) ] || { ln -s $(LIBJVM_DTRACE_DEBUGINFO) $(LIBJVM_DTRACE_G_DEBUGINFO); }
+  ifeq ($(ZIP_DEBUGINFO_FILES),1)
+	$(ZIPEXE) -q -y $(LIBJVM_DTRACE_DIZ) $(LIBJVM_DTRACE_DEBUGINFO) $(LIBJVM_DTRACE_G_DEBUGINFO)
+	$(RM) $(LIBJVM_DTRACE_DEBUGINFO) $(LIBJVM_DTRACE_G_DEBUGINFO)
+	[ -f $(LIBJVM_DTRACE_G_DIZ) ] || { ln -s $(LIBJVM_DTRACE_DIZ) $(LIBJVM_DTRACE_G_DIZ); }
+  endif
 endif
 
 $(DTRACE).d: $(DTRACE_SRCDIR)/hotspot.d $(DTRACE_SRCDIR)/hotspot_jni.d \
--- a/hotspot/make/solaris/makefiles/jsig.make	Wed Jul 05 18:09:43 2017 +0200
+++ b/hotspot/make/solaris/makefiles/jsig.make	Wed Jul 05 18:10:27 2017 +0200
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
@@ -32,12 +32,15 @@
 LIBJSIG_G = lib$(JSIG_G).so
 
 LIBJSIG_DEBUGINFO   = lib$(JSIG).debuginfo
+LIBJSIG_DIZ         = lib$(JSIG).diz
 LIBJSIG_G_DEBUGINFO = lib$(JSIG_G).debuginfo
+LIBJSIG_G_DIZ       = lib$(JSIG_G).diz
 
 JSIGSRCDIR = $(GAMMADIR)/src/os/$(Platform_os_family)/vm
 
 DEST_JSIG           = $(JDK_LIBDIR)/$(LIBJSIG)
 DEST_JSIG_DEBUGINFO = $(JDK_LIBDIR)/$(LIBJSIG_DEBUGINFO)
+DEST_JSIG_DIZ       = $(JDK_LIBDIR)/$(LIBJSIG_DIZ)
 
 LIBJSIG_MAPFILE = $(MAKEFILES_DIR)/mapfile-vers-jsig
 
@@ -54,7 +57,7 @@
 	$(QUIETLY) $(CC) $(SYMFLAG) $(ARCHFLAG) $(SHARED_FLAG) $(PICFLAG) \
                          $(LFLAGS_JSIG) -o $@ $< -ldl
 	[ -f $(LIBJSIG_G) ] || { ln -s $@ $(LIBJSIG_G); }
-ifneq ($(OBJCOPY),)
+ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1)
 	$(QUIETLY) $(OBJCOPY) --only-keep-debug $@ $(LIBJSIG_DEBUGINFO)
 	$(QUIETLY) $(OBJCOPY) --add-gnu-debuglink=$(LIBJSIG_DEBUGINFO) $@
   ifeq ($(STRIP_POLICY),all_strip)
@@ -66,12 +69,19 @@
     endif
   endif
 	[ -f $(LIBJSIG_G_DEBUGINFO) ] || { ln -s $(LIBJSIG_DEBUGINFO) $(LIBJSIG_G_DEBUGINFO); }
+  ifeq ($(ZIP_DEBUGINFO_FILES),1)
+	$(ZIPEXE) -q -y $(LIBJSIG_DIZ) $(LIBJSIG_DEBUGINFO) $(LIBJSIG_G_DEBUGINFO)
+	$(RM) $(LIBJSIG_DEBUGINFO) $(LIBJSIG_G_DEBUGINFO)
+	[ -f $(LIBJSIG_G_DIZ) ] || { ln -s $(LIBJSIG_DIZ) $(LIBJSIG_G_DIZ); }
+  endif
 endif
 
 install_jsig: $(LIBJSIG)
 	@echo "Copying $(LIBJSIG) to $(DEST_JSIG)"
 	$(QUIETLY) test -f $(LIBJSIG_DEBUGINFO) && \
 	    cp -f $(LIBJSIG_DEBUGINFO) $(DEST_JSIG_DEBUGINFO)
+	$(QUIETLY) test -f $(LIBJSIG_DIZ) && \
+	    cp -f $(LIBJSIG_DIZ) $(DEST_JSIG_DIZ)
 	$(QUIETLY) cp -f $(LIBJSIG) $(DEST_JSIG) && echo "Done"
 
 .PHONY: install_jsig
--- a/hotspot/make/solaris/makefiles/saproc.make	Wed Jul 05 18:09:43 2017 +0200
+++ b/hotspot/make/solaris/makefiles/saproc.make	Wed Jul 05 18:10:27 2017 +0200
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
@@ -33,7 +33,9 @@
 LIBSAPROC_G = lib$(SAPROC_G).so
 
 LIBSAPROC_DEBUGINFO   = lib$(SAPROC).debuginfo
+LIBSAPROC_DIZ         = lib$(SAPROC).diz
 LIBSAPROC_G_DEBUGINFO = lib$(SAPROC_G).debuginfo
+LIBSAPROC_G_DIZ       = lib$(SAPROC_G).diz
 
 AGENT_DIR = $(GAMMADIR)/agent
 
@@ -45,6 +47,7 @@
 
 DEST_SAPROC           = $(JDK_LIBDIR)/$(LIBSAPROC)
 DEST_SAPROC_DEBUGINFO = $(JDK_LIBDIR)/$(LIBSAPROC_DEBUGINFO)
+DEST_SAPROC_DIZ       = $(JDK_LIBDIR)/$(LIBSAPROC_DIZ)
 
 # if $(AGENT_DIR) does not exist, we don't build SA
 
@@ -105,7 +108,7 @@
 	           -o $@                                                \
 	           -ldl -ldemangle -lthread -lc
 	[ -f $(LIBSAPROC_G) ] || { ln -s $@ $(LIBSAPROC_G); }
-ifneq ($(OBJCOPY),)
+ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1)
 	$(QUIETLY) $(OBJCOPY) --only-keep-debug $@ $(LIBSAPROC_DEBUGINFO)
 	$(QUIETLY) $(OBJCOPY) --add-gnu-debuglink=$(LIBSAPROC_DEBUGINFO) $@
   ifeq ($(STRIP_POLICY),all_strip)
@@ -117,6 +120,11 @@
     endif
   endif
 	[ -f $(LIBSAPROC_G_DEBUGINFO) ] || { ln -s $(LIBSAPROC_DEBUGINFO) $(LIBSAPROC_G_DEBUGINFO); }
+  ifeq ($(ZIP_DEBUGINFO_FILES),1)
+	$(ZIPEXE) -q -y $(LIBSAPROC_DIZ) $(LIBSAPROC_DEBUGINFO) $(LIBSAPROC_G_DEBUGINFO)
+	$(RM) $(LIBSAPROC_DEBUGINFO) $(LIBSAPROC_G_DEBUGINFO)
+	[ -f $(LIBSAPROC_G_DIZ) ] || { ln -s $(LIBSAPROC_DIZ) $(LIBSAPROC_G_DIZ); }
+  endif
 endif
 
 install_saproc: $(BULDLIBSAPROC)
@@ -124,6 +132,8 @@
 	  echo "Copying $(LIBSAPROC) to $(DEST_SAPROC)";     \
 	  test -f $(LIBSAPROC_DEBUGINFO) &&             \
 	    cp -f $(LIBSAPROC_DEBUGINFO) $(DEST_SAPROC_DEBUGINFO); \
+	  test -f $(LIBSAPROC_DIZ) &&             \
+	    cp -f $(LIBSAPROC_DIZ) $(DEST_SAPROC_DIZ); \
 	  cp -f $(LIBSAPROC) $(DEST_SAPROC) && echo "Done";  \
 	fi
 
--- a/hotspot/make/solaris/makefiles/sparcWorks.make	Wed Jul 05 18:09:43 2017 +0200
+++ b/hotspot/make/solaris/makefiles/sparcWorks.make	Wed Jul 05 18:10:27 2017 +0200
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
@@ -488,12 +488,12 @@
 # The -g0 setting allows the C++ frontend to inline, which is a big win.
 # The -xs setting disables 'lazy debug info' which puts everything in
 # the .so instead of requiring the '.o' files.
-ifneq ($(OBJCOPY),)
+ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1)
   OPT_CFLAGS += -g0 -xs
 endif
 DEBUG_CFLAGS = -g
 FASTDEBUG_CFLAGS = -g0
-ifneq ($(OBJCOPY),)
+ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1)
   DEBUG_CFLAGS += -xs
   FASTDEBUG_CFLAGS += -xs
 endif
--- a/hotspot/make/solaris/makefiles/vm.make	Wed Jul 05 18:09:43 2017 +0200
+++ b/hotspot/make/solaris/makefiles/vm.make	Wed Jul 05 18:10:27 2017 +0200
@@ -56,7 +56,7 @@
 INCLUDES += $(Src_Dirs_I:%=-I%)
 
 # SYMFLAG is used by {dtrace,jsig,saproc}.make.
-ifneq ($(OBJCOPY),)
+ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1)
   # always build with debug info when we can create .debuginfo files
   # and disable 'lazy debug info' so the .so has everything.
   SYMFLAG = -g -xs
@@ -152,7 +152,9 @@
 LIBJVM_G = lib$(JVM)$(G_SUFFIX).so
 
 LIBJVM_DEBUGINFO   = lib$(JVM).debuginfo
+LIBJVM_DIZ         = lib$(JVM).diz
 LIBJVM_G_DEBUGINFO = lib$(JVM)$(G_SUFFIX).debuginfo
+LIBJVM_G_DIZ       = lib$(JVM)$(G_SUFFIX).diz
 
 SPECIAL_PATHS:=adlc c1 dist gc_implementation opto shark libadt
 
@@ -283,7 +285,7 @@
 	$(QUIETLY) rm -f $@.1 && ln -s $@ $@.1
 	$(QUIETLY) [ -f $(LIBJVM_G) ] || ln -s $@ $(LIBJVM_G)
 	$(QUIETLY) [ -f $(LIBJVM_G).1 ] || ln -s $@.1 $(LIBJVM_G).1
-ifneq ($(OBJCOPY),)
+ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1)
 	$(QUIETLY) $(OBJCOPY) --only-keep-debug $@ $(LIBJVM_DEBUGINFO)
 	$(QUIETLY) $(OBJCOPY) --add-gnu-debuglink=$(LIBJVM_DEBUGINFO) $@
   ifeq ($(STRIP_POLICY),all_strip)
@@ -295,6 +297,11 @@
     endif
   endif
 	$(QUIETLY) [ -f $(LIBJVM_G_DEBUGINFO) ] || ln -s $(LIBJVM_DEBUGINFO) $(LIBJVM_G_DEBUGINFO)
+  ifeq ($(ZIP_DEBUGINFO_FILES),1)
+	$(ZIPEXE) -q -y $(LIBJVM_DIZ) $(LIBJVM_DEBUGINFO) $(LIBJVM_G_DEBUGINFO)
+	$(RM) $(LIBJVM_DEBUGINFO) $(LIBJVM_G_DEBUGINFO)
+	[ -f $(LIBJVM_G_DIZ) ] || { ln -s $(LIBJVM_DIZ) $(LIBJVM_G_DIZ); }
+  endif
 endif
 endif # filter -sbfast -xsbfast
 
@@ -302,11 +309,14 @@
 DEST_SUBDIR        = $(JDK_LIBDIR)/$(VM_SUBDIR)
 DEST_JVM           = $(DEST_SUBDIR)/$(LIBJVM)
 DEST_JVM_DEBUGINFO = $(DEST_SUBDIR)/$(LIBJVM_DEBUGINFO)
+DEST_JVM_DIZ       = $(DEST_SUBDIR)/$(LIBJVM_DIZ)
 
 install_jvm: $(LIBJVM)
 	@echo "Copying $(LIBJVM) to $(DEST_JVM)"
 	$(QUIETLY) test -f $(LIBJVM_DEBUGINFO) && \
 	    cp -f $(LIBJVM_DEBUGINFO) $(DEST_JVM_DEBUGINFO)
+	$(QUIETLY) test -f $(LIBJVM_DIZ) && \
+	    cp -f $(LIBJVM_DIZ) $(DEST_JVM_DIZ)
 	$(QUIETLY) cp -f $(LIBJVM) $(DEST_JVM) && echo "Done"
 
 #----------------------------------------------------------------------
--- a/hotspot/make/windows/build.make	Wed Jul 05 18:09:43 2017 +0200
+++ b/hotspot/make/windows/build.make	Wed Jul 05 18:10:27 2017 +0200
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
@@ -302,6 +302,10 @@
 	@ echo MT=$(MT)						>> $@
 	@ echo RC=$(RC)						>> $@
 	@ sh $(WorkSpace)/make/windows/get_msc_ver.sh		>> $@
+	@ if "$(ENABLE_FULL_DEBUG_SYMBOLS)" NEQ "" echo ENABLE_FULL_DEBUG_SYMBOLS=$(ENABLE_FULL_DEBUG_SYMBOLS) >> $@
+	@ if "$(ZIP_DEBUGINFO_FILES)" NEQ "" echo ZIP_DEBUGINFO_FILES=$(ZIP_DEBUGINFO_FILES) >> $@
+	@ if "$(RM)" NEQ "" echo RM=$(RM)                       >> $@
+	@ if "$(ZIPEXE)" NEQ "" echo ZIPEXE=$(ZIPEXE)           >> $@
 
 checks: checkVariant checkWorkSpace checkSA
 
--- a/hotspot/make/windows/makefiles/compile.make	Wed Jul 05 18:09:43 2017 +0200
+++ b/hotspot/make/windows/makefiles/compile.make	Wed Jul 05 18:10:27 2017 +0200
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
@@ -54,8 +54,10 @@
 # These are always used in all compiles
 CXX_FLAGS=/nologo /W3 /WX
 
-# Let's add debug information always too.
+# Let's add debug information when Full Debug Symbols is enabled
+!if "$(ENABLE_FULL_DEBUG_SYMBOLS)" == "1"
 CXX_FLAGS=$(CXX_FLAGS) /Zi
+!endif
 
 # Based on BUILDARCH we add some flags and select the default compiler name
 !if "$(BUILDARCH)" == "ia64"
@@ -239,7 +241,10 @@
 LD_FLAGS= $(LD_FLAGS) kernel32.lib user32.lib gdi32.lib winspool.lib \
  comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib \
  uuid.lib Wsock32.lib winmm.lib /nologo /machine:$(MACHINE) /opt:REF \
- /opt:ICF,8 /map /debug
+ /opt:ICF,8
+!if "$(ENABLE_FULL_DEBUG_SYMBOLS)" == "1"
+LD_FLAGS= $(LD_FLAGS) /map /debug
+!endif
 
 
 !if $(MSC_VER) >= 1600 
--- a/hotspot/make/windows/makefiles/debug.make	Wed Jul 05 18:09:43 2017 +0200
+++ b/hotspot/make/windows/makefiles/debug.make	Wed Jul 05 18:10:27 2017 +0200
@@ -61,6 +61,12 @@
 # separately.  Use ";#2" for .dll and ";#1" for .exe:
 	$(MT) /manifest $@.manifest /outputresource:$@;#2
 !endif
+!if "$(ENABLE_FULL_DEBUG_SYMBOLS)" == "1"
+!if "$(ZIP_DEBUGINFO_FILES)" == "1"
+	$(ZIPEXE) -q $*.diz $*.map $*.pdb
+	$(RM) $*.map $*.pdb
+!endif
+!endif
 
 !include $(WorkSpace)/make/windows/makefiles/shared.make
 !include $(WorkSpace)/make/windows/makefiles/sa.make
--- a/hotspot/make/windows/makefiles/defs.make	Wed Jul 05 18:09:43 2017 +0200
+++ b/hotspot/make/windows/makefiles/defs.make	Wed Jul 05 18:10:27 2017 +0200
@@ -107,6 +107,52 @@
   endif
 endif
 
+# Full Debug Symbols has been enabled on Windows since JDK1.4.1 so
+# there is no need for an "earlier than JDK7 check".
+# The Full Debug Symbols (FDS) default for BUILD_FLAVOR == product
+# builds is enabled with debug info files ZIP'ed to save space. For
+# BUILD_FLAVOR != product builds, FDS is always enabled, after all a
+# debug build without debug info isn't very useful.
+# The ZIP_DEBUGINFO_FILES option only has meaning when FDS is enabled.
+#
+# If you invoke a build with FULL_DEBUG_SYMBOLS=0, then FDS will be
+# disabled for a BUILD_FLAVOR == product build.
+#
+# Note: Use of a different variable name for the FDS override option
+# versus the FDS enabled check is intentional (FULL_DEBUG_SYMBOLS
+# versus ENABLE_FULL_DEBUG_SYMBOLS). For auto build systems that pass
+# in options via environment variables, use of distinct variables
+# prevents strange behaviours. For example, in a BUILD_FLAVOR !=
+# product build, the FULL_DEBUG_SYMBOLS environment variable will be
+# 0, but the ENABLE_FULL_DEBUG_SYMBOLS make variable will be 1. If
+# the same variable name is used, then different values can be picked
+# up by different parts of the build. Just to be clear, we only need
+# two variable names because the incoming option value can be
+# overridden in some situations, e.g., a BUILD_FLAVOR != product
+# build.
+
+ifeq ($(BUILD_FLAVOR), product)
+  FULL_DEBUG_SYMBOLS ?= 1
+  ENABLE_FULL_DEBUG_SYMBOLS = $(FULL_DEBUG_SYMBOLS)
+else
+  # debug variants always get Full Debug Symbols (if available)
+  ENABLE_FULL_DEBUG_SYMBOLS = 1
+endif
+_JUNK_ := $(shell \
+  echo >&2 "INFO: ENABLE_FULL_DEBUG_SYMBOLS=$(ENABLE_FULL_DEBUG_SYMBOLS)")
+MAKE_ARGS += ENABLE_FULL_DEBUG_SYMBOLS=$(ENABLE_FULL_DEBUG_SYMBOLS)
+
+ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1)
+  # Disable ZIP_DEBUGINFO_FILES by default because various tests are
+  # failing in nightly when the debug info files are ZIP'ed.
+  ZIP_DEBUGINFO_FILES ?= 0
+else
+  ZIP_DEBUGINFO_FILES=0
+endif
+MAKE_ARGS += ZIP_DEBUGINFO_FILES=$(ZIP_DEBUGINFO_FILES)
+MAKE_ARGS += RM="$(RM)"
+MAKE_ARGS += ZIPEXE=$(ZIPEXE)
+
 # On 32 bit windows we build server, client and kernel, on 64 bit just server.
 ifeq ($(JVM_VARIANTS),)
   ifeq ($(ARCH_DATA_MODEL), 32)
@@ -193,29 +239,53 @@
 ifeq ($(JVM_VARIANT_SERVER),true)
   EXPORT_LIST += $(EXPORT_SERVER_DIR)/Xusage.txt
   EXPORT_LIST += $(EXPORT_SERVER_DIR)/jvm.$(LIBRARY_SUFFIX)
-  EXPORT_LIST += $(EXPORT_SERVER_DIR)/jvm.pdb
-  EXPORT_LIST += $(EXPORT_SERVER_DIR)/jvm.map
+  ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1)
+    ifeq ($(ZIP_DEBUGINFO_FILES),1)
+      EXPORT_LIST += $(EXPORT_SERVER_DIR)/jvm.diz
+    else
+      EXPORT_LIST += $(EXPORT_SERVER_DIR)/jvm.pdb
+      EXPORT_LIST += $(EXPORT_SERVER_DIR)/jvm.map
+    endif
+  endif
   EXPORT_LIST += $(EXPORT_LIB_DIR)/jvm.lib
 endif
 ifeq ($(JVM_VARIANT_CLIENT),true)
   EXPORT_LIST += $(EXPORT_CLIENT_DIR)/Xusage.txt
   EXPORT_LIST += $(EXPORT_CLIENT_DIR)/jvm.$(LIBRARY_SUFFIX)
-  EXPORT_LIST += $(EXPORT_CLIENT_DIR)/jvm.pdb
-  EXPORT_LIST += $(EXPORT_CLIENT_DIR)/jvm.map
+  ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1)
+    ifeq ($(ZIP_DEBUGINFO_FILES),1)
+      EXPORT_LIST += $(EXPORT_CLIENT_DIR)/jvm.diz
+    else
+      EXPORT_LIST += $(EXPORT_CLIENT_DIR)/jvm.pdb
+      EXPORT_LIST += $(EXPORT_CLIENT_DIR)/jvm.map
+    endif
+  endif
 endif
 ifeq ($(JVM_VARIANT_KERNEL),true)
   EXPORT_LIST += $(EXPORT_KERNEL_DIR)/Xusage.txt
   EXPORT_LIST += $(EXPORT_KERNEL_DIR)/jvm.$(LIBRARY_SUFFIX)
-  EXPORT_LIST += $(EXPORT_KERNEL_DIR)/jvm.pdb
-  EXPORT_LIST += $(EXPORT_KERNEL_DIR)/jvm.map
+  ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1)
+    ifeq ($(ZIP_DEBUGINFO_FILES),1)
+      EXPORT_LIST += $(EXPORT_KERNEL_DIR)/jvm.diz
+    else
+      EXPORT_LIST += $(EXPORT_KERNEL_DIR)/jvm.pdb
+      EXPORT_LIST += $(EXPORT_KERNEL_DIR)/jvm.map
+    endif
+  endif
 endif
 
 EXPORT_LIST += $(EXPORT_JRE_LIB_DIR)/wb.jar
 
 ifeq ($(BUILD_WIN_SA), 1)
   EXPORT_LIST += $(EXPORT_JRE_BIN_DIR)/sawindbg.$(LIBRARY_SUFFIX)
-  EXPORT_LIST += $(EXPORT_JRE_BIN_DIR)/sawindbg.pdb
-  EXPORT_LIST += $(EXPORT_JRE_BIN_DIR)/sawindbg.map
+  ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1)
+    ifeq ($(ZIP_DEBUGINFO_FILES),1)
+      EXPORT_LIST += $(EXPORT_JRE_BIN_DIR)/sawindbg.diz
+    else
+      EXPORT_LIST += $(EXPORT_JRE_BIN_DIR)/sawindbg.pdb
+      EXPORT_LIST += $(EXPORT_JRE_BIN_DIR)/sawindbg.map
+    endif
+  endif
   EXPORT_LIST += $(EXPORT_LIB_DIR)/sa-jdi.jar
   # Must pass this down to nmake.
   MAKE_ARGS += BUILD_WIN_SA=1
--- a/hotspot/make/windows/makefiles/fastdebug.make	Wed Jul 05 18:09:43 2017 +0200
+++ b/hotspot/make/windows/makefiles/fastdebug.make	Wed Jul 05 18:10:27 2017 +0200
@@ -61,6 +61,12 @@
 # separately.  Use ";#2" for .dll and ";#1" for .exe:
 	$(MT) /manifest $@.manifest /outputresource:$@;#2
 !endif
+!if "$(ENABLE_FULL_DEBUG_SYMBOLS)" == "1"
+!if "$(ZIP_DEBUGINFO_FILES)" == "1"
+	$(ZIPEXE) -q $*.diz $*.map $*.pdb
+	$(RM) $*.map $*.pdb
+!endif
+!endif
 
 !include $(WorkSpace)/make/windows/makefiles/shared.make
 !include $(WorkSpace)/make/windows/makefiles/sa.make
--- a/hotspot/make/windows/makefiles/product.make	Wed Jul 05 18:09:43 2017 +0200
+++ b/hotspot/make/windows/makefiles/product.make	Wed Jul 05 18:10:27 2017 +0200
@@ -72,6 +72,12 @@
 # separately.  Use ";#2" for .dll and ";#1" for .exe:
 	$(MT) /manifest $@.manifest /outputresource:$@;#2
 !endif
+!if "$(ENABLE_FULL_DEBUG_SYMBOLS)" == "1"
+!if "$(ZIP_DEBUGINFO_FILES)" == "1"
+	$(ZIPEXE) -q $*.diz $*.map $*.pdb
+	$(RM) $*.map $*.pdb
+!endif
+!endif
 
 !include $(WorkSpace)/make/windows/makefiles/shared.make
 !include $(WorkSpace)/make/windows/makefiles/sa.make
--- a/hotspot/make/windows/makefiles/sa.make	Wed Jul 05 18:09:43 2017 +0200
+++ b/hotspot/make/windows/makefiles/sa.make	Wed Jul 05 18:10:27 2017 +0200
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
@@ -94,13 +94,19 @@
 SA_LD_FLAGS = bufferoverflowU.lib
 !endif
 !else
-SA_CFLAGS = /nologo $(MS_RUNTIME_OPTION) /W3 /Gm $(GX_OPTION) /ZI /Od /D "WIN32" /D "_WINDOWS" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+SA_CFLAGS = /nologo $(MS_RUNTIME_OPTION) /W3 /Gm $(GX_OPTION) /Od /D "WIN32" /D "_WINDOWS" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+!if "$(ENABLE_FULL_DEBUG_SYMBOLS)" == "1"
+SA_CFLAGS = $(SA_CFLAGS) /ZI
+!endif
 !endif
 !if "$(MT)" != ""
 SA_LD_FLAGS = /manifest $(SA_LD_FLAGS)
 !endif
 SASRCFILE = $(AGENT_DIR)/src/os/win32/windbg/sawindbg.cpp
-SA_LFLAGS = $(SA_LD_FLAGS) /nologo /subsystem:console /map /debug /machine:$(MACHINE)
+SA_LFLAGS = $(SA_LD_FLAGS) /nologo /subsystem:console /machine:$(MACHINE)
+!if "$(ENABLE_FULL_DEBUG_SYMBOLS)" == "1"
+SA_LFLAGS = $(SA_LFLAGS) /map /debug
+!endif
 
 # Note that we do not keep sawindbj.obj around as it would then
 # get included in the dumpbin command in build_vm_def.sh
@@ -114,14 +120,20 @@
 	  /I"$(BootStrapDir)/include" /I"$(BootStrapDir)/include/win32" 
 	  /I"$(GENERATED)" $(SA_CFLAGS)
 	  $(SASRCFILE)
-	  /out:sawindbg.obj
+	  /out:$*.obj
 <<
 	set LIB=$(SA_LIB)$(LIB)
-	$(LD) /out:$@ /DLL sawindbg.obj dbgeng.lib $(SA_LFLAGS)
+	$(LD) /out:$@ /DLL $*.obj dbgeng.lib $(SA_LFLAGS)
 !if "$(MT)" != ""
 	$(MT) /manifest $(@F).manifest /outputresource:$(@F);#2
 !endif
-	-@rm -f sawindbg.obj
+!if "$(ENABLE_FULL_DEBUG_SYMBOLS)" == "1"
+!if "$(ZIP_DEBUGINFO_FILES)" == "1"
+	$(ZIPEXE) -q $*.diz $*.map $*.pdb
+	$(RM) $*.map $*.pdb
+!endif
+!endif
+	-@rm -f $*.obj
 
 cleanall :
 	rm -rf $(GENERATED:\=/)/saclasses
--- a/hotspot/src/os/solaris/vm/attachListener_solaris.cpp	Wed Jul 05 18:09:43 2017 +0200
+++ b/hotspot/src/os/solaris/vm/attachListener_solaris.cpp	Wed Jul 05 18:10:27 2017 +0200
@@ -336,7 +336,9 @@
     // Return 0 (success) + file descriptor, or non-0 (error)
     if (res == 0) {
       door_desc_t desc;
-      desc.d_attributes = DOOR_DESCRIPTOR;
+      // DOOR_RELEASE flag makes sure fd is closed after passing it to
+      // the client.  See door_return(3DOOR) man page.
+      desc.d_attributes = DOOR_DESCRIPTOR | DOOR_RELEASE;
       desc.d_data.d_desc.d_descriptor = return_fd;
       door_return((char*)&res, sizeof(res), &desc, 1);
     } else {
--- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/binaryTreeDictionary.cpp	Wed Jul 05 18:09:43 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1257 +0,0 @@
-/*
- * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-
-#include "precompiled.hpp"
-#include "gc_implementation/concurrentMarkSweep/binaryTreeDictionary.hpp"
-#include "gc_implementation/shared/allocationStats.hpp"
-#include "gc_implementation/shared/spaceDecorator.hpp"
-#include "memory/space.inline.hpp"
-#include "runtime/globals.hpp"
-#include "utilities/ostream.hpp"
-
-////////////////////////////////////////////////////////////////////////////////
-// A binary tree based search structure for free blocks.
-// This is currently used in the Concurrent Mark&Sweep implementation.
-////////////////////////////////////////////////////////////////////////////////
-
-TreeChunk* TreeChunk::as_TreeChunk(FreeChunk* fc) {
-  // Do some assertion checking here.
-  return (TreeChunk*) fc;
-}
-
-void TreeChunk::verifyTreeChunkList() const {
-  TreeChunk* nextTC = (TreeChunk*)next();
-  if (prev() != NULL) { // interior list node shouldn'r have tree fields
-    guarantee(embedded_list()->parent() == NULL && embedded_list()->left() == NULL &&
-              embedded_list()->right()  == NULL, "should be clear");
-  }
-  if (nextTC != NULL) {
-    guarantee(as_TreeChunk(nextTC->prev()) == this, "broken chain");
-    guarantee(nextTC->size() == size(), "wrong size");
-    nextTC->verifyTreeChunkList();
-  }
-}
-
-
-TreeList* TreeList::as_TreeList(TreeChunk* tc) {
-  // This first free chunk in the list will be the tree list.
-  assert(tc->size() >= sizeof(TreeChunk), "Chunk is too small for a TreeChunk");
-  TreeList* tl = tc->embedded_list();
-  tc->set_list(tl);
-#ifdef ASSERT
-  tl->set_protecting_lock(NULL);
-#endif
-  tl->set_hint(0);
-  tl->set_size(tc->size());
-  tl->link_head(tc);
-  tl->link_tail(tc);
-  tl->set_count(1);
-  tl->init_statistics(true /* split_birth */);
-  tl->setParent(NULL);
-  tl->setLeft(NULL);
-  tl->setRight(NULL);
-  return tl;
-}
-
-TreeList* TreeList::as_TreeList(HeapWord* addr, size_t size) {
-  TreeChunk* tc = (TreeChunk*) addr;
-  assert(size >= sizeof(TreeChunk), "Chunk is too small for a TreeChunk");
-  // The space in the heap will have been mangled initially but
-  // is not remangled when a free chunk is returned to the free list
-  // (since it is used to maintain the chunk on the free list).
-  assert((ZapUnusedHeapArea &&
-          SpaceMangler::is_mangled((HeapWord*) tc->size_addr()) &&
-          SpaceMangler::is_mangled((HeapWord*) tc->prev_addr()) &&
-          SpaceMangler::is_mangled((HeapWord*) tc->next_addr())) ||
-          (tc->size() == 0 && tc->prev() == NULL && tc->next() == NULL),
-    "Space should be clear or mangled");
-  tc->setSize(size);
-  tc->linkPrev(NULL);
-  tc->linkNext(NULL);
-  TreeList* tl = TreeList::as_TreeList(tc);
-  return tl;
-}
-
-TreeList* TreeList::removeChunkReplaceIfNeeded(TreeChunk* tc) {
-
-  TreeList* retTL = this;
-  FreeChunk* list = head();
-  assert(!list || list != list->next(), "Chunk on list twice");
-  assert(tc != NULL, "Chunk being removed is NULL");
-  assert(parent() == NULL || this == parent()->left() ||
-    this == parent()->right(), "list is inconsistent");
-  assert(tc->isFree(), "Header is not marked correctly");
-  assert(head() == NULL || head()->prev() == NULL, "list invariant");
-  assert(tail() == NULL || tail()->next() == NULL, "list invariant");
-
-  FreeChunk* prevFC = tc->prev();
-  TreeChunk* nextTC = TreeChunk::as_TreeChunk(tc->next());
-  assert(list != NULL, "should have at least the target chunk");
-
-  // Is this the first item on the list?
-  if (tc == list) {
-    // The "getChunk..." functions for a TreeList will not return the
-    // first chunk in the list unless it is the last chunk in the list
-    // because the first chunk is also acting as the tree node.
-    // When coalescing happens, however, the first chunk in the a tree
-    // list can be the start of a free range.  Free ranges are removed
-    // from the free lists so that they are not available to be
-    // allocated when the sweeper yields (giving up the free list lock)
-    // to allow mutator activity.  If this chunk is the first in the
-    // list and is not the last in the list, do the work to copy the
-    // TreeList from the first chunk to the next chunk and update all
-    // the TreeList pointers in the chunks in the list.
-    if (nextTC == NULL) {
-      assert(prevFC == NULL, "Not last chunk in the list");
-      set_tail(NULL);
-      set_head(NULL);
-    } else {
-      // copy embedded list.
-      nextTC->set_embedded_list(tc->embedded_list());
-      retTL = nextTC->embedded_list();
-      // Fix the pointer to the list in each chunk in the list.
-      // This can be slow for a long list.  Consider having
-      // an option that does not allow the first chunk on the
-      // list to be coalesced.
-      for (TreeChunk* curTC = nextTC; curTC != NULL;
-          curTC = TreeChunk::as_TreeChunk(curTC->next())) {
-        curTC->set_list(retTL);
-      }
-      // Fix the parent to point to the new TreeList.
-      if (retTL->parent() != NULL) {
-        if (this == retTL->parent()->left()) {
-          retTL->parent()->setLeft(retTL);
-        } else {
-          assert(this == retTL->parent()->right(), "Parent is incorrect");
-          retTL->parent()->setRight(retTL);
-        }
-      }
-      // Fix the children's parent pointers to point to the
-      // new list.
-      assert(right() == retTL->right(), "Should have been copied");
-      if (retTL->right() != NULL) {
-        retTL->right()->setParent(retTL);
-      }
-      assert(left() == retTL->left(), "Should have been copied");
-      if (retTL->left() != NULL) {
-        retTL->left()->setParent(retTL);
-      }
-      retTL->link_head(nextTC);
-      assert(nextTC->isFree(), "Should be a free chunk");
-    }
-  } else {
-    if (nextTC == NULL) {
-      // Removing chunk at tail of list
-      link_tail(prevFC);
-    }
-    // Chunk is interior to the list
-    prevFC->linkAfter(nextTC);
-  }
-
-  // Below this point the embeded TreeList being used for the
-  // tree node may have changed. Don't use "this"
-  // TreeList*.
-  // chunk should still be a free chunk (bit set in _prev)
-  assert(!retTL->head() || retTL->size() == retTL->head()->size(),
-    "Wrong sized chunk in list");
-  debug_only(
-    tc->linkPrev(NULL);
-    tc->linkNext(NULL);
-    tc->set_list(NULL);
-    bool prev_found = false;
-    bool next_found = false;
-    for (FreeChunk* curFC = retTL->head();
-         curFC != NULL; curFC = curFC->next()) {
-      assert(curFC != tc, "Chunk is still in list");
-      if (curFC == prevFC) {
-        prev_found = true;
-      }
-      if (curFC == nextTC) {
-        next_found = true;
-      }
-    }
-    assert(prevFC == NULL || prev_found, "Chunk was lost from list");
-    assert(nextTC == NULL || next_found, "Chunk was lost from list");
-    assert(retTL->parent() == NULL ||
-           retTL == retTL->parent()->left() ||
-           retTL == retTL->parent()->right(),
-           "list is inconsistent");
-  )
-  retTL->decrement_count();
-
-  assert(tc->isFree(), "Should still be a free chunk");
-  assert(retTL->head() == NULL || retTL->head()->prev() == NULL,
-    "list invariant");
-  assert(retTL->tail() == NULL || retTL->tail()->next() == NULL,
-    "list invariant");
-  return retTL;
-}
-void TreeList::returnChunkAtTail(TreeChunk* chunk) {
-  assert(chunk != NULL, "returning NULL chunk");
-  assert(chunk->list() == this, "list should be set for chunk");
-  assert(tail() != NULL, "The tree list is embedded in the first chunk");
-  // which means that the list can never be empty.
-  assert(!verifyChunkInFreeLists(chunk), "Double entry");
-  assert(head() == NULL || head()->prev() == NULL, "list invariant");
-  assert(tail() == NULL || tail()->next() == NULL, "list invariant");
-
-  FreeChunk* fc = tail();
-  fc->linkAfter(chunk);
-  link_tail(chunk);
-
-  assert(!tail() || size() == tail()->size(), "Wrong sized chunk in list");
-  increment_count();
-  debug_only(increment_returnedBytes_by(chunk->size()*sizeof(HeapWord));)
-  assert(head() == NULL || head()->prev() == NULL, "list invariant");
-  assert(tail() == NULL || tail()->next() == NULL, "list invariant");
-}
-
-// Add this chunk at the head of the list.  "At the head of the list"
-// is defined to be after the chunk pointer to by head().  This is
-// because the TreeList is embedded in the first TreeChunk in the
-// list.  See the definition of TreeChunk.
-void TreeList::returnChunkAtHead(TreeChunk* chunk) {
-  assert(chunk->list() == this, "list should be set for chunk");
-  assert(head() != NULL, "The tree list is embedded in the first chunk");
-  assert(chunk != NULL, "returning NULL chunk");
-  assert(!verifyChunkInFreeLists(chunk), "Double entry");
-  assert(head() == NULL || head()->prev() == NULL, "list invariant");
-  assert(tail() == NULL || tail()->next() == NULL, "list invariant");
-
-  FreeChunk* fc = head()->next();
-  if (fc != NULL) {
-    chunk->linkAfter(fc);
-  } else {
-    assert(tail() == NULL, "List is inconsistent");
-    link_tail(chunk);
-  }
-  head()->linkAfter(chunk);
-  assert(!head() || size() == head()->size(), "Wrong sized chunk in list");
-  increment_count();
-  debug_only(increment_returnedBytes_by(chunk->size()*sizeof(HeapWord));)
-  assert(head() == NULL || head()->prev() == NULL, "list invariant");
-  assert(tail() == NULL || tail()->next() == NULL, "list invariant");
-}
-
-TreeChunk* TreeList::head_as_TreeChunk() {
-  assert(head() == NULL || TreeChunk::as_TreeChunk(head())->list() == this,
-    "Wrong type of chunk?");
-  return TreeChunk::as_TreeChunk(head());
-}
-
-TreeChunk* TreeList::first_available() {
-  assert(head() != NULL, "The head of the list cannot be NULL");
-  FreeChunk* fc = head()->next();
-  TreeChunk* retTC;
-  if (fc == NULL) {
-    retTC = head_as_TreeChunk();
-  } else {
-    retTC = TreeChunk::as_TreeChunk(fc);
-  }
-  assert(retTC->list() == this, "Wrong type of chunk.");
-  return retTC;
-}
-
-// Returns the block with the largest heap address amongst
-// those in the list for this size; potentially slow and expensive,
-// use with caution!
-TreeChunk* TreeList::largest_address() {
-  assert(head() != NULL, "The head of the list cannot be NULL");
-  FreeChunk* fc = head()->next();
-  TreeChunk* retTC;
-  if (fc == NULL) {
-    retTC = head_as_TreeChunk();
-  } else {
-    // walk down the list and return the one with the highest
-    // heap address among chunks of this size.
-    FreeChunk* last = fc;
-    while (fc->next() != NULL) {
-      if ((HeapWord*)last < (HeapWord*)fc) {
-        last = fc;
-      }
-      fc = fc->next();
-    }
-    retTC = TreeChunk::as_TreeChunk(last);
-  }
-  assert(retTC->list() == this, "Wrong type of chunk.");
-  return retTC;
-}
-
-BinaryTreeDictionary::BinaryTreeDictionary(MemRegion mr, bool splay):
-  _splay(splay)
-{
-  assert(mr.byte_size() > MIN_TREE_CHUNK_SIZE, "minimum chunk size");
-
-  reset(mr);
-  assert(root()->left() == NULL, "reset check failed");
-  assert(root()->right() == NULL, "reset check failed");
-  assert(root()->head()->next() == NULL, "reset check failed");
-  assert(root()->head()->prev() == NULL, "reset check failed");
-  assert(totalSize() == root()->size(), "reset check failed");
-  assert(totalFreeBlocks() == 1, "reset check failed");
-}
-
-void BinaryTreeDictionary::inc_totalSize(size_t inc) {
-  _totalSize = _totalSize + inc;
-}
-
-void BinaryTreeDictionary::dec_totalSize(size_t dec) {
-  _totalSize = _totalSize - dec;
-}
-
-void BinaryTreeDictionary::reset(MemRegion mr) {
-  assert(mr.byte_size() > MIN_TREE_CHUNK_SIZE, "minimum chunk size");
-  set_root(TreeList::as_TreeList(mr.start(), mr.word_size()));
-  set_totalSize(mr.word_size());
-  set_totalFreeBlocks(1);
-}
-
-void BinaryTreeDictionary::reset(HeapWord* addr, size_t byte_size) {
-  MemRegion mr(addr, heap_word_size(byte_size));
-  reset(mr);
-}
-
-void BinaryTreeDictionary::reset() {
-  set_root(NULL);
-  set_totalSize(0);
-  set_totalFreeBlocks(0);
-}
-
-// Get a free block of size at least size from tree, or NULL.
-// If a splay step is requested, the removal algorithm (only) incorporates
-// a splay step as follows:
-// . the search proceeds down the tree looking for a possible
-//   match. At the (closest) matching location, an appropriate splay step is applied
-//   (zig, zig-zig or zig-zag). A chunk of the appropriate size is then returned
-//   if available, and if it's the last chunk, the node is deleted. A deteleted
-//   node is replaced in place by its tree successor.
-TreeChunk*
-BinaryTreeDictionary::getChunkFromTree(size_t size, Dither dither, bool splay)
-{
-  TreeList *curTL, *prevTL;
-  TreeChunk* retTC = NULL;
-  assert(size >= MIN_TREE_CHUNK_SIZE, "minimum chunk size");
-  if (FLSVerifyDictionary) {
-    verifyTree();
-  }
-  // starting at the root, work downwards trying to find match.
-  // Remember the last node of size too great or too small.
-  for (prevTL = curTL = root(); curTL != NULL;) {
-    if (curTL->size() == size) {        // exact match
-      break;
-    }
-    prevTL = curTL;
-    if (curTL->size() < size) {        // proceed to right sub-tree
-      curTL = curTL->right();
-    } else {                           // proceed to left sub-tree
-      assert(curTL->size() > size, "size inconsistency");
-      curTL = curTL->left();
-    }
-  }
-  if (curTL == NULL) { // couldn't find exact match
-    // try and find the next larger size by walking back up the search path
-    for (curTL = prevTL; curTL != NULL;) {
-      if (curTL->size() >= size) break;
-      else curTL = curTL->parent();
-    }
-    assert(curTL == NULL || curTL->count() > 0,
-      "An empty list should not be in the tree");
-  }
-  if (curTL != NULL) {
-    assert(curTL->size() >= size, "size inconsistency");
-    if (UseCMSAdaptiveFreeLists) {
-
-      // A candidate chunk has been found.  If it is already under
-      // populated, get a chunk associated with the hint for this
-      // chunk.
-      if (curTL->surplus() <= 0) {
-        /* Use the hint to find a size with a surplus, and reset the hint. */
-        TreeList* hintTL = curTL;
-        while (hintTL->hint() != 0) {
-          assert(hintTL->hint() == 0 || hintTL->hint() > hintTL->size(),
-            "hint points in the wrong direction");
-          hintTL = findList(hintTL->hint());
-          assert(curTL != hintTL, "Infinite loop");
-          if (hintTL == NULL ||
-              hintTL == curTL /* Should not happen but protect against it */ ) {
-            // No useful hint.  Set the hint to NULL and go on.
-            curTL->set_hint(0);
-            break;
-          }
-          assert(hintTL->size() > size, "hint is inconsistent");
-          if (hintTL->surplus() > 0) {
-            // The hint led to a list that has a surplus.  Use it.
-            // Set the hint for the candidate to an overpopulated
-            // size.
-            curTL->set_hint(hintTL->size());
-            // Change the candidate.
-            curTL = hintTL;
-            break;
-          }
-          // The evm code reset the hint of the candidate as
-          // at an interim point.  Why?  Seems like this leaves
-          // the hint pointing to a list that didn't work.
-          // curTL->set_hint(hintTL->size());
-        }
-      }
-    }
-    // don't waste time splaying if chunk's singleton
-    if (splay && curTL->head()->next() != NULL) {
-      semiSplayStep(curTL);
-    }
-    retTC = curTL->first_available();
-    assert((retTC != NULL) && (curTL->count() > 0),
-      "A list in the binary tree should not be NULL");
-    assert(retTC->size() >= size,
-      "A chunk of the wrong size was found");
-    removeChunkFromTree(retTC);
-    assert(retTC->isFree(), "Header is not marked correctly");
-  }
-
-  if (FLSVerifyDictionary) {
-    verify();
-  }
-  return retTC;
-}
-
-TreeList* BinaryTreeDictionary::findList(size_t size) const {
-  TreeList* curTL;
-  for (curTL = root(); curTL != NULL;) {
-    if (curTL->size() == size) {        // exact match
-      break;
-    }
-
-    if (curTL->size() < size) {        // proceed to right sub-tree
-      curTL = curTL->right();
-    } else {                           // proceed to left sub-tree
-      assert(curTL->size() > size, "size inconsistency");
-      curTL = curTL->left();
-    }
-  }
-  return curTL;
-}
-
-
-bool BinaryTreeDictionary::verifyChunkInFreeLists(FreeChunk* tc) const {
-  size_t size = tc->size();
-  TreeList* tl = findList(size);
-  if (tl == NULL) {
-    return false;
-  } else {
-    return tl->verifyChunkInFreeLists(tc);
-  }
-}
-
-FreeChunk* BinaryTreeDictionary::findLargestDict() const {
-  TreeList *curTL = root();
-  if (curTL != NULL) {
-    while(curTL->right() != NULL) curTL = curTL->right();
-    return curTL->largest_address();
-  } else {
-    return NULL;
-  }
-}
-
-// Remove the current chunk from the tree.  If it is not the last
-// chunk in a list on a tree node, just unlink it.
-// If it is the last chunk in the list (the next link is NULL),
-// remove the node and repair the tree.
-TreeChunk*
-BinaryTreeDictionary::removeChunkFromTree(TreeChunk* tc) {
-  assert(tc != NULL, "Should not call with a NULL chunk");
-  assert(tc->isFree(), "Header is not marked correctly");
-
-  TreeList *newTL, *parentTL;
-  TreeChunk* retTC;
-  TreeList* tl = tc->list();
-  debug_only(
-    bool removing_only_chunk = false;
-    if (tl == _root) {
-      if ((_root->left() == NULL) && (_root->right() == NULL)) {
-        if (_root->count() == 1) {
-          assert(_root->head() == tc, "Should only be this one chunk");
-          removing_only_chunk = true;
-        }
-      }
-    }
-  )
-  assert(tl != NULL, "List should be set");
-  assert(tl->parent() == NULL || tl == tl->parent()->left() ||
-         tl == tl->parent()->right(), "list is inconsistent");
-
-  bool complicatedSplice = false;
-
-  retTC = tc;
-  // Removing this chunk can have the side effect of changing the node
-  // (TreeList*) in the tree.  If the node is the root, update it.
-  TreeList* replacementTL = tl->removeChunkReplaceIfNeeded(tc);
-  assert(tc->isFree(), "Chunk should still be free");
-  assert(replacementTL->parent() == NULL ||
-         replacementTL == replacementTL->parent()->left() ||
-         replacementTL == replacementTL->parent()->right(),
-         "list is inconsistent");
-  if (tl == root()) {
-    assert(replacementTL->parent() == NULL, "Incorrectly replacing root");
-    set_root(replacementTL);
-  }
-  debug_only(
-    if (tl != replacementTL) {
-      assert(replacementTL->head() != NULL,
-        "If the tree list was replaced, it should not be a NULL list");
-      TreeList* rhl = replacementTL->head_as_TreeChunk()->list();
-      TreeList* rtl = TreeChunk::as_TreeChunk(replacementTL->tail())->list();
-      assert(rhl == replacementTL, "Broken head");
-      assert(rtl == replacementTL, "Broken tail");
-      assert(replacementTL->size() == tc->size(),  "Broken size");
-    }
-  )
-
-  // Does the tree need to be repaired?
-  if (replacementTL->count() == 0) {
-    assert(replacementTL->head() == NULL &&
-           replacementTL->tail() == NULL, "list count is incorrect");
-    // Find the replacement node for the (soon to be empty) node being removed.
-    // if we have a single (or no) child, splice child in our stead
-    if (replacementTL->left() == NULL) {
-      // left is NULL so pick right.  right may also be NULL.
-      newTL = replacementTL->right();
-      debug_only(replacementTL->clearRight();)
-    } else if (replacementTL->right() == NULL) {
-      // right is NULL
-      newTL = replacementTL->left();
-      debug_only(replacementTL->clearLeft();)
-    } else {  // we have both children, so, by patriarchal convention,
-              // my replacement is least node in right sub-tree
-      complicatedSplice = true;
-      newTL = removeTreeMinimum(replacementTL->right());
-      assert(newTL != NULL && newTL->left() == NULL &&
-             newTL->right() == NULL, "sub-tree minimum exists");
-    }
-    // newTL is the replacement for the (soon to be empty) node.
-    // newTL may be NULL.
-    // should verify; we just cleanly excised our replacement
-    if (FLSVerifyDictionary) {
-      verifyTree();
-    }
-    // first make newTL my parent's child
-    if ((parentTL = replacementTL->parent()) == NULL) {
-      // newTL should be root
-      assert(tl == root(), "Incorrectly replacing root");
-      set_root(newTL);
-      if (newTL != NULL) {
-        newTL->clearParent();
-      }
-    } else if (parentTL->right() == replacementTL) {
-      // replacementTL is a right child
-      parentTL->setRight(newTL);
-    } else {                                // replacementTL is a left child
-      assert(parentTL->left() == replacementTL, "should be left child");
-      parentTL->setLeft(newTL);
-    }
-    debug_only(replacementTL->clearParent();)
-    if (complicatedSplice) {  // we need newTL to get replacementTL's
-                              // two children
-      assert(newTL != NULL &&
-             newTL->left() == NULL && newTL->right() == NULL,
-            "newTL should not have encumbrances from the past");
-      // we'd like to assert as below:
-      // assert(replacementTL->left() != NULL && replacementTL->right() != NULL,
-      //       "else !complicatedSplice");
-      // ... however, the above assertion is too strong because we aren't
-      // guaranteed that replacementTL->right() is still NULL.
-      // Recall that we removed
-      // the right sub-tree minimum from replacementTL.
-      // That may well have been its right
-      // child! So we'll just assert half of the above:
-      assert(replacementTL->left() != NULL, "else !complicatedSplice");
-      newTL->setLeft(replacementTL->left());
-      newTL->setRight(replacementTL->right());
-      debug_only(
-        replacementTL->clearRight();
-        replacementTL->clearLeft();
-      )
-    }
-    assert(replacementTL->right() == NULL &&
-           replacementTL->left() == NULL &&
-           replacementTL->parent() == NULL,
-        "delete without encumbrances");
-  }
-
-  assert(totalSize() >= retTC->size(), "Incorrect total size");
-  dec_totalSize(retTC->size());     // size book-keeping
-  assert(totalFreeBlocks() > 0, "Incorrect total count");
-  set_totalFreeBlocks(totalFreeBlocks() - 1);
-
-  assert(retTC != NULL, "null chunk?");
-  assert(retTC->prev() == NULL && retTC->next() == NULL,
-         "should return without encumbrances");
-  if (FLSVerifyDictionary) {
-    verifyTree();
-  }
-  assert(!removing_only_chunk || _root == NULL, "root should be NULL");
-  return TreeChunk::as_TreeChunk(retTC);
-}
-
-// Remove the leftmost node (lm) in the tree and return it.
-// If lm has a right child, link it to the left node of
-// the parent of lm.
-TreeList* BinaryTreeDictionary::removeTreeMinimum(TreeList* tl) {
-  assert(tl != NULL && tl->parent() != NULL, "really need a proper sub-tree");
-  // locate the subtree minimum by walking down left branches
-  TreeList* curTL = tl;
-  for (; curTL->left() != NULL; curTL = curTL->left());
-  // obviously curTL now has at most one child, a right child
-  if (curTL != root()) {  // Should this test just be removed?
-    TreeList* parentTL = curTL->parent();
-    if (parentTL->left() == curTL) { // curTL is a left child
-      parentTL->setLeft(curTL->right());
-    } else {
-      // If the list tl has no left child, then curTL may be
-      // the right child of parentTL.
-      assert(parentTL->right() == curTL, "should be a right child");
-      parentTL->setRight(curTL->right());
-    }
-  } else {
-    // The only use of this method would not pass the root of the
-    // tree (as indicated by the assertion above that the tree list
-    // has a parent) but the specification does not explicitly exclude the
-    // passing of the root so accomodate it.
-    set_root(NULL);
-  }
-  debug_only(
-    curTL->clearParent();  // Test if this needs to be cleared
-    curTL->clearRight();    // recall, above, left child is already null
-  )
-  // we just excised a (non-root) node, we should still verify all tree invariants
-  if (FLSVerifyDictionary) {
-    verifyTree();
-  }
-  return curTL;
-}
-
-// Based on a simplification of the algorithm by Sleator and Tarjan (JACM 1985).
-// The simplifications are the following:
-// . we splay only when we delete (not when we insert)
-// . we apply a single spay step per deletion/access
-// By doing such partial splaying, we reduce the amount of restructuring,
-// while getting a reasonably efficient search tree (we think).
-// [Measurements will be needed to (in)validate this expectation.]
-
-void BinaryTreeDictionary::semiSplayStep(TreeList* tc) {
-  // apply a semi-splay step at the given node:
-  // . if root, norting needs to be done
-  // . if child of root, splay once
-  // . else zig-zig or sig-zag depending on path from grandparent
-  if (root() == tc) return;
-  warning("*** Splaying not yet implemented; "
-          "tree operations may be inefficient ***");
-}
-
-void BinaryTreeDictionary::insertChunkInTree(FreeChunk* fc) {
-  TreeList *curTL, *prevTL;
-  size_t size = fc->size();
-
-  assert(size >= MIN_TREE_CHUNK_SIZE, "too small to be a TreeList");
-  if (FLSVerifyDictionary) {
-    verifyTree();
-  }
-  // XXX: do i need to clear the FreeChunk fields, let me do it just in case
-  // Revisit this later
-
-  fc->clearNext();
-  fc->linkPrev(NULL);
-
-  // work down from the _root, looking for insertion point
-  for (prevTL = curTL = root(); curTL != NULL;) {
-    if (curTL->size() == size)  // exact match
-      break;
-    prevTL = curTL;
-    if (curTL->size() > size) { // follow left branch
-      curTL = curTL->left();
-    } else {                    // follow right branch
-      assert(curTL->size() < size, "size inconsistency");
-      curTL = curTL->right();
-    }
-  }
-  TreeChunk* tc = TreeChunk::as_TreeChunk(fc);
-  // This chunk is being returned to the binary tree.  Its embedded
-  // TreeList should be unused at this point.
-  tc->initialize();
-  if (curTL != NULL) {          // exact match
-    tc->set_list(curTL);
-    curTL->returnChunkAtTail(tc);
-  } else {                     // need a new node in tree
-    tc->clearNext();
-    tc->linkPrev(NULL);
-    TreeList* newTL = TreeList::as_TreeList(tc);
-    assert(((TreeChunk*)tc)->list() == newTL,
-      "List was not initialized correctly");
-    if (prevTL == NULL) {      // we are the only tree node
-      assert(root() == NULL, "control point invariant");
-      set_root(newTL);
-    } else {                   // insert under prevTL ...
-      if (prevTL->size() < size) {   // am right child
-        assert(prevTL->right() == NULL, "control point invariant");
-        prevTL->setRight(newTL);
-      } else {                       // am left child
-        assert(prevTL->size() > size && prevTL->left() == NULL, "cpt pt inv");
-        prevTL->setLeft(newTL);
-      }
-    }
-  }
-  assert(tc->list() != NULL, "Tree list should be set");
-
-  inc_totalSize(size);
-  // Method 'totalSizeInTree' walks through the every block in the
-  // tree, so it can cause significant performance loss if there are
-  // many blocks in the tree
-  assert(!FLSVerifyDictionary || totalSizeInTree(root()) == totalSize(), "_totalSize inconsistency");
-  set_totalFreeBlocks(totalFreeBlocks() + 1);
-  if (FLSVerifyDictionary) {
-    verifyTree();
-  }
-}
-
-size_t BinaryTreeDictionary::maxChunkSize() const {
-  verify_par_locked();
-  TreeList* tc = root();
-  if (tc == NULL) return 0;
-  for (; tc->right() != NULL; tc = tc->right());
-  return tc->size();
-}
-
-size_t BinaryTreeDictionary::totalListLength(TreeList* tl) const {
-  size_t res;
-  res = tl->count();
-#ifdef ASSERT
-  size_t cnt;
-  FreeChunk* tc = tl->head();
-  for (cnt = 0; tc != NULL; tc = tc->next(), cnt++);
-  assert(res == cnt, "The count is not being maintained correctly");
-#endif
-  return res;
-}
-
-size_t BinaryTreeDictionary::totalSizeInTree(TreeList* tl) const {
-  if (tl == NULL)
-    return 0;
-  return (tl->size() * totalListLength(tl)) +
-         totalSizeInTree(tl->left())    +
-         totalSizeInTree(tl->right());
-}
-
-double BinaryTreeDictionary::sum_of_squared_block_sizes(TreeList* const tl) const {
-  if (tl == NULL) {
-    return 0.0;
-  }
-  double size = (double)(tl->size());
-  double curr = size * size * totalListLength(tl);
-  curr += sum_of_squared_block_sizes(tl->left());
-  curr += sum_of_squared_block_sizes(tl->right());
-  return curr;
-}
-
-size_t BinaryTreeDictionary::totalFreeBlocksInTree(TreeList* tl) const {
-  if (tl == NULL)
-    return 0;
-  return totalListLength(tl) +
-         totalFreeBlocksInTree(tl->left()) +
-         totalFreeBlocksInTree(tl->right());
-}
-
-size_t BinaryTreeDictionary::numFreeBlocks() const {
-  assert(totalFreeBlocksInTree(root()) == totalFreeBlocks(),
-         "_totalFreeBlocks inconsistency");
-  return totalFreeBlocks();
-}
-
-size_t BinaryTreeDictionary::treeHeightHelper(TreeList* tl) const {
-  if (tl == NULL)
-    return 0;
-  return 1 + MAX2(treeHeightHelper(tl->left()),
-                  treeHeightHelper(tl->right()));
-}
-
-size_t BinaryTreeDictionary::treeHeight() const {
-  return treeHeightHelper(root());
-}
-
-size_t BinaryTreeDictionary::totalNodesHelper(TreeList* tl) const {
-  if (tl == NULL) {
-    return 0;
-  }
-  return 1 + totalNodesHelper(tl->left()) +
-    totalNodesHelper(tl->right());
-}
-
-size_t BinaryTreeDictionary::totalNodesInTree(TreeList* tl) const {
-  return totalNodesHelper(root());
-}
-
-void BinaryTreeDictionary::dictCensusUpdate(size_t size, bool split, bool birth){
-  TreeList* nd = findList(size);
-  if (nd) {
-    if (split) {
-      if (birth) {
-        nd->increment_splitBirths();
-        nd->increment_surplus();
-      }  else {
-        nd->increment_splitDeaths();
-        nd->decrement_surplus();
-      }
-    } else {
-      if (birth) {
-        nd->increment_coalBirths();
-        nd->increment_surplus();
-      } else {
-        nd->increment_coalDeaths();
-        nd->decrement_surplus();
-      }
-    }
-  }
-  // A list for this size may not be found (nd == 0) if
-  //   This is a death where the appropriate list is now
-  //     empty and has been removed from the list.
-  //   This is a birth associated with a LinAB.  The chunk
-  //     for the LinAB is not in the dictionary.
-}
-
-bool BinaryTreeDictionary::coalDictOverPopulated(size_t size) {
-  if (FLSAlwaysCoalesceLarge) return true;
-
-  TreeList* list_of_size = findList(size);
-  // None of requested size implies overpopulated.
-  return list_of_size == NULL || list_of_size->coalDesired() <= 0 ||
-         list_of_size->count() > list_of_size->coalDesired();
-}
-
-// Closures for walking the binary tree.
-//   do_list() walks the free list in a node applying the closure
-//     to each free chunk in the list
-//   do_tree() walks the nodes in the binary tree applying do_list()
-//     to each list at each node.
-
-class TreeCensusClosure : public StackObj {
- protected:
-  virtual void do_list(FreeList* fl) = 0;
- public:
-  virtual void do_tree(TreeList* tl) = 0;
-};
-
-class AscendTreeCensusClosure : public TreeCensusClosure {
- public:
-  void do_tree(TreeList* tl) {
-    if (tl != NULL) {
-      do_tree(tl->left());
-      do_list(tl);
-      do_tree(tl->right());
-    }
-  }
-};
-
-class DescendTreeCensusClosure : public TreeCensusClosure {
- public:
-  void do_tree(TreeList* tl) {
-    if (tl != NULL) {
-      do_tree(tl->right());
-      do_list(tl);
-      do_tree(tl->left());
-    }
-  }
-};
-
-// For each list in the tree, calculate the desired, desired
-// coalesce, count before sweep, and surplus before sweep.
-class BeginSweepClosure : public AscendTreeCensusClosure {
-  double _percentage;
-  float _inter_sweep_current;
-  float _inter_sweep_estimate;
-  float _intra_sweep_estimate;
-
- public:
-  BeginSweepClosure(double p, float inter_sweep_current,
-                              float inter_sweep_estimate,
-                              float intra_sweep_estimate) :
-   _percentage(p),
-   _inter_sweep_current(inter_sweep_current),
-   _inter_sweep_estimate(inter_sweep_estimate),
-   _intra_sweep_estimate(intra_sweep_estimate) { }
-
-  void do_list(FreeList* fl) {
-    double coalSurplusPercent = _percentage;
-    fl->compute_desired(_inter_sweep_current, _inter_sweep_estimate, _intra_sweep_estimate);
-    fl->set_coalDesired((ssize_t)((double)fl->desired() * coalSurplusPercent));
-    fl->set_beforeSweep(fl->count());
-    fl->set_bfrSurp(fl->surplus());
-  }
-};
-
-// Used to search the tree until a condition is met.
-// Similar to TreeCensusClosure but searches the
-// tree and returns promptly when found.
-
-class TreeSearchClosure : public StackObj {
- protected:
-  virtual bool do_list(FreeList* fl) = 0;
- public:
-  virtual bool do_tree(TreeList* tl) = 0;
-};
-
-#if 0 //  Don't need this yet but here for symmetry.
-class AscendTreeSearchClosure : public TreeSearchClosure {
- public:
-  bool do_tree(TreeList* tl) {
-    if (tl != NULL) {
-      if (do_tree(tl->left())) return true;
-      if (do_list(tl)) return true;
-      if (do_tree(tl->right())) return true;
-    }
-    return false;
-  }
-};
-#endif
-
-class DescendTreeSearchClosure : public TreeSearchClosure {
- public:
-  bool do_tree(TreeList* tl) {
-    if (tl != NULL) {
-      if (do_tree(tl->right())) return true;
-      if (do_list(tl)) return true;
-      if (do_tree(tl->left())) return true;
-    }
-    return false;
-  }
-};
-
-// Searches the tree for a chunk that ends at the
-// specified address.
-class EndTreeSearchClosure : public DescendTreeSearchClosure {
-  HeapWord* _target;
-  FreeChunk* _found;
-
- public:
-  EndTreeSearchClosure(HeapWord* target) : _target(target), _found(NULL) {}
-  bool do_list(FreeList* fl) {
-    FreeChunk* item = fl->head();
-    while (item != NULL) {
-      if (item->end() == _target) {
-        _found = item;
-        return true;
-      }
-      item = item->next();
-    }
-    return false;
-  }
-  FreeChunk* found() { return _found; }
-};
-
-FreeChunk* BinaryTreeDictionary::find_chunk_ends_at(HeapWord* target) const {
-  EndTreeSearchClosure etsc(target);
-  bool found_target = etsc.do_tree(root());
-  assert(found_target || etsc.found() == NULL, "Consistency check");
-  assert(!found_target || etsc.found() != NULL, "Consistency check");
-  return etsc.found();
-}
-
-void BinaryTreeDictionary::beginSweepDictCensus(double coalSurplusPercent,
-  float inter_sweep_current, float inter_sweep_estimate, float intra_sweep_estimate) {
-  BeginSweepClosure bsc(coalSurplusPercent, inter_sweep_current,
-                                            inter_sweep_estimate,
-                                            intra_sweep_estimate);
-  bsc.do_tree(root());
-}
-
-// Closures and methods for calculating total bytes returned to the
-// free lists in the tree.
-NOT_PRODUCT(
-  class InitializeDictReturnedBytesClosure : public AscendTreeCensusClosure {
-   public:
-    void do_list(FreeList* fl) {
-      fl->set_returnedBytes(0);
-    }
-  };
-
-  void BinaryTreeDictionary::initializeDictReturnedBytes() {
-    InitializeDictReturnedBytesClosure idrb;
-    idrb.do_tree(root());
-  }
-
-  class ReturnedBytesClosure : public AscendTreeCensusClosure {
-    size_t _dictReturnedBytes;
-   public:
-    ReturnedBytesClosure() { _dictReturnedBytes = 0; }
-    void do_list(FreeList* fl) {
-      _dictReturnedBytes += fl->returnedBytes();
-    }
-    size_t dictReturnedBytes() { return _dictReturnedBytes; }
-  };
-
-  size_t BinaryTreeDictionary::sumDictReturnedBytes() {
-    ReturnedBytesClosure rbc;
-    rbc.do_tree(root());
-
-    return rbc.dictReturnedBytes();
-  }
-
-  // Count the number of entries in the tree.
-  class treeCountClosure : public DescendTreeCensusClosure {
-   public:
-    uint count;
-    treeCountClosure(uint c) { count = c; }
-    void do_list(FreeList* fl) {
-      count++;
-    }
-  };
-
-  size_t BinaryTreeDictionary::totalCount() {
-    treeCountClosure ctc(0);
-    ctc.do_tree(root());
-    return ctc.count;
-  }
-)
-
-// Calculate surpluses for the lists in the tree.
-class setTreeSurplusClosure : public AscendTreeCensusClosure {
-  double percentage;
- public:
-  setTreeSurplusClosure(double v) { percentage = v; }
-  void do_list(FreeList* fl) {
-    double splitSurplusPercent = percentage;
-    fl->set_surplus(fl->count() -
-                   (ssize_t)((double)fl->desired() * splitSurplusPercent));
-  }
-};
-
-void BinaryTreeDictionary::setTreeSurplus(double splitSurplusPercent) {
-  setTreeSurplusClosure sts(splitSurplusPercent);
-  sts.do_tree(root());
-}
-
-// Set hints for the lists in the tree.
-class setTreeHintsClosure : public DescendTreeCensusClosure {
-  size_t hint;
- public:
-  setTreeHintsClosure(size_t v) { hint = v; }
-  void do_list(FreeList* fl) {
-    fl->set_hint(hint);
-    assert(fl->hint() == 0 || fl->hint() > fl->size(),
-      "Current hint is inconsistent");
-    if (fl->surplus() > 0) {
-      hint = fl->size();
-    }
-  }
-};
-
-void BinaryTreeDictionary::setTreeHints(void) {
-  setTreeHintsClosure sth(0);
-  sth.do_tree(root());
-}
-
-// Save count before previous sweep and splits and coalesces.
-class clearTreeCensusClosure : public AscendTreeCensusClosure {
-  void do_list(FreeList* fl) {
-    fl->set_prevSweep(fl->count());
-    fl->set_coalBirths(0);
-    fl->set_coalDeaths(0);
-    fl->set_splitBirths(0);
-    fl->set_splitDeaths(0);
-  }
-};
-
-void BinaryTreeDictionary::clearTreeCensus(void) {
-  clearTreeCensusClosure ctc;
-  ctc.do_tree(root());
-}
-
-// Do reporting and post sweep clean up.
-void BinaryTreeDictionary::endSweepDictCensus(double splitSurplusPercent) {
-  // Does walking the tree 3 times hurt?
-  setTreeSurplus(splitSurplusPercent);
-  setTreeHints();
-  if (PrintGC && Verbose) {
-    reportStatistics();
-  }
-  clearTreeCensus();
-}
-
-// Print summary statistics
-void BinaryTreeDictionary::reportStatistics() const {
-  verify_par_locked();
-  gclog_or_tty->print("Statistics for BinaryTreeDictionary:\n"
-         "------------------------------------\n");
-  size_t totalSize = totalChunkSize(debug_only(NULL));
-  size_t    freeBlocks = numFreeBlocks();
-  gclog_or_tty->print("Total Free Space: %d\n", totalSize);
-  gclog_or_tty->print("Max   Chunk Size: %d\n", maxChunkSize());
-  gclog_or_tty->print("Number of Blocks: %d\n", freeBlocks);
-  if (freeBlocks > 0) {
-    gclog_or_tty->print("Av.  Block  Size: %d\n", totalSize/freeBlocks);
-  }
-  gclog_or_tty->print("Tree      Height: %d\n", treeHeight());
-}
-
-// Print census information - counts, births, deaths, etc.
-// for each list in the tree.  Also print some summary
-// information.
-class PrintTreeCensusClosure : public AscendTreeCensusClosure {
-  int _print_line;
-  size_t _totalFree;
-  FreeList _total;
-
- public:
-  PrintTreeCensusClosure() {
-    _print_line = 0;
-    _totalFree = 0;
-  }
-  FreeList* total() { return &_total; }
-  size_t totalFree() { return _totalFree; }
-  void do_list(FreeList* fl) {
-    if (++_print_line >= 40) {
-      FreeList::print_labels_on(gclog_or_tty, "size");
-      _print_line = 0;
-    }
-    fl->print_on(gclog_or_tty);
-    _totalFree +=            fl->count()            * fl->size()        ;
-    total()->set_count(      total()->count()       + fl->count()      );
-    total()->set_bfrSurp(    total()->bfrSurp()     + fl->bfrSurp()    );
-    total()->set_surplus(    total()->splitDeaths() + fl->surplus()    );
-    total()->set_desired(    total()->desired()     + fl->desired()    );
-    total()->set_prevSweep(  total()->prevSweep()   + fl->prevSweep()  );
-    total()->set_beforeSweep(total()->beforeSweep() + fl->beforeSweep());
-    total()->set_coalBirths( total()->coalBirths()  + fl->coalBirths() );
-    total()->set_coalDeaths( total()->coalDeaths()  + fl->coalDeaths() );
-    total()->set_splitBirths(total()->splitBirths() + fl->splitBirths());
-    total()->set_splitDeaths(total()->splitDeaths() + fl->splitDeaths());
-  }
-};
-
-void BinaryTreeDictionary::printDictCensus(void) const {
-
-  gclog_or_tty->print("\nBinaryTree\n");
-  FreeList::print_labels_on(gclog_or_tty, "size");
-  PrintTreeCensusClosure ptc;
-  ptc.do_tree(root());
-
-  FreeList* total = ptc.total();
-  FreeList::print_labels_on(gclog_or_tty, " ");
-  total->print_on(gclog_or_tty, "TOTAL\t");
-  gclog_or_tty->print(
-              "totalFree(words): " SIZE_FORMAT_W(16)
-              " growth: %8.5f  deficit: %8.5f\n",
-              ptc.totalFree(),
-              (double)(total->splitBirths() + total->coalBirths()
-                     - total->splitDeaths() - total->coalDeaths())
-              /(total->prevSweep() != 0 ? (double)total->prevSweep() : 1.0),
-             (double)(total->desired() - total->count())
-             /(total->desired() != 0 ? (double)total->desired() : 1.0));
-}
-
-class PrintFreeListsClosure : public AscendTreeCensusClosure {
-  outputStream* _st;
-  int _print_line;
-
- public:
-  PrintFreeListsClosure(outputStream* st) {
-    _st = st;
-    _print_line = 0;
-  }
-  void do_list(FreeList* fl) {
-    if (++_print_line >= 40) {
-      FreeList::print_labels_on(_st, "size");
-      _print_line = 0;
-    }
-    fl->print_on(gclog_or_tty);
-    size_t sz = fl->size();
-    for (FreeChunk* fc = fl->head(); fc != NULL;
-         fc = fc->next()) {
-      _st->print_cr("\t[" PTR_FORMAT "," PTR_FORMAT ")  %s",
-                    fc, (HeapWord*)fc + sz,
-                    fc->cantCoalesce() ? "\t CC" : "");
-    }
-  }
-};
-
-void BinaryTreeDictionary::print_free_lists(outputStream* st) const {
-
-  FreeList::print_labels_on(st, "size");
-  PrintFreeListsClosure pflc(st);
-  pflc.do_tree(root());
-}
-
-// Verify the following tree invariants:
-// . _root has no parent
-// . parent and child point to each other
-// . each node's key correctly related to that of its child(ren)
-void BinaryTreeDictionary::verifyTree() const {
-  guarantee(root() == NULL || totalFreeBlocks() == 0 ||
-    totalSize() != 0, "_totalSize should't be 0?");
-  guarantee(root() == NULL || root()->parent() == NULL, "_root shouldn't have parent");
-  verifyTreeHelper(root());
-}
-
-size_t BinaryTreeDictionary::verifyPrevFreePtrs(TreeList* tl) {
-  size_t ct = 0;
-  for (FreeChunk* curFC = tl->head(); curFC != NULL; curFC = curFC->next()) {
-    ct++;
-    assert(curFC->prev() == NULL || curFC->prev()->isFree(),
-      "Chunk should be free");
-  }
-  return ct;
-}
-
-// Note: this helper is recursive rather than iterative, so use with
-// caution on very deep trees; and watch out for stack overflow errors;
-// In general, to be used only for debugging.
-void BinaryTreeDictionary::verifyTreeHelper(TreeList* tl) const {
-  if (tl == NULL)
-    return;
-  guarantee(tl->size() != 0, "A list must has a size");
-  guarantee(tl->left()  == NULL || tl->left()->parent()  == tl,
-         "parent<-/->left");
-  guarantee(tl->right() == NULL || tl->right()->parent() == tl,
-         "parent<-/->right");;
-  guarantee(tl->left() == NULL  || tl->left()->size()    <  tl->size(),
-         "parent !> left");
-  guarantee(tl->right() == NULL || tl->right()->size()   >  tl->size(),
-         "parent !< left");
-  guarantee(tl->head() == NULL || tl->head()->isFree(), "!Free");
-  guarantee(tl->head() == NULL || tl->head_as_TreeChunk()->list() == tl,
-    "list inconsistency");
-  guarantee(tl->count() > 0 || (tl->head() == NULL && tl->tail() == NULL),
-    "list count is inconsistent");
-  guarantee(tl->count() > 1 || tl->head() == tl->tail(),
-    "list is incorrectly constructed");
-  size_t count = verifyPrevFreePtrs(tl);
-  guarantee(count == (size_t)tl->count(), "Node count is incorrect");
-  if (tl->head() != NULL) {
-    tl->head_as_TreeChunk()->verifyTreeChunkList();
-  }
-  verifyTreeHelper(tl->left());
-  verifyTreeHelper(tl->right());
-}
-
-void BinaryTreeDictionary::verify() const {
-  verifyTree();
-  guarantee(totalSize() == totalSizeInTree(root()), "Total Size inconsistency");
-}
--- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/binaryTreeDictionary.hpp	Wed Jul 05 18:09:43 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,296 +0,0 @@
-/*
- * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-
-#ifndef SHARE_VM_GC_IMPLEMENTATION_CONCURRENTMARKSWEEP_BINARYTREEDICTIONARY_HPP
-#define SHARE_VM_GC_IMPLEMENTATION_CONCURRENTMARKSWEEP_BINARYTREEDICTIONARY_HPP
-
-#include "gc_implementation/concurrentMarkSweep/freeBlockDictionary.hpp"
-#include "gc_implementation/concurrentMarkSweep/freeList.hpp"
-
-/*
- * A binary tree based search structure for free blocks.
- * This is currently used in the Concurrent Mark&Sweep implementation.
- */
-
-// A TreeList is a FreeList which can be used to maintain a
-// binary tree of free lists.
-
-class TreeChunk;
-class BinaryTreeDictionary;
-class AscendTreeCensusClosure;
-class DescendTreeCensusClosure;
-class DescendTreeSearchClosure;
-
-class TreeList: public FreeList {
-  friend class TreeChunk;
-  friend class BinaryTreeDictionary;
-  friend class AscendTreeCensusClosure;
-  friend class DescendTreeCensusClosure;
-  friend class DescendTreeSearchClosure;
-
- protected:
-  TreeList* parent() const { return _parent; }
-  TreeList* left()   const { return _left;   }
-  TreeList* right()  const { return _right;  }
-
-  // Accessors for links in tree.
-
-  void setLeft(TreeList* tl) {
-    _left   = tl;
-    if (tl != NULL)
-      tl->setParent(this);
-  }
-  void setRight(TreeList* tl) {
-    _right  = tl;
-    if (tl != NULL)
-      tl->setParent(this);
-  }
-  void setParent(TreeList* tl)  { _parent = tl;   }
-
-  void clearLeft()               { _left = NULL;   }
-  void clearRight()              { _right = NULL;  }
-  void clearParent()             { _parent = NULL; }
-  void initialize()              { clearLeft(); clearRight(), clearParent(); }
-
-  // For constructing a TreeList from a Tree chunk or
-  // address and size.
-  static TreeList* as_TreeList(TreeChunk* tc);
-  static TreeList* as_TreeList(HeapWord* addr, size_t size);
-
-  // Returns the head of the free list as a pointer to a TreeChunk.
-  TreeChunk* head_as_TreeChunk();
-
-  // Returns the first available chunk in the free list as a pointer
-  // to a TreeChunk.
-  TreeChunk* first_available();
-
-  // Returns the block with the largest heap address amongst
-  // those in the list for this size; potentially slow and expensive,
-  // use with caution!
-  TreeChunk* largest_address();
-
-  // removeChunkReplaceIfNeeded() removes the given "tc" from the TreeList.
-  // If "tc" is the first chunk in the list, it is also the
-  // TreeList that is the node in the tree.  removeChunkReplaceIfNeeded()
-  // returns the possibly replaced TreeList* for the node in
-  // the tree.  It also updates the parent of the original
-  // node to point to the new node.
-  TreeList* removeChunkReplaceIfNeeded(TreeChunk* tc);
-  // See FreeList.
-  void returnChunkAtHead(TreeChunk* tc);
-  void returnChunkAtTail(TreeChunk* tc);
-};
-
-// A TreeChunk is a subclass of a FreeChunk that additionally
-// maintains a pointer to the free list on which it is currently
-// linked.
-// A TreeChunk is also used as a node in the binary tree.  This
-// allows the binary tree to be maintained without any additional
-// storage (the free chunks are used).  In a binary tree the first
-// chunk in the free list is also the tree node.  Note that the
-// TreeChunk has an embedded TreeList for this purpose.  Because
-// the first chunk in the list is distinguished in this fashion
-// (also is the node in the tree), it is the last chunk to be found
-// on the free list for a node in the tree and is only removed if
-// it is the last chunk on the free list.
-
-class TreeChunk : public FreeChunk {
-  friend class TreeList;
-  TreeList* _list;
-  TreeList _embedded_list;  // if non-null, this chunk is on _list
- protected:
-  TreeList* embedded_list() const { return (TreeList*) &_embedded_list; }
-  void set_embedded_list(TreeList* v) { _embedded_list = *v; }
- public:
-  TreeList* list() { return _list; }
-  void set_list(TreeList* v) { _list = v; }
-  static TreeChunk* as_TreeChunk(FreeChunk* fc);
-  // Initialize fields in a TreeChunk that should be
-  // initialized when the TreeChunk is being added to
-  // a free list in the tree.
-  void initialize() { embedded_list()->initialize(); }
-
-  // debugging
-  void verifyTreeChunkList() const;
-};
-
-const size_t MIN_TREE_CHUNK_SIZE  = sizeof(TreeChunk)/HeapWordSize;
-
-class BinaryTreeDictionary: public FreeBlockDictionary {
-  friend class VMStructs;
-  bool       _splay;
-  size_t     _totalSize;
-  size_t     _totalFreeBlocks;
-  TreeList* _root;
-
-  // private accessors
-  bool splay() const { return _splay; }
-  void set_splay(bool v) { _splay = v; }
-  size_t totalSize() const { return _totalSize; }
-  void set_totalSize(size_t v) { _totalSize = v; }
-  virtual void inc_totalSize(size_t v);
-  virtual void dec_totalSize(size_t v);
-  size_t totalFreeBlocks() const { return _totalFreeBlocks; }
-  void set_totalFreeBlocks(size_t v) { _totalFreeBlocks = v; }
-  TreeList* root() const { return _root; }
-  void set_root(TreeList* v) { _root = v; }
-
-  // Remove a chunk of size "size" or larger from the tree and
-  // return it.  If the chunk
-  // is the last chunk of that size, remove the node for that size
-  // from the tree.
-  TreeChunk* getChunkFromTree(size_t size, Dither dither, bool splay);
-  // Return a list of the specified size or NULL from the tree.
-  // The list is not removed from the tree.
-  TreeList* findList (size_t size) const;
-  // Remove this chunk from the tree.  If the removal results
-  // in an empty list in the tree, remove the empty list.
-  TreeChunk* removeChunkFromTree(TreeChunk* tc);
-  // Remove the node in the trees starting at tl that has the
-  // minimum value and return it.  Repair the tree as needed.
-  TreeList* removeTreeMinimum(TreeList* tl);
-  void       semiSplayStep(TreeList* tl);
-  // Add this free chunk to the tree.
-  void       insertChunkInTree(FreeChunk* freeChunk);
- public:
-  void       verifyTree() const;
-  // verify that the given chunk is in the tree.
-  bool       verifyChunkInFreeLists(FreeChunk* tc) const;
- private:
-  void          verifyTreeHelper(TreeList* tl) const;
-  static size_t verifyPrevFreePtrs(TreeList* tl);
-
-  // Returns the total number of chunks in the list.
-  size_t     totalListLength(TreeList* tl) const;
-  // Returns the total number of words in the chunks in the tree
-  // starting at "tl".
-  size_t     totalSizeInTree(TreeList* tl) const;
-  // Returns the sum of the square of the size of each block
-  // in the tree starting at "tl".
-  double     sum_of_squared_block_sizes(TreeList* const tl) const;
-  // Returns the total number of free blocks in the tree starting
-  // at "tl".
-  size_t     totalFreeBlocksInTree(TreeList* tl) const;
-  size_t     numFreeBlocks() const;
-  size_t     treeHeight() const;
-  size_t     treeHeightHelper(TreeList* tl) const;
-  size_t     totalNodesInTree(TreeList* tl) const;
-  size_t     totalNodesHelper(TreeList* tl) const;
-
- public:
-  // Constructor
-  BinaryTreeDictionary(MemRegion mr, bool splay = false);
-
-  // Reset the dictionary to the initial conditions with
-  // a single free chunk.
-  void       reset(MemRegion mr);
-  void       reset(HeapWord* addr, size_t size);
-  // Reset the dictionary to be empty.
-  void       reset();
-
-  // Return a chunk of size "size" or greater from
-  // the tree.
-  // want a better dynamic splay strategy for the future.
-  FreeChunk* getChunk(size_t size, Dither dither) {
-    verify_par_locked();
-    FreeChunk* res = getChunkFromTree(size, dither, splay());
-    assert(res == NULL || res->isFree(),
-           "Should be returning a free chunk");
-    return res;
-  }
-
-  void returnChunk(FreeChunk* chunk) {
-    verify_par_locked();
-    insertChunkInTree(chunk);
-  }
-
-  void removeChunk(FreeChunk* chunk) {
-    verify_par_locked();
-    removeChunkFromTree((TreeChunk*)chunk);
-    assert(chunk->isFree(), "Should still be a free chunk");
-  }
-
-  size_t     maxChunkSize() const;
-  size_t     totalChunkSize(debug_only(const Mutex* lock)) const {
-    debug_only(
-      if (lock != NULL && lock->owned_by_self()) {
-        assert(totalSizeInTree(root()) == totalSize(),
-               "_totalSize inconsistency");
-      }
-    )
-    return totalSize();
-  }
-
-  size_t     minSize() const {
-    return MIN_TREE_CHUNK_SIZE;
-  }
-
-  double     sum_of_squared_block_sizes() const {
-    return sum_of_squared_block_sizes(root());
-  }
-
-  FreeChunk* find_chunk_ends_at(HeapWord* target) const;
-
-  // Find the list with size "size" in the binary tree and update
-  // the statistics in the list according to "split" (chunk was
-  // split or coalesce) and "birth" (chunk was added or removed).
-  void       dictCensusUpdate(size_t size, bool split, bool birth);
-  // Return true if the dictionary is overpopulated (more chunks of
-  // this size than desired) for size "size".
-  bool       coalDictOverPopulated(size_t size);
-  // Methods called at the beginning of a sweep to prepare the
-  // statistics for the sweep.
-  void       beginSweepDictCensus(double coalSurplusPercent,
-                                  float inter_sweep_current,
-                                  float inter_sweep_estimate,
-                                  float intra_sweep_estimate);
-  // Methods called after the end of a sweep to modify the
-  // statistics for the sweep.
-  void       endSweepDictCensus(double splitSurplusPercent);
-  // Return the largest free chunk in the tree.
-  FreeChunk* findLargestDict() const;
-  // Accessors for statistics
-  void       setTreeSurplus(double splitSurplusPercent);
-  void       setTreeHints(void);
-  // Reset statistics for all the lists in the tree.
-  void       clearTreeCensus(void);
-  // Print the statistcis for all the lists in the tree.  Also may
-  // print out summaries.
-  void       printDictCensus(void) const;
-  void       print_free_lists(outputStream* st) const;
-
-  // For debugging.  Returns the sum of the _returnedBytes for
-  // all lists in the tree.
-  size_t     sumDictReturnedBytes()     PRODUCT_RETURN0;
-  // Sets the _returnedBytes for all the lists in the tree to zero.
-  void       initializeDictReturnedBytes()      PRODUCT_RETURN;
-  // For debugging.  Return the total number of chunks in the dictionary.
-  size_t     totalCount()       PRODUCT_RETURN0;
-
-  void       reportStatistics() const;
-
-  void       verify() const;
-};
-
-#endif // SHARE_VM_GC_IMPLEMENTATION_CONCURRENTMARKSWEEP_BINARYTREEDICTIONARY_HPP
--- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/cmsPermGen.cpp	Wed Jul 05 18:09:43 2017 +0200
+++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/cmsPermGen.cpp	Wed Jul 05 18:10:27 2017 +0200
@@ -38,7 +38,7 @@
 
 CMSPermGen::CMSPermGen(ReservedSpace rs, size_t initial_byte_size,
              CardTableRS* ct,
-             FreeBlockDictionary::DictionaryChoice dictionaryChoice) {
+             FreeBlockDictionary<FreeChunk>::DictionaryChoice dictionaryChoice) {
   CMSPermGenGen* g =
     new CMSPermGenGen(rs, initial_byte_size, -1, ct);
   if (g == NULL) {
--- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/cmsPermGen.hpp	Wed Jul 05 18:09:43 2017 +0200
+++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/cmsPermGen.hpp	Wed Jul 05 18:10:27 2017 +0200
@@ -45,7 +45,7 @@
 
  public:
   CMSPermGen(ReservedSpace rs, size_t initial_byte_size,
-             CardTableRS* ct, FreeBlockDictionary::DictionaryChoice);
+             CardTableRS* ct, FreeBlockDictionary<FreeChunk>::DictionaryChoice);
 
   HeapWord* mem_allocate(size_t size);
 
@@ -65,7 +65,7 @@
     // regarding not using adaptive free lists for a perm gen.
     ConcurrentMarkSweepGeneration(rs, initial_byte_size, // MinPermHeapExapnsion
       level, ct, false /* use adaptive freelists */,
-      (FreeBlockDictionary::DictionaryChoice)CMSDictionaryChoice)
+      (FreeBlockDictionary<FreeChunk>::DictionaryChoice)CMSDictionaryChoice)
   {}
 
   void initialize_performance_counters();
--- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.cpp	Wed Jul 05 18:09:43 2017 +0200
+++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.cpp	Wed Jul 05 18:10:27 2017 +0200
@@ -69,7 +69,7 @@
 // Constructor
 CompactibleFreeListSpace::CompactibleFreeListSpace(BlockOffsetSharedArray* bs,
   MemRegion mr, bool use_adaptive_freelists,
-  FreeBlockDictionary::DictionaryChoice dictionaryChoice) :
+  FreeBlockDictionary<FreeChunk>::DictionaryChoice dictionaryChoice) :
   _dictionaryChoice(dictionaryChoice),
   _adaptive_freelists(use_adaptive_freelists),
   _bt(bs, mr),
@@ -87,6 +87,8 @@
                     CMSConcMarkMultiple),
   _collector(NULL)
 {
+  assert(sizeof(FreeChunk) / BytesPerWord <= MinChunkSize,
+    "FreeChunk is larger than expected");
   _bt.set_space(this);
   initialize(mr, SpaceDecorator::Clear, SpaceDecorator::Mangle);
   // We have all of "mr", all of which we place in the dictionary
@@ -96,13 +98,13 @@
   // implementation, namely, the simple binary tree (splaying
   // temporarily disabled).
   switch (dictionaryChoice) {
-    case FreeBlockDictionary::dictionarySplayTree:
-    case FreeBlockDictionary::dictionarySkipList:
+    case FreeBlockDictionary<FreeChunk>::dictionarySplayTree:
+    case FreeBlockDictionary<FreeChunk>::dictionarySkipList:
     default:
       warning("dictionaryChoice: selected option not understood; using"
               " default BinaryTreeDictionary implementation instead.");
-    case FreeBlockDictionary::dictionaryBinaryTree:
-      _dictionary = new BinaryTreeDictionary(mr);
+    case FreeBlockDictionary<FreeChunk>::dictionaryBinaryTree:
+      _dictionary = new BinaryTreeDictionary<FreeChunk>(mr, use_adaptive_freelists);
       break;
   }
   assert(_dictionary != NULL, "CMS dictionary initialization");
@@ -117,7 +119,7 @@
   // moved to its new location before the klass is moved.
   // Set the _refillSize for the linear allocation blocks
   if (!use_adaptive_freelists) {
-    FreeChunk* fc = _dictionary->getChunk(mr.word_size());
+    FreeChunk* fc = _dictionary->get_chunk(mr.word_size());
     // The small linAB initially has all the space and will allocate
     // a chunk of any size.
     HeapWord* addr = (HeapWord*) fc;
@@ -273,12 +275,12 @@
     assert(mr.word_size() >= MinChunkSize, "Chunk size is too small");
     _bt.single_block(mr.start(), mr.word_size());
     FreeChunk* fc = (FreeChunk*) mr.start();
-    fc->setSize(mr.word_size());
+    fc->set_size(mr.word_size());
     if (mr.word_size() >= IndexSetSize ) {
       returnChunkToDictionary(fc);
     } else {
       _bt.verify_not_unallocated((HeapWord*)fc, fc->size());
-      _indexedFreeList[mr.word_size()].returnChunkAtHead(fc);
+      _indexedFreeList[mr.word_size()].return_chunk_at_head(fc);
     }
   }
   _promoInfo.reset();
@@ -296,7 +298,7 @@
   } else {
     // Place as much of mr in the linAB as we can get,
     // provided it was big enough to go into the dictionary.
-    FreeChunk* fc = dictionary()->findLargestDict();
+    FreeChunk* fc = dictionary()->find_largest_dict();
     if (fc != NULL) {
       assert(fc->size() == mr.word_size(),
              "Why was the chunk broken up?");
@@ -323,14 +325,14 @@
 #ifndef PRODUCT
 void CompactibleFreeListSpace::initializeIndexedFreeListArrayReturnedBytes() {
   for (size_t i = IndexSetStart; i < IndexSetSize; i += IndexSetStride) {
-    _indexedFreeList[i].allocation_stats()->set_returnedBytes(0);
+    _indexedFreeList[i].allocation_stats()->set_returned_bytes(0);
   }
 }
 
 size_t CompactibleFreeListSpace::sumIndexedFreeListArrayReturnedBytes() {
   size_t sum = 0;
   for (size_t i = IndexSetStart; i < IndexSetSize; i += IndexSetStride) {
-    sum += _indexedFreeList[i].allocation_stats()->returnedBytes();
+    sum += _indexedFreeList[i].allocation_stats()->returned_bytes();
   }
   return sum;
 }
@@ -354,7 +356,7 @@
 
 size_t CompactibleFreeListSpace::totalCount() {
   size_t num = totalCountInIndexedFreeLists();
-  num +=  dictionary()->totalCount();
+  num +=  dictionary()->total_count();
   if (_smallLinearAllocBlock._word_size != 0) {
     num++;
   }
@@ -364,7 +366,7 @@
 
 bool CompactibleFreeListSpace::is_free_block(const HeapWord* p) const {
   FreeChunk* fc = (FreeChunk*) p;
-  return fc->isFree();
+  return fc->is_free();
 }
 
 size_t CompactibleFreeListSpace::used() const {
@@ -391,7 +393,7 @@
   // that supports jvmstat, and you are apt to see the values
   // flicker in such cases.
   assert(_dictionary != NULL, "No _dictionary?");
-  return (_dictionary->totalChunkSize(DEBUG_ONLY(freelistLock())) +
+  return (_dictionary->total_chunk_size(DEBUG_ONLY(freelistLock())) +
           totalSizeInIndexedFreeLists() +
           _smallLinearAllocBlock._word_size) * HeapWordSize;
 }
@@ -399,7 +401,7 @@
 size_t CompactibleFreeListSpace::max_alloc_in_words() const {
   assert(_dictionary != NULL, "No _dictionary?");
   assert_locked();
-  size_t res = _dictionary->maxChunkSize();
+  size_t res = _dictionary->max_chunk_size();
   res = MAX2(res, MIN2(_smallLinearAllocBlock._word_size,
                        (size_t) SmallForLinearAlloc - 1));
   // XXX the following could potentially be pretty slow;
@@ -448,7 +450,7 @@
   reportIndexedFreeListStatistics();
   gclog_or_tty->print_cr("Layout of Indexed Freelists");
   gclog_or_tty->print_cr("---------------------------");
-  FreeList::print_labels_on(st, "size");
+  FreeList<FreeChunk>::print_labels_on(st, "size");
   for (size_t i = IndexSetStart; i < IndexSetSize; i += IndexSetStride) {
     _indexedFreeList[i].print_on(gclog_or_tty);
     for (FreeChunk* fc = _indexedFreeList[i].head(); fc != NULL;
@@ -467,7 +469,7 @@
 
 void CompactibleFreeListSpace::print_dictionary_free_lists(outputStream* st)
 const {
-  _dictionary->reportStatistics();
+  _dictionary->report_statistics();
   st->print_cr("Layout of Freelists in Tree");
   st->print_cr("---------------------------");
   _dictionary->print_free_lists(st);
@@ -545,12 +547,12 @@
 void CompactibleFreeListSpace::reportFreeListStatistics() const {
   assert_lock_strong(&_freelistLock);
   assert(PrintFLSStatistics != 0, "Reporting error");
-  _dictionary->reportStatistics();
+  _dictionary->report_statistics();
   if (PrintFLSStatistics > 1) {
     reportIndexedFreeListStatistics();
-    size_t totalSize = totalSizeInIndexedFreeLists() +
-                       _dictionary->totalChunkSize(DEBUG_ONLY(freelistLock()));
-    gclog_or_tty->print(" free=%ld frag=%1.4f\n", totalSize, flsFrag());
+    size_t total_size = totalSizeInIndexedFreeLists() +
+                       _dictionary->total_chunk_size(DEBUG_ONLY(freelistLock()));
+    gclog_or_tty->print(" free=%ld frag=%1.4f\n", total_size, flsFrag());
   }
 }
 
@@ -558,13 +560,13 @@
   assert_lock_strong(&_freelistLock);
   gclog_or_tty->print("Statistics for IndexedFreeLists:\n"
                       "--------------------------------\n");
-  size_t totalSize = totalSizeInIndexedFreeLists();
-  size_t   freeBlocks = numFreeBlocksInIndexedFreeLists();
-  gclog_or_tty->print("Total Free Space: %d\n", totalSize);
+  size_t total_size = totalSizeInIndexedFreeLists();
+  size_t   free_blocks = numFreeBlocksInIndexedFreeLists();
+  gclog_or_tty->print("Total Free Space: %d\n", total_size);
   gclog_or_tty->print("Max   Chunk Size: %d\n", maxChunkSizeInIndexedFreeLists());
-  gclog_or_tty->print("Number of Blocks: %d\n", freeBlocks);
-  if (freeBlocks != 0) {
-    gclog_or_tty->print("Av.  Block  Size: %d\n", totalSize/freeBlocks);
+  gclog_or_tty->print("Number of Blocks: %d\n", free_blocks);
+  if (free_blocks != 0) {
+    gclog_or_tty->print("Av.  Block  Size: %d\n", total_size/free_blocks);
   }
 }
 
@@ -911,7 +913,7 @@
   for (addr = bottom(), last  = end();
        addr < last; addr += size) {
     FreeChunk* fc = (FreeChunk*)addr;
-    if (fc->isFree()) {
+    if (fc->is_free()) {
       // Since we hold the free list lock, which protects direct
       // allocation in this generation by mutators, a free object
       // will remain free throughout this iteration code.
@@ -953,7 +955,7 @@
   for (addr = block_start_careful(mr.start()), end  = mr.end();
        addr < end; addr += size) {
     FreeChunk* fc = (FreeChunk*)addr;
-    if (fc->isFree()) {
+    if (fc->is_free()) {
       // Since we hold the free list lock, which protects direct
       // allocation in this generation by mutators, a free object
       // will remain free throughout this iteration code.
@@ -1069,7 +1071,7 @@
   NOT_PRODUCT(verify_objects_initialized());
   assert(MemRegion(bottom(), end()).contains(p), "p not in space");
   FreeChunk* fc = (FreeChunk*)p;
-  if (fc->isFree()) {
+  if (fc->is_free()) {
     return fc->size();
   } else {
     // Ignore mark word because this may be a recently promoted
@@ -1160,7 +1162,7 @@
   FreeChunk* fc = (FreeChunk*)p;
   assert(is_in_reserved(p), "Should be in space");
   assert(_bt.block_start(p) == p, "Should be a block boundary");
-  if (!fc->isFree()) {
+  if (!fc->is_free()) {
     // Ignore mark word because it may have been used to
     // chain together promoted objects (the last one
     // would have a null value).
@@ -1222,7 +1224,7 @@
 
     FreeChunk* fc = (FreeChunk*)res;
     fc->markNotFree();
-    assert(!fc->isFree(), "shouldn't be marked free");
+    assert(!fc->is_free(), "shouldn't be marked free");
     assert(oop(fc)->klass_or_null() == NULL, "should look uninitialized");
     // Verify that the block offset table shows this to
     // be a single block, but not one which is unallocated.
@@ -1331,10 +1333,10 @@
   size_t currSize = numWords + MinChunkSize;
   assert(currSize % MinObjAlignment == 0, "currSize should be aligned");
   for (i = currSize; i < IndexSetSize; i += IndexSetStride) {
-    FreeList* fl = &_indexedFreeList[i];
+    FreeList<FreeChunk>* fl = &_indexedFreeList[i];
     if (fl->head()) {
       ret = getFromListGreater(fl, numWords);
-      assert(ret == NULL || ret->isFree(), "Should be returning a free chunk");
+      assert(ret == NULL || ret->is_free(), "Should be returning a free chunk");
       return ret;
     }
   }
@@ -1345,7 +1347,7 @@
   /* Try to get a chunk that satisfies request, while avoiding
      fragmentation that can't be handled. */
   {
-    ret =  dictionary()->getChunk(currSize);
+    ret =  dictionary()->get_chunk(currSize);
     if (ret != NULL) {
       assert(ret->size() - numWords >= MinChunkSize,
              "Chunk is too small");
@@ -1353,10 +1355,10 @@
       /* Carve returned chunk. */
       (void) splitChunkAndReturnRemainder(ret, numWords);
       /* Label this as no longer a free chunk. */
-      assert(ret->isFree(), "This chunk should be free");
-      ret->linkPrev(NULL);
+      assert(ret->is_free(), "This chunk should be free");
+      ret->link_prev(NULL);
     }
-    assert(ret == NULL || ret->isFree(), "Should be returning a free chunk");
+    assert(ret == NULL || ret->is_free(), "Should be returning a free chunk");
     return ret;
   }
   ShouldNotReachHere();
@@ -1364,7 +1366,7 @@
 
 bool CompactibleFreeListSpace::verifyChunkInIndexedFreeLists(FreeChunk* fc) const {
   assert(fc->size() < IndexSetSize, "Size of chunk is too large");
-  return _indexedFreeList[fc->size()].verifyChunkInFreeLists(fc);
+  return _indexedFreeList[fc->size()].verify_chunk_in_free_list(fc);
 }
 
 bool CompactibleFreeListSpace::verify_chunk_is_linear_alloc_block(FreeChunk* fc) const {
@@ -1378,13 +1380,13 @@
 // Check if the purported free chunk is present either as a linear
 // allocation block, the size-indexed table of (smaller) free blocks,
 // or the larger free blocks kept in the binary tree dictionary.
-bool CompactibleFreeListSpace::verifyChunkInFreeLists(FreeChunk* fc) const {
+bool CompactibleFreeListSpace::verify_chunk_in_free_list(FreeChunk* fc) const {
   if (verify_chunk_is_linear_alloc_block(fc)) {
     return true;
   } else if (fc->size() < IndexSetSize) {
     return verifyChunkInIndexedFreeLists(fc);
   } else {
-    return dictionary()->verifyChunkInFreeLists(fc);
+    return dictionary()->verify_chunk_in_free_list(fc);
   }
 }
 
@@ -1412,7 +1414,7 @@
   }
   if (fc != NULL) {
     fc->dontCoalesce();
-    assert(fc->isFree(), "Should be free, but not coalescable");
+    assert(fc->is_free(), "Should be free, but not coalescable");
     // Verify that the block offset table shows this to
     // be a single block, but not one which is unallocated.
     _bt.verify_single_block((HeapWord*)fc, fc->size());
@@ -1492,7 +1494,7 @@
     }
     // Return the chunk that isn't big enough, and then refill below.
     addChunkToFreeLists(blk->_ptr, sz);
-    splitBirth(sz);
+    split_birth(sz);
     // Don't keep statistics on adding back chunk from a LinAB.
   } else {
     // A refilled block would not satisfy the request.
@@ -1504,14 +1506,14 @@
   assert(blk->_ptr == NULL || blk->_word_size >= size + MinChunkSize,
          "block was replenished");
   if (res != NULL) {
-    splitBirth(size);
+    split_birth(size);
     repairLinearAllocBlock(blk);
   } else if (blk->_ptr != NULL) {
     res = blk->_ptr;
     size_t blk_size = blk->_word_size;
     blk->_word_size -= size;
     blk->_ptr  += size;
-    splitBirth(size);
+    split_birth(size);
     repairLinearAllocBlock(blk);
     // Update BOT last so that other (parallel) GC threads see a consistent
     // view of the BOT and free blocks.
@@ -1540,7 +1542,7 @@
     size_t blk_size = blk->_word_size;
     blk->_word_size -= size;
     blk->_ptr  += size;
-    splitBirth(size);
+    split_birth(size);
     repairLinearAllocBlock(blk);
     // Update BOT last so that other (parallel) GC threads see a consistent
     // view of the BOT and free blocks.
@@ -1557,7 +1559,7 @@
   assert_locked();
   assert(size < SmallForDictionary, "just checking");
   FreeChunk* res;
-  res = _indexedFreeList[size].getChunkAtHead();
+  res = _indexedFreeList[size].get_chunk_at_head();
   if (res == NULL) {
     res = getChunkFromIndexedFreeListHelper(size);
   }
@@ -1591,7 +1593,7 @@
         // Do not replenish from an underpopulated size.
         if (_indexedFreeList[replenish_size].surplus() > 0 &&
             _indexedFreeList[replenish_size].head() != NULL) {
-          newFc = _indexedFreeList[replenish_size].getChunkAtHead();
+          newFc = _indexedFreeList[replenish_size].get_chunk_at_head();
         } else if (bestFitFirst()) {
           newFc = bestFitSmall(replenish_size);
         }
@@ -1624,13 +1626,13 @@
                i < (num_blk - 1);
                curFc = nextFc, nextFc = (FreeChunk*)((HeapWord*)nextFc + size),
                i++) {
-            curFc->setSize(size);
+            curFc->set_size(size);
             // Don't record this as a return in order to try and
             // determine the "returns" from a GC.
             _bt.verify_not_unallocated((HeapWord*) fc, size);
-            _indexedFreeList[size].returnChunkAtTail(curFc, false);
+            _indexedFreeList[size].return_chunk_at_tail(curFc, false);
             _bt.mark_block((HeapWord*)curFc, size);
-            splitBirth(size);
+            split_birth(size);
             // Don't record the initial population of the indexed list
             // as a split birth.
           }
@@ -1638,9 +1640,9 @@
           // check that the arithmetic was OK above
           assert((HeapWord*)nextFc == (HeapWord*)newFc + num_blk*size,
             "inconsistency in carving newFc");
-          curFc->setSize(size);
+          curFc->set_size(size);
           _bt.mark_block((HeapWord*)curFc, size);
-          splitBirth(size);
+          split_birth(size);
           fc = curFc;
         } else {
           // Return entire block to caller
@@ -1653,14 +1655,14 @@
     // replenish the indexed free list.
     fc = getChunkFromDictionaryExact(size);
   }
-  // assert(fc == NULL || fc->isFree(), "Should be returning a free chunk");
+  // assert(fc == NULL || fc->is_free(), "Should be returning a free chunk");
   return fc;
 }
 
 FreeChunk*
 CompactibleFreeListSpace::getChunkFromDictionary(size_t size) {
   assert_locked();
-  FreeChunk* fc = _dictionary->getChunk(size);
+  FreeChunk* fc = _dictionary->get_chunk(size);
   if (fc == NULL) {
     return NULL;
   }
@@ -1677,7 +1679,7 @@
 FreeChunk*
 CompactibleFreeListSpace::getChunkFromDictionaryExact(size_t size) {
   assert_locked();
-  FreeChunk* fc = _dictionary->getChunk(size);
+  FreeChunk* fc = _dictionary->get_chunk(size);
   if (fc == NULL) {
     return fc;
   }
@@ -1686,11 +1688,11 @@
     _bt.verify_single_block((HeapWord*)fc, size);
     return fc;
   }
-  assert(fc->size() > size, "getChunk() guarantee");
+  assert(fc->size() > size, "get_chunk() guarantee");
   if (fc->size() < size + MinChunkSize) {
     // Return the chunk to the dictionary and go get a bigger one.
     returnChunkToDictionary(fc);
-    fc = _dictionary->getChunk(size + MinChunkSize);
+    fc = _dictionary->get_chunk(size + MinChunkSize);
     if (fc == NULL) {
       return NULL;
     }
@@ -1711,10 +1713,10 @@
   _bt.verify_single_block((HeapWord*)chunk, size);
   // adjust _unallocated_block downward, as necessary
   _bt.freed((HeapWord*)chunk, size);
-  _dictionary->returnChunk(chunk);
+  _dictionary->return_chunk(chunk);
 #ifndef PRODUCT
   if (CMSCollector::abstract_state() != CMSCollector::Sweeping) {
-    TreeChunk::as_TreeChunk(chunk)->list()->verify_stats();
+    TreeChunk<FreeChunk>::as_TreeChunk(chunk)->list()->verify_stats();
   }
 #endif // PRODUCT
 }
@@ -1726,9 +1728,9 @@
   _bt.verify_single_block((HeapWord*) fc, size);
   _bt.verify_not_unallocated((HeapWord*) fc, size);
   if (_adaptive_freelists) {
-    _indexedFreeList[size].returnChunkAtTail(fc);
+    _indexedFreeList[size].return_chunk_at_tail(fc);
   } else {
-    _indexedFreeList[size].returnChunkAtHead(fc);
+    _indexedFreeList[size].return_chunk_at_head(fc);
   }
 #ifndef PRODUCT
   if (CMSCollector::abstract_state() != CMSCollector::Sweeping) {
@@ -1756,7 +1758,7 @@
   FreeChunk* ec;
   {
     MutexLockerEx x(lock, Mutex::_no_safepoint_check_flag);
-    ec = dictionary()->findLargestDict();  // get largest block
+    ec = dictionary()->find_largest_dict();  // get largest block
     if (ec != NULL && ec->end() == chunk) {
       // It's a coterminal block - we can coalesce.
       size_t old_size = ec->size();
@@ -1767,7 +1769,7 @@
       ec = (FreeChunk*)chunk;
     }
   }
-  ec->setSize(size);
+  ec->set_size(size);
   debug_only(ec->mangleFreed(size));
   if (size < SmallForDictionary) {
     lock = _indexedFreeListParLocks[size];
@@ -1790,7 +1792,7 @@
   _bt.verify_single_block(chunk, size);
 
   FreeChunk* fc = (FreeChunk*) chunk;
-  fc->setSize(size);
+  fc->set_size(size);
   debug_only(fc->mangleFreed(size));
   if (size < SmallForDictionary) {
     returnChunkToFreeList(fc);
@@ -1833,7 +1835,7 @@
   assert_locked();
   assert(fc != NULL, "null chunk");
   _bt.verify_single_block((HeapWord*)fc, size);
-  _dictionary->removeChunk(fc);
+  _dictionary->remove_chunk(fc);
   // adjust _unallocated_block upward, as necessary
   _bt.allocated((HeapWord*)fc, size);
 }
@@ -1848,7 +1850,7 @@
       verifyIndexedFreeList(size);
     }
   )
-  _indexedFreeList[size].removeChunk(fc);
+  _indexedFreeList[size].remove_chunk(fc);
   NOT_PRODUCT(
     if (FLSVerifyIndexTable) {
       verifyIndexedFreeList(size);
@@ -1862,17 +1864,17 @@
      the excess is >= MIN_CHUNK. */
   size_t start = align_object_size(numWords + MinChunkSize);
   if (start < IndexSetSize) {
-    FreeList* it   = _indexedFreeList;
+    FreeList<FreeChunk>* it   = _indexedFreeList;
     size_t    hint = _indexedFreeList[start].hint();
     while (hint < IndexSetSize) {
       assert(hint % MinObjAlignment == 0, "hint should be aligned");
-      FreeList *fl = &_indexedFreeList[hint];
+      FreeList<FreeChunk> *fl = &_indexedFreeList[hint];
       if (fl->surplus() > 0 && fl->head() != NULL) {
         // Found a list with surplus, reset original hint
         // and split out a free chunk which is returned.
         _indexedFreeList[start].set_hint(hint);
         FreeChunk* res = getFromListGreater(fl, numWords);
-        assert(res == NULL || res->isFree(),
+        assert(res == NULL || res->is_free(),
           "Should be returning a free chunk");
         return res;
       }
@@ -1885,7 +1887,7 @@
 }
 
 /* Requires fl->size >= numWords + MinChunkSize */
-FreeChunk* CompactibleFreeListSpace::getFromListGreater(FreeList* fl,
+FreeChunk* CompactibleFreeListSpace::getFromListGreater(FreeList<FreeChunk>* fl,
   size_t numWords) {
   FreeChunk *curr = fl->head();
   size_t oldNumWords = curr->size();
@@ -1894,13 +1896,13 @@
   assert(oldNumWords >= numWords + MinChunkSize,
         "Size of chunks in the list is too small");
 
-  fl->removeChunk(curr);
+  fl->remove_chunk(curr);
   // recorded indirectly by splitChunkAndReturnRemainder -
   // smallSplit(oldNumWords, numWords);
   FreeChunk* new_chunk = splitChunkAndReturnRemainder(curr, numWords);
   // Does anything have to be done for the remainder in terms of
   // fixing the card table?
-  assert(new_chunk == NULL || new_chunk->isFree(),
+  assert(new_chunk == NULL || new_chunk->is_free(),
     "Should be returning a free chunk");
   return new_chunk;
 }
@@ -1918,13 +1920,13 @@
   assert(rem_size >= MinChunkSize, "Free chunk smaller than minimum");
   FreeChunk* ffc = (FreeChunk*)((HeapWord*)chunk + new_size);
   assert(is_aligned(ffc), "alignment problem");
-  ffc->setSize(rem_size);
-  ffc->linkNext(NULL);
-  ffc->linkPrev(NULL); // Mark as a free block for other (parallel) GC threads.
+  ffc->set_size(rem_size);
+  ffc->link_next(NULL);
+  ffc->link_prev(NULL); // Mark as a free block for other (parallel) GC threads.
   // Above must occur before BOT is updated below.
   // adjust block offset table
   OrderAccess::storestore();
-  assert(chunk->isFree() && ffc->isFree(), "Error");
+  assert(chunk->is_free() && ffc->is_free(), "Error");
   _bt.split_block((HeapWord*)chunk, chunk->size(), new_size);
   if (rem_size < SmallForDictionary) {
     bool is_par = (SharedHeap::heap()->n_par_threads() > 0);
@@ -1939,7 +1941,7 @@
     returnChunkToDictionary(ffc);
     split(size ,rem_size);
   }
-  chunk->setSize(new_size);
+  chunk->set_size(new_size);
   return chunk;
 }
 
@@ -2046,10 +2048,10 @@
     assert(blk->_word_size != 0 && blk->_word_size >= MinChunkSize,
            "Minimum block size requirement");
     FreeChunk* fc = (FreeChunk*)(blk->_ptr);
-    fc->setSize(blk->_word_size);
-    fc->linkPrev(NULL);   // mark as free
+    fc->set_size(blk->_word_size);
+    fc->link_prev(NULL);   // mark as free
     fc->dontCoalesce();
-    assert(fc->isFree(), "just marked it free");
+    assert(fc->is_free(), "just marked it free");
     assert(fc->cantCoalesce(), "just marked it uncoalescable");
   }
 }
@@ -2149,7 +2151,7 @@
   }
 
   double totFree = itabFree +
-                   _dictionary->totalChunkSize(DEBUG_ONLY(freelistLock()));
+                   _dictionary->total_chunk_size(DEBUG_ONLY(freelistLock()));
   if (totFree > 0) {
     frag = ((frag + _dictionary->sum_of_squared_block_sizes()) /
             (totFree * totFree));
@@ -2167,16 +2169,16 @@
   assert_locked();
   size_t i;
   for (i = IndexSetStart; i < IndexSetSize; i += IndexSetStride) {
-    FreeList* fl    = &_indexedFreeList[i];
+    FreeList<FreeChunk>* fl = &_indexedFreeList[i];
     if (PrintFLSStatistics > 1) {
       gclog_or_tty->print("size[%d] : ", i);
     }
     fl->compute_desired(inter_sweep_current, inter_sweep_estimate, intra_sweep_estimate);
-    fl->set_coalDesired((ssize_t)((double)fl->desired() * CMSSmallCoalSurplusPercent));
-    fl->set_beforeSweep(fl->count());
-    fl->set_bfrSurp(fl->surplus());
+    fl->set_coal_desired((ssize_t)((double)fl->desired() * CMSSmallCoalSurplusPercent));
+    fl->set_before_sweep(fl->count());
+    fl->set_bfr_surp(fl->surplus());
   }
-  _dictionary->beginSweepDictCensus(CMSLargeCoalSurplusPercent,
+  _dictionary->begin_sweep_dict_census(CMSLargeCoalSurplusPercent,
                                     inter_sweep_current,
                                     inter_sweep_estimate,
                                     intra_sweep_estimate);
@@ -2186,7 +2188,7 @@
   assert_locked();
   size_t i;
   for (i = IndexSetStart; i < IndexSetSize; i += IndexSetStride) {
-    FreeList *fl = &_indexedFreeList[i];
+    FreeList<FreeChunk> *fl = &_indexedFreeList[i];
     fl->set_surplus(fl->count() -
                     (ssize_t)((double)fl->desired() * CMSSmallSplitSurplusPercent));
   }
@@ -2197,7 +2199,7 @@
   size_t i;
   size_t h = IndexSetSize;
   for (i = IndexSetSize - 1; i != 0; i -= IndexSetStride) {
-    FreeList *fl = &_indexedFreeList[i];
+    FreeList<FreeChunk> *fl = &_indexedFreeList[i];
     fl->set_hint(h);
     if (fl->surplus() > 0) {
       h = i;
@@ -2209,18 +2211,18 @@
   assert_locked();
   size_t i;
   for (i = IndexSetStart; i < IndexSetSize; i += IndexSetStride) {
-    FreeList *fl = &_indexedFreeList[i];
-    fl->set_prevSweep(fl->count());
-    fl->set_coalBirths(0);
-    fl->set_coalDeaths(0);
-    fl->set_splitBirths(0);
-    fl->set_splitDeaths(0);
+    FreeList<FreeChunk> *fl = &_indexedFreeList[i];
+    fl->set_prev_sweep(fl->count());
+    fl->set_coal_births(0);
+    fl->set_coal_deaths(0);
+    fl->set_split_births(0);
+    fl->set_split_deaths(0);
   }
 }
 
 void CompactibleFreeListSpace::endSweepFLCensus(size_t sweep_count) {
   if (PrintFLSStatistics > 0) {
-    HeapWord* largestAddr = (HeapWord*) dictionary()->findLargestDict();
+    HeapWord* largestAddr = (HeapWord*) dictionary()->find_largest_dict();
     gclog_or_tty->print_cr("CMS: Large block " PTR_FORMAT,
                            largestAddr);
   }
@@ -2231,30 +2233,30 @@
   }
   clearFLCensus();
   assert_locked();
-  _dictionary->endSweepDictCensus(CMSLargeSplitSurplusPercent);
+  _dictionary->end_sweep_dict_census(CMSLargeSplitSurplusPercent);
 }
 
 bool CompactibleFreeListSpace::coalOverPopulated(size_t size) {
   if (size < SmallForDictionary) {
-    FreeList *fl = &_indexedFreeList[size];
-    return (fl->coalDesired() < 0) ||
-           ((int)fl->count() > fl->coalDesired());
+    FreeList<FreeChunk> *fl = &_indexedFreeList[size];
+    return (fl->coal_desired() < 0) ||
+           ((int)fl->count() > fl->coal_desired());
   } else {
-    return dictionary()->coalDictOverPopulated(size);
+    return dictionary()->coal_dict_over_populated(size);
   }
 }
 
 void CompactibleFreeListSpace::smallCoalBirth(size_t size) {
   assert(size < SmallForDictionary, "Size too large for indexed list");
-  FreeList *fl = &_indexedFreeList[size];
-  fl->increment_coalBirths();
+  FreeList<FreeChunk> *fl = &_indexedFreeList[size];
+  fl->increment_coal_births();
   fl->increment_surplus();
 }
 
 void CompactibleFreeListSpace::smallCoalDeath(size_t size) {
   assert(size < SmallForDictionary, "Size too large for indexed list");
-  FreeList *fl = &_indexedFreeList[size];
-  fl->increment_coalDeaths();
+  FreeList<FreeChunk> *fl = &_indexedFreeList[size];
+  fl->increment_coal_deaths();
   fl->decrement_surplus();
 }
 
@@ -2262,7 +2264,7 @@
   if (size  < SmallForDictionary) {
     smallCoalBirth(size);
   } else {
-    dictionary()->dictCensusUpdate(size,
+    dictionary()->dict_census_udpate(size,
                                    false /* split */,
                                    true /* birth */);
   }
@@ -2272,7 +2274,7 @@
   if(size  < SmallForDictionary) {
     smallCoalDeath(size);
   } else {
-    dictionary()->dictCensusUpdate(size,
+    dictionary()->dict_census_udpate(size,
                                    false /* split */,
                                    false /* birth */);
   }
@@ -2280,23 +2282,23 @@
 
 void CompactibleFreeListSpace::smallSplitBirth(size_t size) {
   assert(size < SmallForDictionary, "Size too large for indexed list");
-  FreeList *fl = &_indexedFreeList[size];
-  fl->increment_splitBirths();
+  FreeList<FreeChunk> *fl = &_indexedFreeList[size];
+  fl->increment_split_births();
   fl->increment_surplus();
 }
 
 void CompactibleFreeListSpace::smallSplitDeath(size_t size) {
   assert(size < SmallForDictionary, "Size too large for indexed list");
-  FreeList *fl = &_indexedFreeList[size];
-  fl->increment_splitDeaths();
+  FreeList<FreeChunk> *fl = &_indexedFreeList[size];
+  fl->increment_split_deaths();
   fl->decrement_surplus();
 }
 
-void CompactibleFreeListSpace::splitBirth(size_t size) {
+void CompactibleFreeListSpace::split_birth(size_t size) {
   if (size  < SmallForDictionary) {
     smallSplitBirth(size);
   } else {
-    dictionary()->dictCensusUpdate(size,
+    dictionary()->dict_census_udpate(size,
                                    true /* split */,
                                    true /* birth */);
   }
@@ -2306,7 +2308,7 @@
   if (size  < SmallForDictionary) {
     smallSplitDeath(size);
   } else {
-    dictionary()->dictCensusUpdate(size,
+    dictionary()->dict_census_udpate(size,
                                    true /* split */,
                                    false /* birth */);
   }
@@ -2315,8 +2317,8 @@
 void CompactibleFreeListSpace::split(size_t from, size_t to1) {
   size_t to2 = from - to1;
   splitDeath(from);
-  splitBirth(to1);
-  splitBirth(to2);
+  split_birth(to1);
+  split_birth(to2);
 }
 
 void CompactibleFreeListSpace::print() const {
@@ -2362,7 +2364,7 @@
       FreeChunk* fc = (FreeChunk*)addr;
       res = fc->size();
       if (FLSVerifyLists && !fc->cantCoalesce()) {
-        guarantee(_sp->verifyChunkInFreeLists(fc),
+        guarantee(_sp->verify_chunk_in_free_list(fc),
                   "Chunk should be on a free list");
       }
     }
@@ -2518,7 +2520,7 @@
             "Slot should have been empty");
   for (; fc != NULL; fc = fc->next(), n++) {
     guarantee(fc->size() == size, "Size inconsistency");
-    guarantee(fc->isFree(), "!free?");
+    guarantee(fc->is_free(), "!free?");
     guarantee(fc->next() == NULL || fc->next()->prev() == fc, "Broken list");
     guarantee((fc->next() == NULL) == (fc == tail), "Incorrect tail");
   }
@@ -2527,10 +2529,10 @@
 
 #ifndef PRODUCT
 void CompactibleFreeListSpace::check_free_list_consistency() const {
-  assert(_dictionary->minSize() <= IndexSetSize,
+  assert(_dictionary->min_size() <= IndexSetSize,
     "Some sizes can't be allocated without recourse to"
     " linear allocation buffers");
-  assert(MIN_TREE_CHUNK_SIZE*HeapWordSize == sizeof(TreeChunk),
+  assert(BinaryTreeDictionary<FreeChunk>::min_tree_chunk_size*HeapWordSize == sizeof(TreeChunk<FreeChunk>),
     "else MIN_TREE_CHUNK_SIZE is wrong");
   assert((IndexSetStride == 2 && IndexSetStart == 4) ||                   // 32-bit
          (IndexSetStride == 1 && IndexSetStart == 3), "just checking");   // 64-bit
@@ -2543,36 +2545,36 @@
 
 void CompactibleFreeListSpace::printFLCensus(size_t sweep_count) const {
   assert_lock_strong(&_freelistLock);
-  FreeList total;
+  FreeList<FreeChunk> total;
   gclog_or_tty->print("end sweep# " SIZE_FORMAT "\n", sweep_count);
-  FreeList::print_labels_on(gclog_or_tty, "size");
-  size_t totalFree = 0;
+  FreeList<FreeChunk>::print_labels_on(gclog_or_tty, "size");
+  size_t total_free = 0;
   for (size_t i = IndexSetStart; i < IndexSetSize; i += IndexSetStride) {
-    const FreeList *fl = &_indexedFreeList[i];
-    totalFree += fl->count() * fl->size();
+    const FreeList<FreeChunk> *fl = &_indexedFreeList[i];
+    total_free += fl->count() * fl->size();
     if (i % (40*IndexSetStride) == 0) {
-      FreeList::print_labels_on(gclog_or_tty, "size");
+      FreeList<FreeChunk>::print_labels_on(gclog_or_tty, "size");
     }
     fl->print_on(gclog_or_tty);
-    total.set_bfrSurp(    total.bfrSurp()     + fl->bfrSurp()    );
+    total.set_bfr_surp(    total.bfr_surp()     + fl->bfr_surp()    );
     total.set_surplus(    total.surplus()     + fl->surplus()    );
     total.set_desired(    total.desired()     + fl->desired()    );
-    total.set_prevSweep(  total.prevSweep()   + fl->prevSweep()  );
-    total.set_beforeSweep(total.beforeSweep() + fl->beforeSweep());
+    total.set_prev_sweep(  total.prev_sweep()   + fl->prev_sweep()  );
+    total.set_before_sweep(total.before_sweep() + fl->before_sweep());
     total.set_count(      total.count()       + fl->count()      );
-    total.set_coalBirths( total.coalBirths()  + fl->coalBirths() );
-    total.set_coalDeaths( total.coalDeaths()  + fl->coalDeaths() );
-    total.set_splitBirths(total.splitBirths() + fl->splitBirths());
-    total.set_splitDeaths(total.splitDeaths() + fl->splitDeaths());
+    total.set_coal_births( total.coal_births()  + fl->coal_births() );
+    total.set_coal_deaths( total.coal_deaths()  + fl->coal_deaths() );
+    total.set_split_births(total.split_births() + fl->split_births());
+    total.set_split_deaths(total.split_deaths() + fl->split_deaths());
   }
   total.print_on(gclog_or_tty, "TOTAL");
   gclog_or_tty->print_cr("Total free in indexed lists "
-                         SIZE_FORMAT " words", totalFree);
+                         SIZE_FORMAT " words", total_free);
   gclog_or_tty->print("growth: %8.5f  deficit: %8.5f\n",
-    (double)(total.splitBirths()+total.coalBirths()-total.splitDeaths()-total.coalDeaths())/
-            (total.prevSweep() != 0 ? (double)total.prevSweep() : 1.0),
+    (double)(total.split_births()+total.coal_births()-total.split_deaths()-total.coal_deaths())/
+            (total.prev_sweep() != 0 ? (double)total.prev_sweep() : 1.0),
     (double)(total.desired() - total.count())/(total.desired() != 0 ? (double)total.desired() : 1.0));
-  _dictionary->printDictCensus();
+  _dictionary->print_dict_census();
 }
 
 ///////////////////////////////////////////////////////////////////////////
@@ -2634,18 +2636,18 @@
     res = _cfls->getChunkFromDictionaryExact(word_sz);
     if (res == NULL) return NULL;
   } else {
-    FreeList* fl = &_indexedFreeList[word_sz];
+    FreeList<FreeChunk>* fl = &_indexedFreeList[word_sz];
     if (fl->count() == 0) {
       // Attempt to refill this local free list.
       get_from_global_pool(word_sz, fl);
       // If it didn't work, give up.
       if (fl->count() == 0) return NULL;
     }
-    res = fl->getChunkAtHead();
+    res = fl->get_chunk_at_head();
     assert(res != NULL, "Why was count non-zero?");
   }
   res->markNotFree();
-  assert(!res->isFree(), "shouldn't be marked free");
+  assert(!res->is_free(), "shouldn't be marked free");
   assert(oop(res)->klass_or_null() == NULL, "should look uninitialized");
   // mangle a just allocated object with a distinct pattern.
   debug_only(res->mangleAllocated(word_sz));
@@ -2654,7 +2656,7 @@
 
 // Get a chunk of blocks of the right size and update related
 // book-keeping stats
-void CFLS_LAB::get_from_global_pool(size_t word_sz, FreeList* fl) {
+void CFLS_LAB::get_from_global_pool(size_t word_sz, FreeList<FreeChunk>* fl) {
   // Get the #blocks we want to claim
   size_t n_blks = (size_t)_blocks_to_claim[word_sz].average();
   assert(n_blks > 0, "Error");
@@ -2736,7 +2738,7 @@
         if (num_retire > 0) {
           _cfls->_indexedFreeList[i].prepend(&_indexedFreeList[i]);
           // Reset this list.
-          _indexedFreeList[i] = FreeList();
+          _indexedFreeList[i] = FreeList<FreeChunk>();
           _indexedFreeList[i].set_size(i);
         }
       }
@@ -2750,7 +2752,7 @@
   }
 }
 
-void CompactibleFreeListSpace:: par_get_chunk_of_blocks(size_t word_sz, size_t n, FreeList* fl) {
+void CompactibleFreeListSpace:: par_get_chunk_of_blocks(size_t word_sz, size_t n, FreeList<FreeChunk>* fl) {
   assert(fl->count() == 0, "Precondition.");
   assert(word_sz < CompactibleFreeListSpace::IndexSetSize,
          "Precondition");
@@ -2766,12 +2768,12 @@
          (cur_sz < CompactibleFreeListSpace::IndexSetSize) &&
          (CMSSplitIndexedFreeListBlocks || k <= 1);
          k++, cur_sz = k * word_sz) {
-      FreeList fl_for_cur_sz;  // Empty.
+      FreeList<FreeChunk> fl_for_cur_sz;  // Empty.
       fl_for_cur_sz.set_size(cur_sz);
       {
         MutexLockerEx x(_indexedFreeListParLocks[cur_sz],
                         Mutex::_no_safepoint_check_flag);
-        FreeList* gfl = &_indexedFreeList[cur_sz];
+        FreeList<FreeChunk>* gfl = &_indexedFreeList[cur_sz];
         if (gfl->count() != 0) {
           // nn is the number of chunks of size cur_sz that
           // we'd need to split k-ways each, in order to create
@@ -2784,9 +2786,9 @@
             // we increment the split death count by the number of blocks
             // we just took from the cur_sz-size blocks list and which
             // we will be splitting below.
-            ssize_t deaths = gfl->splitDeaths() +
+            ssize_t deaths = gfl->split_deaths() +
                              fl_for_cur_sz.count();
-            gfl->set_splitDeaths(deaths);
+            gfl->set_split_deaths(deaths);
           }
         }
       }
@@ -2797,21 +2799,21 @@
         } else {
           // Divide each block on fl_for_cur_sz up k ways.
           FreeChunk* fc;
-          while ((fc = fl_for_cur_sz.getChunkAtHead()) != NULL) {
+          while ((fc = fl_for_cur_sz.get_chunk_at_head()) != NULL) {
             // Must do this in reverse order, so that anybody attempting to
             // access the main chunk sees it as a single free block until we
             // change it.
             size_t fc_size = fc->size();
-            assert(fc->isFree(), "Error");
+            assert(fc->is_free(), "Error");
             for (int i = k-1; i >= 0; i--) {
               FreeChunk* ffc = (FreeChunk*)((HeapWord*)fc + i * word_sz);
               assert((i != 0) ||
-                        ((fc == ffc) && ffc->isFree() &&
+                        ((fc == ffc) && ffc->is_free() &&
                          (ffc->size() == k*word_sz) && (fc_size == word_sz)),
                         "Counting error");
-              ffc->setSize(word_sz);
-              ffc->linkPrev(NULL); // Mark as a free block for other (parallel) GC threads.
-              ffc->linkNext(NULL);
+              ffc->set_size(word_sz);
+              ffc->link_prev(NULL); // Mark as a free block for other (parallel) GC threads.
+              ffc->link_next(NULL);
               // Above must occur before BOT is updated below.
               OrderAccess::storestore();
               // splitting from the right, fc_size == i * word_sz
@@ -2822,7 +2824,7 @@
               _bt.verify_single_block((HeapWord*)fc, fc_size);
               _bt.verify_single_block((HeapWord*)ffc, word_sz);
               // Push this on "fl".
-              fl->returnChunkAtHead(ffc);
+              fl->return_chunk_at_head(ffc);
             }
             // TRAP
             assert(fl->tail()->next() == NULL, "List invariant.");
@@ -2832,8 +2834,8 @@
         size_t num = fl->count();
         MutexLockerEx x(_indexedFreeListParLocks[word_sz],
                         Mutex::_no_safepoint_check_flag);
-        ssize_t births = _indexedFreeList[word_sz].splitBirths() + num;
-        _indexedFreeList[word_sz].set_splitBirths(births);
+        ssize_t births = _indexedFreeList[word_sz].split_births() + num;
+        _indexedFreeList[word_sz].set_split_births(births);
         return;
       }
     }
@@ -2846,12 +2848,12 @@
     MutexLockerEx x(parDictionaryAllocLock(),
                     Mutex::_no_safepoint_check_flag);
     while (n > 0) {
-      fc = dictionary()->getChunk(MAX2(n * word_sz,
-                                  _dictionary->minSize()),
-                                  FreeBlockDictionary::atLeast);
+      fc = dictionary()->get_chunk(MAX2(n * word_sz,
+                                  _dictionary->min_size()),
+                                  FreeBlockDictionary<FreeChunk>::atLeast);
       if (fc != NULL) {
         _bt.allocated((HeapWord*)fc, fc->size(), true /* reducing */);  // update _unallocated_blk
-        dictionary()->dictCensusUpdate(fc->size(),
+        dictionary()->dict_census_udpate(fc->size(),
                                        true /*split*/,
                                        false /*birth*/);
         break;
@@ -2862,7 +2864,7 @@
     if (fc == NULL) return;
     // Otherwise, split up that block.
     assert((ssize_t)n >= 1, "Control point invariant");
-    assert(fc->isFree(), "Error: should be a free block");
+    assert(fc->is_free(), "Error: should be a free block");
     _bt.verify_single_block((HeapWord*)fc, fc->size());
     const size_t nn = fc->size() / word_sz;
     n = MIN2(nn, n);
@@ -2893,18 +2895,18 @@
     if (rem > 0) {
       size_t prefix_size = n * word_sz;
       rem_fc = (FreeChunk*)((HeapWord*)fc + prefix_size);
-      rem_fc->setSize(rem);
-      rem_fc->linkPrev(NULL); // Mark as a free block for other (parallel) GC threads.
-      rem_fc->linkNext(NULL);
+      rem_fc->set_size(rem);
+      rem_fc->link_prev(NULL); // Mark as a free block for other (parallel) GC threads.
+      rem_fc->link_next(NULL);
       // Above must occur before BOT is updated below.
       assert((ssize_t)n > 0 && prefix_size > 0 && rem_fc > fc, "Error");
       OrderAccess::storestore();
       _bt.split_block((HeapWord*)fc, fc->size(), prefix_size);
-      assert(fc->isFree(), "Error");
-      fc->setSize(prefix_size);
+      assert(fc->is_free(), "Error");
+      fc->set_size(prefix_size);
       if (rem >= IndexSetSize) {
         returnChunkToDictionary(rem_fc);
-        dictionary()->dictCensusUpdate(rem, true /*split*/, true /*birth*/);
+        dictionary()->dict_census_udpate(rem, true /*split*/, true /*birth*/);
         rem_fc = NULL;
       }
       // Otherwise, return it to the small list below.
@@ -2914,7 +2916,7 @@
     MutexLockerEx x(_indexedFreeListParLocks[rem],
                     Mutex::_no_safepoint_check_flag);
     _bt.verify_not_unallocated((HeapWord*)rem_fc, rem_fc->size());
-    _indexedFreeList[rem].returnChunkAtHead(rem_fc);
+    _indexedFreeList[rem].return_chunk_at_head(rem_fc);
     smallSplitBirth(rem);
   }
   assert((ssize_t)n > 0 && fc != NULL, "Consistency");
@@ -2926,9 +2928,9 @@
   // All but first chunk in this loop
   for (ssize_t i = n-1; i > 0; i--) {
     FreeChunk* ffc = (FreeChunk*)((HeapWord*)fc + i * word_sz);
-    ffc->setSize(word_sz);
-    ffc->linkPrev(NULL); // Mark as a free block for other (parallel) GC threads.
-    ffc->linkNext(NULL);
+    ffc->set_size(word_sz);
+    ffc->link_prev(NULL); // Mark as a free block for other (parallel) GC threads.
+    ffc->link_next(NULL);
     // Above must occur before BOT is updated below.
     OrderAccess::storestore();
     // splitting from the right, fc_size == (n - i + 1) * wordsize
@@ -2938,25 +2940,25 @@
     _bt.verify_single_block((HeapWord*)ffc, ffc->size());
     _bt.verify_single_block((HeapWord*)fc, fc_size);
     // Push this on "fl".
-    fl->returnChunkAtHead(ffc);
+    fl->return_chunk_at_head(ffc);
   }
   // First chunk
-  assert(fc->isFree() && fc->size() == n*word_sz, "Error: should still be a free block");
+  assert(fc->is_free() && fc->size() == n*word_sz, "Error: should still be a free block");
   // The blocks above should show their new sizes before the first block below
-  fc->setSize(word_sz);
-  fc->linkPrev(NULL);    // idempotent wrt free-ness, see assert above
-  fc->linkNext(NULL);
+  fc->set_size(word_sz);
+  fc->link_prev(NULL);    // idempotent wrt free-ness, see assert above
+  fc->link_next(NULL);
   _bt.verify_not_unallocated((HeapWord*)fc, fc->size());
   _bt.verify_single_block((HeapWord*)fc, fc->size());
-  fl->returnChunkAtHead(fc);
+  fl->return_chunk_at_head(fc);
 
   assert((ssize_t)n > 0 && (ssize_t)n == fl->count(), "Incorrect number of blocks");
   {
     // Update the stats for this block size.
     MutexLockerEx x(_indexedFreeListParLocks[word_sz],
                     Mutex::_no_safepoint_check_flag);
-    const ssize_t births = _indexedFreeList[word_sz].splitBirths() + n;
-    _indexedFreeList[word_sz].set_splitBirths(births);
+    const ssize_t births = _indexedFreeList[word_sz].split_births() + n;
+    _indexedFreeList[word_sz].set_split_births(births);
     // ssize_t new_surplus = _indexedFreeList[word_sz].surplus() + n;
     // _indexedFreeList[word_sz].set_surplus(new_surplus);
   }
--- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.hpp	Wed Jul 05 18:09:43 2017 +0200
+++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.hpp	Wed Jul 05 18:10:27 2017 +0200
@@ -25,10 +25,10 @@
 #ifndef SHARE_VM_GC_IMPLEMENTATION_CONCURRENTMARKSWEEP_COMPACTIBLEFREELISTSPACE_HPP
 #define SHARE_VM_GC_IMPLEMENTATION_CONCURRENTMARKSWEEP_COMPACTIBLEFREELISTSPACE_HPP
 
-#include "gc_implementation/concurrentMarkSweep/binaryTreeDictionary.hpp"
-#include "gc_implementation/concurrentMarkSweep/freeList.hpp"
 #include "gc_implementation/concurrentMarkSweep/promotionInfo.hpp"
+#include "memory/binaryTreeDictionary.hpp"
 #include "memory/blockOffsetTable.inline.hpp"
+#include "memory/freeList.hpp"
 #include "memory/space.hpp"
 
 // Classes in support of keeping track of promotions into a non-Contiguous
@@ -129,10 +129,10 @@
   // Linear allocation blocks
   LinearAllocBlock _smallLinearAllocBlock;
 
-  FreeBlockDictionary::DictionaryChoice _dictionaryChoice;
-  FreeBlockDictionary* _dictionary;    // ptr to dictionary for large size blocks
+  FreeBlockDictionary<FreeChunk>::DictionaryChoice _dictionaryChoice;
+  FreeBlockDictionary<FreeChunk>* _dictionary;    // ptr to dictionary for large size blocks
 
-  FreeList _indexedFreeList[IndexSetSize];
+  FreeList<FreeChunk> _indexedFreeList[IndexSetSize];
                                        // indexed array for small size blocks
   // allocation stategy
   bool       _fitStrategy;      // Use best fit strategy.
@@ -169,7 +169,7 @@
   // If the count of "fl" is negative, it's absolute value indicates a
   // number of free chunks that had been previously "borrowed" from global
   // list of size "word_sz", and must now be decremented.
-  void par_get_chunk_of_blocks(size_t word_sz, size_t n, FreeList* fl);
+  void par_get_chunk_of_blocks(size_t word_sz, size_t n, FreeList<FreeChunk>* fl);
 
   // Allocation helper functions
   // Allocate using a strategy that takes from the indexed free lists
@@ -215,7 +215,7 @@
   // and return it.  The split off remainder is returned to
   // the free lists.  The old name for getFromListGreater
   // was lookInListGreater.
-  FreeChunk* getFromListGreater(FreeList* fl, size_t numWords);
+  FreeChunk* getFromListGreater(FreeList<FreeChunk>* fl, size_t numWords);
   // Get a chunk in the indexed free list or dictionary,
   // by considering a larger chunk and splitting it.
   FreeChunk* getChunkFromGreater(size_t numWords);
@@ -286,10 +286,10 @@
   // Constructor...
   CompactibleFreeListSpace(BlockOffsetSharedArray* bs, MemRegion mr,
                            bool use_adaptive_freelists,
-                           FreeBlockDictionary::DictionaryChoice);
+                           FreeBlockDictionary<FreeChunk>::DictionaryChoice);
   // accessors
   bool bestFitFirst() { return _fitStrategy == FreeBlockBestFitFirst; }
-  FreeBlockDictionary* dictionary() const { return _dictionary; }
+  FreeBlockDictionary<FreeChunk>* dictionary() const { return _dictionary; }
   HeapWord* nearLargestChunk() const { return _nearLargestChunk; }
   void set_nearLargestChunk(HeapWord* v) { _nearLargestChunk = v; }
 
@@ -499,7 +499,7 @@
   // Verify that the given chunk is in the free lists:
   // i.e. either the binary tree dictionary, the indexed free lists
   // or the linear allocation block.
-  bool verifyChunkInFreeLists(FreeChunk* fc) const;
+  bool verify_chunk_in_free_list(FreeChunk* fc) const;
   // Verify that the given chunk is the linear allocation block
   bool verify_chunk_is_linear_alloc_block(FreeChunk* fc) const;
   // Do some basic checks on the the free lists.
@@ -608,7 +608,7 @@
   void coalDeath(size_t size);
   void smallSplitBirth(size_t size);
   void smallSplitDeath(size_t size);
-  void splitBirth(size_t size);
+  void split_birth(size_t size);
   void splitDeath(size_t size);
   void split(size_t from, size_t to1);
 
@@ -622,7 +622,7 @@
   CompactibleFreeListSpace* _cfls;
 
   // Our local free lists.
-  FreeList _indexedFreeList[CompactibleFreeListSpace::IndexSetSize];
+  FreeList<FreeChunk> _indexedFreeList[CompactibleFreeListSpace::IndexSetSize];
 
   // Initialized from a command-line arg.
 
@@ -635,7 +635,7 @@
   size_t        _num_blocks        [CompactibleFreeListSpace::IndexSetSize];
 
   // Internal work method
-  void get_from_global_pool(size_t word_sz, FreeList* fl);
+  void get_from_global_pool(size_t word_sz, FreeList<FreeChunk>* fl);
 
 public:
   CFLS_LAB(CompactibleFreeListSpace* cfls);
--- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp	Wed Jul 05 18:09:43 2017 +0200
+++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp	Wed Jul 05 18:10:27 2017 +0200
@@ -188,7 +188,7 @@
 ConcurrentMarkSweepGeneration::ConcurrentMarkSweepGeneration(
      ReservedSpace rs, size_t initial_byte_size, int level,
      CardTableRS* ct, bool use_adaptive_freelists,
-     FreeBlockDictionary::DictionaryChoice dictionaryChoice) :
+     FreeBlockDictionary<FreeChunk>::DictionaryChoice dictionaryChoice) :
   CardGeneration(rs, initial_byte_size, level, ct),
   _dilatation_factor(((double)MinChunkSize)/((double)(CollectedHeap::min_fill_size()))),
   _debug_collection_type(Concurrent_collection_type)
@@ -1026,7 +1026,7 @@
     // its mark-bit or P-bits not yet set. Such objects need
     // to be safely navigable by block_start().
     assert(oop(res)->klass_or_null() == NULL, "Object should be uninitialized here.");
-    assert(!((FreeChunk*)res)->isFree(), "Error, block will look free but show wrong size");
+    assert(!((FreeChunk*)res)->is_free(), "Error, block will look free but show wrong size");
     collector()->direct_allocated(res, adjustedSize);
     _direct_allocated_words += adjustedSize;
     // allocation counters
@@ -1391,7 +1391,7 @@
   oop obj = oop(obj_ptr);
   OrderAccess::storestore();
   assert(obj->klass_or_null() == NULL, "Object should be uninitialized here.");
-  assert(!((FreeChunk*)obj_ptr)->isFree(), "Error, block will look free but show wrong size");
+  assert(!((FreeChunk*)obj_ptr)->is_free(), "Error, block will look free but show wrong size");
   // IMPORTANT: See note on object initialization for CMS above.
   // Otherwise, copy the object.  Here we must be careful to insert the
   // klass pointer last, since this marks the block as an allocated object.
@@ -1400,7 +1400,7 @@
   // Restore the mark word copied above.
   obj->set_mark(m);
   assert(obj->klass_or_null() == NULL, "Object should be uninitialized here.");
-  assert(!((FreeChunk*)obj_ptr)->isFree(), "Error, block will look free but show wrong size");
+  assert(!((FreeChunk*)obj_ptr)->is_free(), "Error, block will look free but show wrong size");
   OrderAccess::storestore();
 
   if (UseCompressedOops) {
@@ -1421,7 +1421,7 @@
     promoInfo->track((PromotedObject*)obj, old->klass());
   }
   assert(obj->klass_or_null() == NULL, "Object should be uninitialized here.");
-  assert(!((FreeChunk*)obj_ptr)->isFree(), "Error, block will look free but show wrong size");
+  assert(!((FreeChunk*)obj_ptr)->is_free(), "Error, block will look free but show wrong size");
   assert(old->is_oop(), "Will use and dereference old klass ptr below");
 
   // Finally, install the klass pointer (this should be volatile).
@@ -2034,7 +2034,7 @@
            pointer_delta(cms_space->end(), cms_space->compaction_top())
            * HeapWordSize,
       "All the free space should be compacted into one chunk at top");
-    assert(cms_space->dictionary()->totalChunkSize(
+    assert(cms_space->dictionary()->total_chunk_size(
                                       debug_only(cms_space->freelistLock())) == 0 ||
            cms_space->totalSizeInIndexedFreeLists() == 0,
       "All the free space should be in a single chunk");
@@ -6131,7 +6131,7 @@
   double nearLargestPercent = FLSLargestBlockCoalesceProximity;
   HeapWord*  minAddr        = _cmsSpace->bottom();
   HeapWord*  largestAddr    =
-    (HeapWord*) _cmsSpace->dictionary()->findLargestDict();
+    (HeapWord*) _cmsSpace->dictionary()->find_largest_dict();
   if (largestAddr == NULL) {
     // The dictionary appears to be empty.  In this case
     // try to coalesce at the end of the heap.
@@ -7906,7 +7906,7 @@
     _last_fc = NULL;
 
     _sp->initializeIndexedFreeListArrayReturnedBytes();
-    _sp->dictionary()->initializeDictReturnedBytes();
+    _sp->dictionary()->initialize_dict_returned_bytes();
   )
   assert(_limit >= _sp->bottom() && _limit <= _sp->end(),
          "sweep _limit out of bounds");
@@ -7954,13 +7954,13 @@
 
     if (PrintCMSStatistics && CMSVerifyReturnedBytes) {
       size_t indexListReturnedBytes = _sp->sumIndexedFreeListArrayReturnedBytes();
-      size_t dictReturnedBytes = _sp->dictionary()->sumDictReturnedBytes();
-      size_t returnedBytes = indexListReturnedBytes + dictReturnedBytes;
-      gclog_or_tty->print("Returned "SIZE_FORMAT" bytes", returnedBytes);
+      size_t dict_returned_bytes = _sp->dictionary()->sum_dict_returned_bytes();
+      size_t returned_bytes = indexListReturnedBytes + dict_returned_bytes;
+      gclog_or_tty->print("Returned "SIZE_FORMAT" bytes", returned_bytes);
       gclog_or_tty->print("   Indexed List Returned "SIZE_FORMAT" bytes",
         indexListReturnedBytes);
       gclog_or_tty->print_cr("        Dictionary Returned "SIZE_FORMAT" bytes",
-        dictReturnedBytes);
+        dict_returned_bytes);
     }
   }
   if (CMSTraceSweeper) {
@@ -7985,9 +7985,9 @@
   if (CMSTestInFreeList) {
     if (freeRangeInFreeLists) {
       FreeChunk* fc = (FreeChunk*) freeFinger;
-      assert(fc->isFree(), "A chunk on the free list should be free.");
+      assert(fc->is_free(), "A chunk on the free list should be free.");
       assert(fc->size() > 0, "Free range should have a size");
-      assert(_sp->verifyChunkInFreeLists(fc), "Chunk is not in free lists");
+      assert(_sp->verify_chunk_in_free_list(fc), "Chunk is not in free lists");
     }
   }
 }
@@ -8057,7 +8057,7 @@
   assert(addr < _limit, "sweep invariant");
   // check if we should yield
   do_yield_check(addr);
-  if (fc->isFree()) {
+  if (fc->is_free()) {
     // Chunk that is already free
     res = fc->size();
     do_already_free_chunk(fc);
@@ -8145,7 +8145,7 @@
   // Chunks that cannot be coalesced are not in the
   // free lists.
   if (CMSTestInFreeList && !fc->cantCoalesce()) {
-    assert(_sp->verifyChunkInFreeLists(fc),
+    assert(_sp->verify_chunk_in_free_list(fc),
       "free chunk should be in free lists");
   }
   // a chunk that is already free, should not have been
@@ -8171,7 +8171,7 @@
         FreeChunk* nextChunk = (FreeChunk*)(addr + size);
         assert((HeapWord*)nextChunk <= _sp->end(), "Chunk size out of bounds?");
         if ((HeapWord*)nextChunk < _sp->end() &&     // There is another free chunk to the right ...
-            nextChunk->isFree()               &&     // ... which is free...
+            nextChunk->is_free()               &&     // ... which is free...
             nextChunk->cantCoalesce()) {             // ... but can't be coalesced
           // nothing to do
         } else {
@@ -8203,7 +8203,7 @@
           assert(ffc->size() == pointer_delta(addr, freeFinger()),
             "Size of free range is inconsistent with chunk size.");
           if (CMSTestInFreeList) {
-            assert(_sp->verifyChunkInFreeLists(ffc),
+            assert(_sp->verify_chunk_in_free_list(ffc),
               "free range is not in free lists");
           }
           _sp->removeFreeChunkFromFreeLists(ffc);
@@ -8262,7 +8262,7 @@
         assert(ffc->size() == pointer_delta(addr, freeFinger()),
           "Size of free range is inconsistent with chunk size.");
         if (CMSTestInFreeList) {
-          assert(_sp->verifyChunkInFreeLists(ffc),
+          assert(_sp->verify_chunk_in_free_list(ffc),
             "free range is not in free lists");
         }
         _sp->removeFreeChunkFromFreeLists(ffc);
@@ -8351,11 +8351,11 @@
                                                  size_t chunkSize) {
   // do_post_free_or_garbage_chunk() should only be called in the case
   // of the adaptive free list allocator.
-  const bool fcInFreeLists = fc->isFree();
+  const bool fcInFreeLists = fc->is_free();
   assert(_sp->adaptive_freelists(), "Should only be used in this case.");
   assert((HeapWord*)fc <= _limit, "sweep invariant");
   if (CMSTestInFreeList && fcInFreeLists) {
-    assert(_sp->verifyChunkInFreeLists(fc), "free chunk is not in free lists");
+    assert(_sp->verify_chunk_in_free_list(fc), "free chunk is not in free lists");
   }
 
   if (CMSTraceSweeper) {
@@ -8410,7 +8410,7 @@
       assert(ffc->size() == pointer_delta(fc_addr, freeFinger()),
         "Size of free range is inconsistent with chunk size.");
       if (CMSTestInFreeList) {
-        assert(_sp->verifyChunkInFreeLists(ffc),
+        assert(_sp->verify_chunk_in_free_list(ffc),
           "Chunk is not in free lists");
       }
       _sp->coalDeath(ffc->size());
@@ -8459,7 +8459,7 @@
                  " when examining fc = " PTR_FORMAT "(" SIZE_FORMAT ")",
                  _limit, _sp->bottom(), _sp->end(), fc, chunk_size));
   if (eob >= _limit) {
-    assert(eob == _limit || fc->isFree(), "Only a free chunk should allow us to cross over the limit");
+    assert(eob == _limit || fc->is_free(), "Only a free chunk should allow us to cross over the limit");
     if (CMSTraceSweeper) {
       gclog_or_tty->print_cr("_limit " PTR_FORMAT " reached or crossed by block "
                              "[" PTR_FORMAT "," PTR_FORMAT ") in space "
@@ -8482,8 +8482,8 @@
   if (!freeRangeInFreeLists()) {
     if (CMSTestInFreeList) {
       FreeChunk* fc = (FreeChunk*) chunk;
-      fc->setSize(size);
-      assert(!_sp->verifyChunkInFreeLists(fc),
+      fc->set_size(size);
+      assert(!_sp->verify_chunk_in_free_list(fc),
         "chunk should not be in free lists yet");
     }
     if (CMSTraceSweeper) {
@@ -8557,8 +8557,8 @@
 // This is actually very useful in a product build if it can
 // be called from the debugger.  Compile it into the product
 // as needed.
-bool debug_verifyChunkInFreeLists(FreeChunk* fc) {
-  return debug_cms_space->verifyChunkInFreeLists(fc);
+bool debug_verify_chunk_in_free_list(FreeChunk* fc) {
+  return debug_cms_space->verify_chunk_in_free_list(fc);
 }
 #endif
 
@@ -9255,7 +9255,7 @@
       size_t chunk_at_end_old_size = chunk_at_end->size();
       assert(chunk_at_end_old_size >= word_size_change,
         "Shrink is too large");
-      chunk_at_end->setSize(chunk_at_end_old_size -
+      chunk_at_end->set_size(chunk_at_end_old_size -
                           word_size_change);
       _cmsSpace->freed((HeapWord*) chunk_at_end->end(),
         word_size_change);
--- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp	Wed Jul 05 18:09:43 2017 +0200
+++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp	Wed Jul 05 18:10:27 2017 +0200
@@ -25,10 +25,10 @@
 #ifndef SHARE_VM_GC_IMPLEMENTATION_CONCURRENTMARKSWEEP_CONCURRENTMARKSWEEPGENERATION_HPP
 #define SHARE_VM_GC_IMPLEMENTATION_CONCURRENTMARKSWEEP_CONCURRENTMARKSWEEPGENERATION_HPP
 
-#include "gc_implementation/concurrentMarkSweep/freeBlockDictionary.hpp"
 #include "gc_implementation/shared/gSpaceCounters.hpp"
 #include "gc_implementation/shared/gcStats.hpp"
 #include "gc_implementation/shared/generationCounters.hpp"
+#include "memory/freeBlockDictionary.hpp"
 #include "memory/generation.hpp"
 #include "runtime/mutexLocker.hpp"
 #include "runtime/virtualspace.hpp"
@@ -1106,7 +1106,7 @@
   ConcurrentMarkSweepGeneration(ReservedSpace rs, size_t initial_byte_size,
                                 int level, CardTableRS* ct,
                                 bool use_adaptive_freelists,
-                                FreeBlockDictionary::DictionaryChoice);
+                                FreeBlockDictionary<FreeChunk>::DictionaryChoice);
 
   // Accessors
   CMSCollector* collector() const { return _collector; }
@@ -1328,7 +1328,7 @@
   ASConcurrentMarkSweepGeneration(ReservedSpace rs, size_t initial_byte_size,
                                   int level, CardTableRS* ct,
                                   bool use_adaptive_freelists,
-                                  FreeBlockDictionary::DictionaryChoice
+                                  FreeBlockDictionary<FreeChunk>::DictionaryChoice
                                     dictionaryChoice) :
     ConcurrentMarkSweepGeneration(rs, initial_byte_size, level, ct,
       use_adaptive_freelists, dictionaryChoice) {}
--- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/freeBlockDictionary.cpp	Wed Jul 05 18:09:43 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,60 +0,0 @@
-/*
- * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-
-#include "precompiled.hpp"
-#include "gc_implementation/concurrentMarkSweep/freeBlockDictionary.hpp"
-#ifdef TARGET_OS_FAMILY_linux
-# include "thread_linux.inline.hpp"
-#endif
-#ifdef TARGET_OS_FAMILY_solaris
-# include "thread_solaris.inline.hpp"
-#endif
-#ifdef TARGET_OS_FAMILY_windows
-# include "thread_windows.inline.hpp"
-#endif
-#ifdef TARGET_OS_FAMILY_bsd
-# include "thread_bsd.inline.hpp"
-#endif
-
-#ifndef PRODUCT
-Mutex* FreeBlockDictionary::par_lock() const {
-  return _lock;
-}
-
-void FreeBlockDictionary::set_par_lock(Mutex* lock) {
-  _lock = lock;
-}
-
-void FreeBlockDictionary::verify_par_locked() const {
-#ifdef ASSERT
-  if (ParallelGCThreads > 0) {
-    Thread* myThread = Thread::current();
-    if (myThread->is_GC_task_thread()) {
-      assert(par_lock() != NULL, "Should be using locking?");
-      assert_lock_strong(par_lock());
-    }
-  }
-#endif // ASSERT
-}
-#endif
--- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/freeBlockDictionary.hpp	Wed Jul 05 18:09:43 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,103 +0,0 @@
-/*
- * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-
-#ifndef SHARE_VM_GC_IMPLEMENTATION_CONCURRENTMARKSWEEP_FREEBLOCKDICTIONARY_HPP
-#define SHARE_VM_GC_IMPLEMENTATION_CONCURRENTMARKSWEEP_FREEBLOCKDICTIONARY_HPP
-
-#include "gc_implementation/concurrentMarkSweep/freeChunk.hpp"
-#include "memory/allocation.hpp"
-#include "memory/memRegion.hpp"
-#include "runtime/mutex.hpp"
-#include "utilities/debug.hpp"
-#include "utilities/globalDefinitions.hpp"
-#include "utilities/ostream.hpp"
-
-// A FreeBlockDictionary is an abstract superclass that will allow
-// a number of alternative implementations in the future.
-class FreeBlockDictionary: public CHeapObj {
- public:
-  enum Dither {
-    atLeast,
-    exactly,
-    roughly
-  };
-  enum DictionaryChoice {
-    dictionaryBinaryTree = 0,
-    dictionarySplayTree  = 1,
-    dictionarySkipList   = 2
-  };
-
- private:
-  NOT_PRODUCT(Mutex* _lock;)
-
- public:
-  virtual void       removeChunk(FreeChunk* fc) = 0;
-  virtual FreeChunk* getChunk(size_t size, Dither dither = atLeast) = 0;
-  virtual void       returnChunk(FreeChunk* chunk) = 0;
-  virtual size_t     totalChunkSize(debug_only(const Mutex* lock)) const = 0;
-  virtual size_t     maxChunkSize()   const = 0;
-  virtual size_t     minSize()        const = 0;
-  // Reset the dictionary to the initial conditions for a single
-  // block.
-  virtual void       reset(HeapWord* addr, size_t size) = 0;
-  virtual void       reset() = 0;
-
-  virtual void       dictCensusUpdate(size_t size, bool split, bool birth) = 0;
-  virtual bool       coalDictOverPopulated(size_t size) = 0;
-  virtual void       beginSweepDictCensus(double coalSurplusPercent,
-                       float inter_sweep_current, float inter_sweep_estimate,
-                       float intra__sweep_current) = 0;
-  virtual void       endSweepDictCensus(double splitSurplusPercent) = 0;
-  virtual FreeChunk* findLargestDict() const = 0;
-  // verify that the given chunk is in the dictionary.
-  virtual bool verifyChunkInFreeLists(FreeChunk* tc) const = 0;
-
-  // Sigma_{all_free_blocks} (block_size^2)
-  virtual double sum_of_squared_block_sizes() const = 0;
-
-  virtual FreeChunk* find_chunk_ends_at(HeapWord* target) const = 0;
-  virtual void inc_totalSize(size_t v) = 0;
-  virtual void dec_totalSize(size_t v) = 0;
-
-  NOT_PRODUCT (
-    virtual size_t   sumDictReturnedBytes() = 0;
-    virtual void     initializeDictReturnedBytes() = 0;
-    virtual size_t   totalCount() = 0;
-  )
-
-  virtual void       reportStatistics() const {
-    gclog_or_tty->print("No statistics available");
-  }
-
-  virtual void       printDictCensus() const = 0;
-  virtual void       print_free_lists(outputStream* st) const = 0;
-
-  virtual void       verify()         const = 0;
-
-  Mutex* par_lock()                const PRODUCT_RETURN0;
-  void   set_par_lock(Mutex* lock)       PRODUCT_RETURN;
-  void   verify_par_locked()       const PRODUCT_RETURN;
-};
-
-#endif // SHARE_VM_GC_IMPLEMENTATION_CONCURRENTMARKSWEEP_FREEBLOCKDICTIONARY_HPP
--- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/freeChunk.cpp	Wed Jul 05 18:09:43 2017 +0200
+++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/freeChunk.cpp	Wed Jul 05 18:10:27 2017 +0200
@@ -23,7 +23,8 @@
  */
 
 #include "precompiled.hpp"
-#include "gc_implementation/concurrentMarkSweep/freeBlockDictionary.hpp"
+#include "gc_implementation/concurrentMarkSweep/freeChunk.hpp"
+#include "memory/freeBlockDictionary.hpp"
 #include "utilities/copy.hpp"
 
 #ifndef PRODUCT
--- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/freeChunk.hpp	Wed Jul 05 18:09:43 2017 +0200
+++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/freeChunk.hpp	Wed Jul 05 18:10:27 2017 +0200
@@ -75,20 +75,20 @@
     // calls.  We really want the read of _mark and _prev from this pointer
     // to be volatile but making the fields volatile causes all sorts of
     // compilation errors.
-    return ((volatile FreeChunk*)addr)->isFree();
+    return ((volatile FreeChunk*)addr)->is_free();
   }
 
-  bool isFree() const volatile {
+  bool is_free() const volatile {
     LP64_ONLY(if (UseCompressedOops) return mark()->is_cms_free_chunk(); else)
     return (((intptr_t)_prev) & 0x1) == 0x1;
   }
   bool cantCoalesce() const {
-    assert(isFree(), "can't get coalesce bit on not free");
+    assert(is_free(), "can't get coalesce bit on not free");
     return (((intptr_t)_prev) & 0x2) == 0x2;
   }
   void dontCoalesce() {
     // the block should be free
-    assert(isFree(), "Should look like a free block");
+    assert(is_free(), "Should look like a free block");
     _prev = (FreeChunk*)(((intptr_t)_prev) | 0x2);
   }
   FreeChunk* prev() const {
@@ -103,23 +103,23 @@
     LP64_ONLY(if (UseCompressedOops) return mark()->get_size(); else )
     return _size;
   }
-  void setSize(size_t sz) {
+  void set_size(size_t sz) {
     LP64_ONLY(if (UseCompressedOops) set_mark(markOopDesc::set_size_and_free(sz)); else )
     _size = sz;
   }
 
   FreeChunk* next()   const { return _next; }
 
-  void linkAfter(FreeChunk* ptr) {
-    linkNext(ptr);
-    if (ptr != NULL) ptr->linkPrev(this);
+  void link_after(FreeChunk* ptr) {
+    link_next(ptr);
+    if (ptr != NULL) ptr->link_prev(this);
   }
-  void linkNext(FreeChunk* ptr) { _next = ptr; }
-  void linkPrev(FreeChunk* ptr) {
+  void link_next(FreeChunk* ptr) { _next = ptr; }
+  void link_prev(FreeChunk* ptr) {
     LP64_ONLY(if (UseCompressedOops) _prev = ptr; else)
     _prev = (FreeChunk*)((intptr_t)ptr | 0x1);
   }
-  void clearNext()              { _next = NULL; }
+  void clear_next()              { _next = NULL; }
   void markNotFree() {
     // Set _prev (klass) to null before (if) clearing the mark word below
     _prev = NULL;
@@ -129,7 +129,7 @@
       set_mark(markOopDesc::prototype());
     }
 #endif
-    assert(!isFree(), "Error");
+    assert(!is_free(), "Error");
   }
 
   // Return the address past the end of this chunk
--- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/freeList.cpp	Wed Jul 05 18:09:43 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,360 +0,0 @@
-/*
- * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-
-#include "precompiled.hpp"
-#include "gc_implementation/concurrentMarkSweep/freeBlockDictionary.hpp"
-#include "gc_implementation/concurrentMarkSweep/freeList.hpp"
-#include "memory/sharedHeap.hpp"
-#include "runtime/globals.hpp"
-#include "runtime/mutex.hpp"
-#include "runtime/vmThread.hpp"
-
-// Free list.  A FreeList is used to access a linked list of chunks
-// of space in the heap.  The head and tail are maintained so that
-// items can be (as in the current implementation) added at the
-// at the tail of the list and removed from the head of the list to
-// maintain a FIFO queue.
-
-FreeList::FreeList() :
-  _head(NULL), _tail(NULL)
-#ifdef ASSERT
-  , _protecting_lock(NULL)
-#endif
-{
-  _size         = 0;
-  _count        = 0;
-  _hint         = 0;
-  init_statistics();
-}
-
-FreeList::FreeList(FreeChunk* fc) :
-  _head(fc), _tail(fc)
-#ifdef ASSERT
-  , _protecting_lock(NULL)
-#endif
-{
-  _size         = fc->size();
-  _count        = 1;
-  _hint         = 0;
-  init_statistics();
-#ifndef PRODUCT
-  _allocation_stats.set_returnedBytes(size() * HeapWordSize);
-#endif
-}
-
-FreeList::FreeList(HeapWord* addr, size_t size) :
-  _head((FreeChunk*) addr), _tail((FreeChunk*) addr)
-#ifdef ASSERT
-  , _protecting_lock(NULL)
-#endif
-{
-  assert(size > sizeof(FreeChunk), "size is too small");
-  head()->setSize(size);
-  _size         = size;
-  _count        = 1;
-  init_statistics();
-#ifndef PRODUCT
-  _allocation_stats.set_returnedBytes(_size * HeapWordSize);
-#endif
-}
-
-void FreeList::reset(size_t hint) {
-  set_count(0);
-  set_head(NULL);
-  set_tail(NULL);
-  set_hint(hint);
-}
-
-void FreeList::init_statistics(bool split_birth) {
-  _allocation_stats.initialize(split_birth);
-}
-
-FreeChunk* FreeList::getChunkAtHead() {
-  assert_proper_lock_protection();
-  assert(head() == NULL || head()->prev() == NULL, "list invariant");
-  assert(tail() == NULL || tail()->next() == NULL, "list invariant");
-  FreeChunk* fc = head();
-  if (fc != NULL) {
-    FreeChunk* nextFC = fc->next();
-    if (nextFC != NULL) {
-      // The chunk fc being removed has a "next".  Set the "next" to the
-      // "prev" of fc.
-      nextFC->linkPrev(NULL);
-    } else { // removed tail of list
-      link_tail(NULL);
-    }
-    link_head(nextFC);
-    decrement_count();
-  }
-  assert(head() == NULL || head()->prev() == NULL, "list invariant");
-  assert(tail() == NULL || tail()->next() == NULL, "list invariant");
-  return fc;
-}
-
-
-void FreeList::getFirstNChunksFromList(size_t n, FreeList* fl) {
-  assert_proper_lock_protection();
-  assert(fl->count() == 0, "Precondition");
-  if (count() > 0) {
-    int k = 1;
-    fl->set_head(head()); n--;
-    FreeChunk* tl = head();
-    while (tl->next() != NULL && n > 0) {
-      tl = tl->next(); n--; k++;
-    }
-    assert(tl != NULL, "Loop Inv.");
-
-    // First, fix up the list we took from.
-    FreeChunk* new_head = tl->next();
-    set_head(new_head);
-    set_count(count() - k);
-    if (new_head == NULL) {
-      set_tail(NULL);
-    } else {
-      new_head->linkPrev(NULL);
-    }
-    // Now we can fix up the tail.
-    tl->linkNext(NULL);
-    // And return the result.
-    fl->set_tail(tl);
-    fl->set_count(k);
-  }
-}
-
-// Remove this chunk from the list
-void FreeList::removeChunk(FreeChunk*fc) {
-   assert_proper_lock_protection();
-   assert(head() != NULL, "Remove from empty list");
-   assert(fc != NULL, "Remove a NULL chunk");
-   assert(size() == fc->size(), "Wrong list");
-   assert(head() == NULL || head()->prev() == NULL, "list invariant");
-   assert(tail() == NULL || tail()->next() == NULL, "list invariant");
-
-   FreeChunk* prevFC = fc->prev();
-   FreeChunk* nextFC = fc->next();
-   if (nextFC != NULL) {
-     // The chunk fc being removed has a "next".  Set the "next" to the
-     // "prev" of fc.
-     nextFC->linkPrev(prevFC);
-   } else { // removed tail of list
-     link_tail(prevFC);
-   }
-   if (prevFC == NULL) { // removed head of list
-     link_head(nextFC);
-     assert(nextFC == NULL || nextFC->prev() == NULL,
-       "Prev of head should be NULL");
-   } else {
-     prevFC->linkNext(nextFC);
-     assert(tail() != prevFC || prevFC->next() == NULL,
-       "Next of tail should be NULL");
-   }
-   decrement_count();
-   assert(((head() == NULL) + (tail() == NULL) + (count() == 0)) % 3 == 0,
-          "H/T/C Inconsistency");
-   // clear next and prev fields of fc, debug only
-   NOT_PRODUCT(
-     fc->linkPrev(NULL);
-     fc->linkNext(NULL);
-   )
-   assert(fc->isFree(), "Should still be a free chunk");
-   assert(head() == NULL || head()->prev() == NULL, "list invariant");
-   assert(tail() == NULL || tail()->next() == NULL, "list invariant");
-   assert(head() == NULL || head()->size() == size(), "wrong item on list");
-   assert(tail() == NULL || tail()->size() == size(), "wrong item on list");
-}
-
-// Add this chunk at the head of the list.
-void FreeList::returnChunkAtHead(FreeChunk* chunk, bool record_return) {
-  assert_proper_lock_protection();
-  assert(chunk != NULL, "insert a NULL chunk");
-  assert(size() == chunk->size(), "Wrong size");
-  assert(head() == NULL || head()->prev() == NULL, "list invariant");
-  assert(tail() == NULL || tail()->next() == NULL, "list invariant");
-
-  FreeChunk* oldHead = head();
-  assert(chunk != oldHead, "double insertion");
-  chunk->linkAfter(oldHead);
-  link_head(chunk);
-  if (oldHead == NULL) { // only chunk in list
-    assert(tail() == NULL, "inconsistent FreeList");
-    link_tail(chunk);
-  }
-  increment_count(); // of # of chunks in list
-  DEBUG_ONLY(
-    if (record_return) {
-      increment_returnedBytes_by(size()*HeapWordSize);
-    }
-  )
-  assert(head() == NULL || head()->prev() == NULL, "list invariant");
-  assert(tail() == NULL || tail()->next() == NULL, "list invariant");
-  assert(head() == NULL || head()->size() == size(), "wrong item on list");
-  assert(tail() == NULL || tail()->size() == size(), "wrong item on list");
-}
-
-void FreeList::returnChunkAtHead(FreeChunk* chunk) {
-  assert_proper_lock_protection();
-  returnChunkAtHead(chunk, true);
-}
-
-// Add this chunk at the tail of the list.
-void FreeList::returnChunkAtTail(FreeChunk* chunk, bool record_return) {
-  assert_proper_lock_protection();
-  assert(head() == NULL || head()->prev() == NULL, "list invariant");
-  assert(tail() == NULL || tail()->next() == NULL, "list invariant");
-  assert(chunk != NULL, "insert a NULL chunk");
-  assert(size() == chunk->size(), "wrong size");
-
-  FreeChunk* oldTail = tail();
-  assert(chunk != oldTail, "double insertion");
-  if (oldTail != NULL) {
-    oldTail->linkAfter(chunk);
-  } else { // only chunk in list
-    assert(head() == NULL, "inconsistent FreeList");
-    link_head(chunk);
-  }
-  link_tail(chunk);
-  increment_count();  // of # of chunks in list
-  DEBUG_ONLY(
-    if (record_return) {
-      increment_returnedBytes_by(size()*HeapWordSize);
-    }
-  )
-  assert(head() == NULL || head()->prev() == NULL, "list invariant");
-  assert(tail() == NULL || tail()->next() == NULL, "list invariant");
-  assert(head() == NULL || head()->size() == size(), "wrong item on list");
-  assert(tail() == NULL || tail()->size() == size(), "wrong item on list");
-}
-
-void FreeList::returnChunkAtTail(FreeChunk* chunk) {
-  returnChunkAtTail(chunk, true);
-}
-
-void FreeList::prepend(FreeList* fl) {
-  assert_proper_lock_protection();
-  if (fl->count() > 0) {
-    if (count() == 0) {
-      set_head(fl->head());
-      set_tail(fl->tail());
-      set_count(fl->count());
-    } else {
-      // Both are non-empty.
-      FreeChunk* fl_tail = fl->tail();
-      FreeChunk* this_head = head();
-      assert(fl_tail->next() == NULL, "Well-formedness of fl");
-      fl_tail->linkNext(this_head);
-      this_head->linkPrev(fl_tail);
-      set_head(fl->head());
-      set_count(count() + fl->count());
-    }
-    fl->set_head(NULL);
-    fl->set_tail(NULL);
-    fl->set_count(0);
-  }
-}
-
-// verifyChunkInFreeLists() is used to verify that an item is in this free list.
-// It is used as a debugging aid.
-bool FreeList::verifyChunkInFreeLists(FreeChunk* fc) const {
-  // This is an internal consistency check, not part of the check that the
-  // chunk is in the free lists.
-  guarantee(fc->size() == size(), "Wrong list is being searched");
-  FreeChunk* curFC = head();
-  while (curFC) {
-    // This is an internal consistency check.
-    guarantee(size() == curFC->size(), "Chunk is in wrong list.");
-    if (fc == curFC) {
-      return true;
-    }
-    curFC = curFC->next();
-  }
-  return false;
-}
-
-#ifndef PRODUCT
-void FreeList::verify_stats() const {
-  // The +1 of the LH comparand is to allow some "looseness" in
-  // checking: we usually call this interface when adding a block
-  // and we'll subsequently update the stats; we cannot update the
-  // stats beforehand because in the case of the large-block BT
-  // dictionary for example, this might be the first block and
-  // in that case there would be no place that we could record
-  // the stats (which are kept in the block itself).
-  assert((_allocation_stats.prevSweep() + _allocation_stats.splitBirths()
-          + _allocation_stats.coalBirths() + 1)   // Total Production Stock + 1
-         >= (_allocation_stats.splitDeaths() + _allocation_stats.coalDeaths()
-             + (ssize_t)count()),                // Total Current Stock + depletion
-         err_msg("FreeList " PTR_FORMAT " of size " SIZE_FORMAT
-                 " violates Conservation Principle: "
-                 "prevSweep(" SIZE_FORMAT ")"
-                 " + splitBirths(" SIZE_FORMAT ")"
-                 " + coalBirths(" SIZE_FORMAT ") + 1 >= "
-                 " splitDeaths(" SIZE_FORMAT ")"
-                 " coalDeaths(" SIZE_FORMAT ")"
-                 " + count(" SSIZE_FORMAT ")",
-                 this, _size, _allocation_stats.prevSweep(), _allocation_stats.splitBirths(),
-                 _allocation_stats.splitBirths(), _allocation_stats.splitDeaths(),
-                 _allocation_stats.coalDeaths(), count()));
-}
-
-void FreeList::assert_proper_lock_protection_work() const {
-  assert(_protecting_lock != NULL, "Don't call this directly");
-  assert(ParallelGCThreads > 0, "Don't call this directly");
-  Thread* thr = Thread::current();
-  if (thr->is_VM_thread() || thr->is_ConcurrentGC_thread()) {
-    // assert that we are holding the freelist lock
-  } else if (thr->is_GC_task_thread()) {
-    assert(_protecting_lock->owned_by_self(), "FreeList RACE DETECTED");
-  } else if (thr->is_Java_thread()) {
-    assert(!SafepointSynchronize::is_at_safepoint(), "Should not be executing");
-  } else {
-    ShouldNotReachHere();  // unaccounted thread type?
-  }
-}
-#endif
-
-// Print the "label line" for free list stats.
-void FreeList::print_labels_on(outputStream* st, const char* c) {
-  st->print("%16s\t", c);
-  st->print("%14s\t"    "%14s\t"    "%14s\t"    "%14s\t"    "%14s\t"
-            "%14s\t"    "%14s\t"    "%14s\t"    "%14s\t"    "%14s\t"    "\n",
-            "bfrsurp", "surplus", "desired", "prvSwep", "bfrSwep",
-            "count",   "cBirths", "cDeaths", "sBirths", "sDeaths");
-}
-
-// Print the AllocationStats for the given free list. If the second argument
-// to the call is a non-null string, it is printed in the first column;
-// otherwise, if the argument is null (the default), then the size of the
-// (free list) block is printed in the first column.
-void FreeList::print_on(outputStream* st, const char* c) const {
-  if (c != NULL) {
-    st->print("%16s", c);
-  } else {
-    st->print(SIZE_FORMAT_W(16), size());
-  }
-  st->print("\t"
-           SSIZE_FORMAT_W(14) "\t" SSIZE_FORMAT_W(14) "\t" SSIZE_FORMAT_W(14) "\t" SSIZE_FORMAT_W(14) "\t" SSIZE_FORMAT_W(14) "\t"
-           SSIZE_FORMAT_W(14) "\t" SSIZE_FORMAT_W(14) "\t" SSIZE_FORMAT_W(14) "\t" SSIZE_FORMAT_W(14) "\t" SSIZE_FORMAT_W(14) "\n",
-           bfrSurp(),             surplus(),             desired(),             prevSweep(),           beforeSweep(),
-           count(),               coalBirths(),          coalDeaths(),          splitBirths(),         splitDeaths());
-}
--- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/freeList.hpp	Wed Jul 05 18:09:43 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,335 +0,0 @@
-/*
- * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-
-#ifndef SHARE_VM_GC_IMPLEMENTATION_CONCURRENTMARKSWEEP_FREELIST_HPP
-#define SHARE_VM_GC_IMPLEMENTATION_CONCURRENTMARKSWEEP_FREELIST_HPP
-
-#include "gc_implementation/shared/allocationStats.hpp"
-
-class CompactibleFreeListSpace;
-
-// A class for maintaining a free list of FreeChunk's.  The FreeList
-// maintains a the structure of the list (head, tail, etc.) plus
-// statistics for allocations from the list.  The links between items
-// are not part of FreeList.  The statistics are
-// used to make decisions about coalescing FreeChunk's when they
-// are swept during collection.
-//
-// See the corresponding .cpp file for a description of the specifics
-// for that implementation.
-
-class Mutex;
-class TreeList;
-
-class FreeList VALUE_OBJ_CLASS_SPEC {
-  friend class CompactibleFreeListSpace;
-  friend class VMStructs;
-  friend class PrintTreeCensusClosure;
-
- protected:
-  TreeList* _parent;
-  TreeList* _left;
-  TreeList* _right;
-
- private:
-  FreeChunk*    _head;          // Head of list of free chunks
-  FreeChunk*    _tail;          // Tail of list of free chunks
-  size_t        _size;          // Size in Heap words of each chunk
-  ssize_t       _count;         // Number of entries in list
-  size_t        _hint;          // next larger size list with a positive surplus
-
-  AllocationStats _allocation_stats; // allocation-related statistics
-
-#ifdef ASSERT
-  Mutex*        _protecting_lock;
-#endif
-
-  // Asserts false if the protecting lock (if any) is not held.
-  void assert_proper_lock_protection_work() const PRODUCT_RETURN;
-  void assert_proper_lock_protection() const {
-#ifdef ASSERT
-    if (_protecting_lock != NULL)
-      assert_proper_lock_protection_work();
-#endif
-  }
-
-  // Initialize the allocation statistics.
- protected:
-  void init_statistics(bool split_birth = false);
-  void set_count(ssize_t v) { _count = v;}
-  void increment_count()    {
-    _count++;
-  }
-
-  void decrement_count() {
-    _count--;
-    assert(_count >= 0, "Count should not be negative");
-  }
-
- public:
-  // Constructor
-  // Construct a list without any entries.
-  FreeList();
-  // Construct a list with "fc" as the first (and lone) entry in the list.
-  FreeList(FreeChunk* fc);
-  // Construct a list which will have a FreeChunk at address "addr" and
-  // of size "size" as the first (and lone) entry in the list.
-  FreeList(HeapWord* addr, size_t size);
-
-  // Reset the head, tail, hint, and count of a free list.
-  void reset(size_t hint);
-
-  // Declare the current free list to be protected by the given lock.
-#ifdef ASSERT
-  void set_protecting_lock(Mutex* protecting_lock) {
-    _protecting_lock = protecting_lock;
-  }
-#endif
-
-  // Accessors.
-  FreeChunk* head() const {
-    assert_proper_lock_protection();
-    return _head;
-  }
-  void set_head(FreeChunk* v) {
-    assert_proper_lock_protection();
-    _head = v;
-    assert(!_head || _head->size() == _size, "bad chunk size");
-  }
-  // Set the head of the list and set the prev field of non-null
-  // values to NULL.
-  void link_head(FreeChunk* v) {
-    assert_proper_lock_protection();
-    set_head(v);
-    // If this method is not used (just set the head instead),
-    // this check can be avoided.
-    if (v != NULL) {
-      v->linkPrev(NULL);
-    }
-  }
-
-  FreeChunk* tail() const {
-    assert_proper_lock_protection();
-    return _tail;
-  }
-  void set_tail(FreeChunk* v) {
-    assert_proper_lock_protection();
-    _tail = v;
-    assert(!_tail || _tail->size() == _size, "bad chunk size");
-  }
-  // Set the tail of the list and set the next field of non-null
-  // values to NULL.
-  void link_tail(FreeChunk* v) {
-    assert_proper_lock_protection();
-    set_tail(v);
-    if (v != NULL) {
-      v->clearNext();
-    }
-  }
-
-  // No locking checks in read-accessors: lock-free reads (only) are benign.
-  // Readers are expected to have the lock if they are doing work that
-  // requires atomicity guarantees in sections of code.
-  size_t size() const {
-    return _size;
-  }
-  void set_size(size_t v) {
-    assert_proper_lock_protection();
-    _size = v;
-  }
-  ssize_t count() const {
-    return _count;
-  }
-  size_t hint() const {
-    return _hint;
-  }
-  void set_hint(size_t v) {
-    assert_proper_lock_protection();
-    assert(v == 0 || _size < v, "Bad hint"); _hint = v;
-  }
-
-  // Accessors for statistics
-  AllocationStats* allocation_stats() {
-    assert_proper_lock_protection();
-    return &_allocation_stats;
-  }
-
-  ssize_t desired() const {
-    return _allocation_stats.desired();
-  }
-  void set_desired(ssize_t v) {
-    assert_proper_lock_protection();
-    _allocation_stats.set_desired(v);
-  }
-  void compute_desired(float inter_sweep_current,
-                       float inter_sweep_estimate,
-                       float intra_sweep_estimate) {
-    assert_proper_lock_protection();
-    _allocation_stats.compute_desired(_count,
-                                      inter_sweep_current,
-                                      inter_sweep_estimate,
-                                      intra_sweep_estimate);
-  }
-  ssize_t coalDesired() const {
-    return _allocation_stats.coalDesired();
-  }
-  void set_coalDesired(ssize_t v) {
-    assert_proper_lock_protection();
-    _allocation_stats.set_coalDesired(v);
-  }
-
-  ssize_t surplus() const {
-    return _allocation_stats.surplus();
-  }
-  void set_surplus(ssize_t v) {
-    assert_proper_lock_protection();
-    _allocation_stats.set_surplus(v);
-  }
-  void increment_surplus() {
-    assert_proper_lock_protection();
-    _allocation_stats.increment_surplus();
-  }
-  void decrement_surplus() {
-    assert_proper_lock_protection();
-    _allocation_stats.decrement_surplus();
-  }
-
-  ssize_t bfrSurp() const {
-    return _allocation_stats.bfrSurp();
-  }
-  void set_bfrSurp(ssize_t v) {
-    assert_proper_lock_protection();
-    _allocation_stats.set_bfrSurp(v);
-  }
-  ssize_t prevSweep() const {
-    return _allocation_stats.prevSweep();
-  }
-  void set_prevSweep(ssize_t v) {
-    assert_proper_lock_protection();
-    _allocation_stats.set_prevSweep(v);
-  }
-  ssize_t beforeSweep() const {
-    return _allocation_stats.beforeSweep();
-  }
-  void set_beforeSweep(ssize_t v) {
-    assert_proper_lock_protection();
-    _allocation_stats.set_beforeSweep(v);
-  }
-
-  ssize_t coalBirths() const {
-    return _allocation_stats.coalBirths();
-  }
-  void set_coalBirths(ssize_t v) {
-    assert_proper_lock_protection();
-    _allocation_stats.set_coalBirths(v);
-  }
-  void increment_coalBirths() {
-    assert_proper_lock_protection();
-    _allocation_stats.increment_coalBirths();
-  }
-
-  ssize_t coalDeaths() const {
-    return _allocation_stats.coalDeaths();
-  }
-  void set_coalDeaths(ssize_t v) {
-    assert_proper_lock_protection();
-    _allocation_stats.set_coalDeaths(v);
-  }
-  void increment_coalDeaths() {
-    assert_proper_lock_protection();
-    _allocation_stats.increment_coalDeaths();
-  }
-
-  ssize_t splitBirths() const {
-    return _allocation_stats.splitBirths();
-  }
-  void set_splitBirths(ssize_t v) {
-    assert_proper_lock_protection();
-    _allocation_stats.set_splitBirths(v);
-  }
-  void increment_splitBirths() {
-    assert_proper_lock_protection();
-    _allocation_stats.increment_splitBirths();
-  }
-
-  ssize_t splitDeaths() const {
-    return _allocation_stats.splitDeaths();
-  }
-  void set_splitDeaths(ssize_t v) {
-    assert_proper_lock_protection();
-    _allocation_stats.set_splitDeaths(v);
-  }
-  void increment_splitDeaths() {
-    assert_proper_lock_protection();
-    _allocation_stats.increment_splitDeaths();
-  }
-
-  NOT_PRODUCT(
-    // For debugging.  The "_returnedBytes" in all the lists are summed
-    // and compared with the total number of bytes swept during a
-    // collection.
-    size_t returnedBytes() const { return _allocation_stats.returnedBytes(); }
-    void set_returnedBytes(size_t v) { _allocation_stats.set_returnedBytes(v); }
-    void increment_returnedBytes_by(size_t v) {
-      _allocation_stats.set_returnedBytes(_allocation_stats.returnedBytes() + v);
-    }
-  )
-
-  // Unlink head of list and return it.  Returns NULL if
-  // the list is empty.
-  FreeChunk* getChunkAtHead();
-
-  // Remove the first "n" or "count", whichever is smaller, chunks from the
-  // list, setting "fl", which is required to be empty, to point to them.
-  void getFirstNChunksFromList(size_t n, FreeList* fl);
-
-  // Unlink this chunk from it's free list
-  void removeChunk(FreeChunk* fc);
-
-  // Add this chunk to this free list.
-  void returnChunkAtHead(FreeChunk* fc);
-  void returnChunkAtTail(FreeChunk* fc);
-
-  // Similar to returnChunk* but also records some diagnostic
-  // information.
-  void returnChunkAtHead(FreeChunk* fc, bool record_return);
-  void returnChunkAtTail(FreeChunk* fc, bool record_return);
-
-  // Prepend "fl" (whose size is required to be the same as that of "this")
-  // to the front of "this" list.
-  void prepend(FreeList* fl);
-
-  // Verify that the chunk is in the list.
-  // found.  Return NULL if "fc" is not found.
-  bool verifyChunkInFreeLists(FreeChunk* fc) const;
-
-  // Stats verification
-  void verify_stats() const PRODUCT_RETURN;
-
-  // Printing support
-  static void print_labels_on(outputStream* st, const char* c);
-  void print_on(outputStream* st, const char* c = NULL) const;
-};
-
-#endif // SHARE_VM_GC_IMPLEMENTATION_CONCURRENTMARKSWEEP_FREELIST_HPP
--- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/promotionInfo.cpp	Wed Jul 05 18:09:43 2017 +0200
+++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/promotionInfo.cpp	Wed Jul 05 18:10:27 2017 +0200
@@ -121,7 +121,7 @@
 void PromotionInfo::track(PromotedObject* trackOop, klassOop klassOfOop) {
   // make a copy of header as it may need to be spooled
   markOop mark = oop(trackOop)->mark();
-  trackOop->clearNext();
+  trackOop->clear_next();
   if (mark->must_be_preserved_for_cms_scavenge(klassOfOop)) {
     // save non-prototypical header, and mark oop
     saveDisplacedHeader(mark);
--- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/promotionInfo.hpp	Wed Jul 05 18:09:43 2017 +0200
+++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/promotionInfo.hpp	Wed Jul 05 18:10:27 2017 +0200
@@ -43,7 +43,7 @@
   // whose position will depend on endian-ness of the platform.
   // This is so that there is no interference with the
   // cms_free_bit occupying bit position 7 (lsb == 0)
-  // when we are using compressed oops; see FreeChunk::isFree().
+  // when we are using compressed oops; see FreeChunk::is_free().
   // We cannot move the cms_free_bit down because currently
   // biased locking code assumes that age bits are contiguous
   // with the lock bits. Even if that assumption were relaxed,
@@ -65,7 +65,7 @@
   };
  public:
   inline PromotedObject* next() const {
-    assert(!((FreeChunk*)this)->isFree(), "Error");
+    assert(!((FreeChunk*)this)->is_free(), "Error");
     PromotedObject* res;
     if (UseCompressedOops) {
       // The next pointer is a compressed oop stored in the top 32 bits
@@ -85,27 +85,27 @@
     } else {
       _next |= (intptr_t)x;
     }
-    assert(!((FreeChunk*)this)->isFree(), "Error");
+    assert(!((FreeChunk*)this)->is_free(), "Error");
   }
   inline void setPromotedMark() {
     _next |= promoted_mask;
-    assert(!((FreeChunk*)this)->isFree(), "Error");
+    assert(!((FreeChunk*)this)->is_free(), "Error");
   }
   inline bool hasPromotedMark() const {
-    assert(!((FreeChunk*)this)->isFree(), "Error");
+    assert(!((FreeChunk*)this)->is_free(), "Error");
     return (_next & promoted_mask) == promoted_mask;
   }
   inline void setDisplacedMark() {
     _next |= displaced_mark;
-    assert(!((FreeChunk*)this)->isFree(), "Error");
+    assert(!((FreeChunk*)this)->is_free(), "Error");
   }
   inline bool hasDisplacedMark() const {
-    assert(!((FreeChunk*)this)->isFree(), "Error");
+    assert(!((FreeChunk*)this)->is_free(), "Error");
     return (_next & displaced_mark) != 0;
   }
-  inline void clearNext()        {
+  inline void clear_next()        {
     _next = 0;
-    assert(!((FreeChunk*)this)->isFree(), "Error");
+    assert(!((FreeChunk*)this)->is_free(), "Error");
   }
   debug_only(void *next_addr() { return (void *) &_next; })
 };
--- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/vmStructs_cms.hpp	Wed Jul 05 18:09:43 2017 +0200
+++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/vmStructs_cms.hpp	Wed Jul 05 18:10:27 2017 +0200
@@ -44,11 +44,11 @@
   nonstatic_field(FreeChunk,                   _next,                                         FreeChunk*)                            \
   nonstatic_field(FreeChunk,                   _prev,                                         FreeChunk*)                            \
   nonstatic_field(LinearAllocBlock,            _word_size,                                    size_t)                                \
-  nonstatic_field(FreeList,                    _size,                                         size_t)                                \
-  nonstatic_field(FreeList,                    _count,                                        ssize_t)                               \
-  nonstatic_field(BinaryTreeDictionary,        _totalSize,                                    size_t)                                \
-  nonstatic_field(CompactibleFreeListSpace,    _dictionary,                                   FreeBlockDictionary*)                  \
-  nonstatic_field(CompactibleFreeListSpace,    _indexedFreeList[0],                           FreeList)                              \
+  nonstatic_field(FreeList<FreeChunk>,         _size,                                         size_t)                                \
+  nonstatic_field(FreeList<FreeChunk>,         _count,                                        ssize_t)                               \
+  nonstatic_field(BinaryTreeDictionary<FreeChunk>,_total_size,                                 size_t)                                \
+  nonstatic_field(CompactibleFreeListSpace,    _dictionary,                                   FreeBlockDictionary<FreeChunk>*)       \
+  nonstatic_field(CompactibleFreeListSpace,    _indexedFreeList[0],                           FreeList<FreeChunk>)                   \
   nonstatic_field(CompactibleFreeListSpace,    _smallLinearAllocBlock,                        LinearAllocBlock)
 
 
@@ -70,13 +70,13 @@
   declare_toplevel_type(CompactibleFreeListSpace*)                        \
   declare_toplevel_type(CMSCollector*)                                    \
   declare_toplevel_type(FreeChunk*)                                       \
-  declare_toplevel_type(BinaryTreeDictionary*)                            \
-  declare_toplevel_type(FreeBlockDictionary*)                             \
-  declare_toplevel_type(FreeList*)                                        \
-  declare_toplevel_type(FreeList)                                         \
+  declare_toplevel_type(BinaryTreeDictionary<FreeChunk>*)                 \
+  declare_toplevel_type(FreeBlockDictionary<FreeChunk>*)                  \
+  declare_toplevel_type(FreeList<FreeChunk>*)                             \
+  declare_toplevel_type(FreeList<FreeChunk>)                              \
   declare_toplevel_type(LinearAllocBlock)                                 \
-  declare_toplevel_type(FreeBlockDictionary)                              \
-            declare_type(BinaryTreeDictionary,        FreeBlockDictionary)
+  declare_toplevel_type(FreeBlockDictionary<FreeChunk>)                   \
+            declare_type(BinaryTreeDictionary<FreeChunk>, FreeBlockDictionary<FreeChunk>)
 
 #define VM_INT_CONSTANTS_CMS(declare_constant)                            \
   declare_constant(Generation::ConcurrentMarkSweep)                       \
--- a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp	Wed Jul 05 18:09:43 2017 +0200
+++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp	Wed Jul 05 18:10:27 2017 +0200
@@ -1183,35 +1183,31 @@
   g1p->record_concurrent_mark_remark_end();
 }
 
-// Used to calculate the # live objects per region
-// for verification purposes
-class CalcLiveObjectsClosure: public HeapRegionClosure {
-
-  CMBitMapRO* _bm;
+// Base class of the closures that finalize and verify the
+// liveness counting data.
+class CMCountDataClosureBase: public HeapRegionClosure {
+protected:
   ConcurrentMark* _cm;
   BitMap* _region_bm;
   BitMap* _card_bm;
 
-  size_t _region_marked_bytes;
-
-  intptr_t _bottom_card_num;
-
-  void mark_card_num_range(intptr_t start_card_num, intptr_t last_card_num) {
-    assert(start_card_num <= last_card_num, "sanity");
-    BitMap::idx_t start_idx = start_card_num - _bottom_card_num;
-    BitMap::idx_t last_idx = last_card_num - _bottom_card_num;
-
-    for (BitMap::idx_t i = start_idx; i <= last_idx; i += 1) {
-      _card_bm->par_at_put(i, 1);
+  void set_card_bitmap_range(BitMap::idx_t start_idx, BitMap::idx_t last_idx) {
+    assert(start_idx <= last_idx, "sanity");
+
+    // Set the inclusive bit range [start_idx, last_idx].
+    // For small ranges (up to 8 cards) use a simple loop; otherwise
+    // use par_at_put_range.
+    if ((last_idx - start_idx) < 8) {
+      for (BitMap::idx_t i = start_idx; i <= last_idx; i += 1) {
+        _card_bm->par_set_bit(i);
+      }
+    } else {
+      assert(last_idx < _card_bm->size(), "sanity");
+      // Note BitMap::par_at_put_range() is exclusive.
+      _card_bm->par_at_put_range(start_idx, last_idx+1, true);
     }
   }
 
-public:
-  CalcLiveObjectsClosure(CMBitMapRO *bm, ConcurrentMark *cm,
-                         BitMap* region_bm, BitMap* card_bm) :
-    _bm(bm), _cm(cm), _region_bm(region_bm), _card_bm(card_bm),
-    _region_marked_bytes(0), _bottom_card_num(cm->heap_bottom_card_num()) { }
-
   // It takes a region that's not empty (i.e., it has at least one
   // live object in it and sets its corresponding bit on the region
   // bitmap to 1. If the region is "starts humongous" it will also set
@@ -1234,6 +1230,24 @@
     }
   }
 
+public:
+  CMCountDataClosureBase(ConcurrentMark *cm,
+                         BitMap* region_bm, BitMap* card_bm):
+    _cm(cm), _region_bm(region_bm), _card_bm(card_bm) { }
+};
+
+// Closure that calculates the # live objects per region. Used
+// for verification purposes during the cleanup pause.
+class CalcLiveObjectsClosure: public CMCountDataClosureBase {
+  CMBitMapRO* _bm;
+  size_t _region_marked_bytes;
+
+public:
+  CalcLiveObjectsClosure(CMBitMapRO *bm, ConcurrentMark *cm,
+                         BitMap* region_bm, BitMap* card_bm) :
+    CMCountDataClosureBase(cm, region_bm, card_bm),
+    _bm(bm), _region_marked_bytes(0) { }
+
   bool doHeapRegion(HeapRegion* hr) {
 
     if (hr->continuesHumongous()) {
@@ -1260,65 +1274,31 @@
 
     size_t marked_bytes = 0;
 
-    // Below, the term "card num" means the result of shifting an address
-    // by the card shift -- address 0 corresponds to card number 0.  One
-    // must subtract the card num of the bottom of the heap to obtain a
-    // card table index.
-
-    // The first card num of the sequence of live cards currently being
-    // constructed.  -1 ==> no sequence.
-    intptr_t start_card_num = -1;
-
-    // The last card num of the sequence of live cards currently being
-    // constructed.  -1 ==> no sequence.
-    intptr_t last_card_num = -1;
-
     while (start < nextTop) {
       oop obj = oop(start);
       int obj_sz = obj->size();
-
-      // The card num of the start of the current object.
-      intptr_t obj_card_num =
-        intptr_t(uintptr_t(start) >> CardTableModRefBS::card_shift);
       HeapWord* obj_last = start + obj_sz - 1;
-      intptr_t obj_last_card_num =
-        intptr_t(uintptr_t(obj_last) >> CardTableModRefBS::card_shift);
-
-      if (obj_card_num != last_card_num) {
-        if (start_card_num == -1) {
-          assert(last_card_num == -1, "Both or neither.");
-          start_card_num = obj_card_num;
-        } else {
-          assert(last_card_num != -1, "Both or neither.");
-          assert(obj_card_num >= last_card_num, "Inv");
-          if ((obj_card_num - last_card_num) > 1) {
-            // Mark the last run, and start a new one.
-            mark_card_num_range(start_card_num, last_card_num);
-            start_card_num = obj_card_num;
-          }
-        }
-      }
-      // In any case, we set the last card num.
-      last_card_num = obj_last_card_num;
-
+
+      BitMap::idx_t start_idx = _cm->card_bitmap_index_for(start);
+      BitMap::idx_t last_idx = _cm->card_bitmap_index_for(obj_last);
+
+      // Set the bits in the card BM for this object (inclusive).
+      set_card_bitmap_range(start_idx, last_idx);
+
+      // Add the size of this object to the number of marked bytes.
       marked_bytes += (size_t)obj_sz * HeapWordSize;
 
       // Find the next marked object after this one.
-      start = _bm->getNextMarkedWordAddress(start + 1, nextTop);
-    }
-
-    // Handle the last range, if any.
-    if (start_card_num != -1) {
-      mark_card_num_range(start_card_num, last_card_num);
+      start = _bm->getNextMarkedWordAddress(obj_last + 1, nextTop);
     }
 
     // Mark the allocated-since-marking portion...
     HeapWord* top = hr->top();
     if (nextTop < top) {
-      start_card_num = intptr_t(uintptr_t(nextTop) >> CardTableModRefBS::card_shift);
-      last_card_num = intptr_t(uintptr_t(top) >> CardTableModRefBS::card_shift);
-
-      mark_card_num_range(start_card_num, last_card_num);
+      BitMap::idx_t start_idx = _cm->card_bitmap_index_for(nextTop);
+      BitMap::idx_t last_idx = _cm->card_bitmap_index_for(top - 1);
+
+      set_card_bitmap_range(start_idx, last_idx);
 
       // This definitely means the region has live objects.
       set_bit_for_region(hr);
@@ -1394,17 +1374,6 @@
     MutexLockerEx x((_verbose ? ParGCRareEvent_lock : NULL),
                     Mutex::_no_safepoint_check_flag);
 
-    // Verify that _top_at_conc_count == ntams
-    if (hr->top_at_conc_mark_count() != hr->next_top_at_mark_start()) {
-      if (_verbose) {
-        gclog_or_tty->print_cr("Region %u: top at conc count incorrect: "
-                               "expected " PTR_FORMAT ", actual: " PTR_FORMAT,
-                               hr->hrs_index(), hr->next_top_at_mark_start(),
-                               hr->top_at_conc_mark_count());
-      }
-      failures += 1;
-    }
-
     // Verify the marked bytes for this region.
     size_t exp_marked_bytes = _calc_cl.region_marked_bytes();
     size_t act_marked_bytes = hr->next_marked_bytes();
@@ -1470,7 +1439,7 @@
     _failures += failures;
 
     // We could stop iteration over the heap when we
-    // find the first voilating region by returning true.
+    // find the first violating region by returning true.
     return false;
   }
 };
@@ -1543,62 +1512,19 @@
   int failures() const { return _failures; }
 };
 
-// Final update of count data (during cleanup).
-// Adds [top_at_count, NTAMS) to the marked bytes for each
-// region. Sets the bits in the card bitmap corresponding
-// to the interval [top_at_count, top], and sets the
-// liveness bit for each region containing live data
-// in the region bitmap.
-
-class FinalCountDataUpdateClosure: public HeapRegionClosure {
-  ConcurrentMark* _cm;
-  BitMap* _region_bm;
-  BitMap* _card_bm;
-
-  void set_card_bitmap_range(BitMap::idx_t start_idx, BitMap::idx_t last_idx) {
-    assert(start_idx <= last_idx, "sanity");
-
-    // Set the inclusive bit range [start_idx, last_idx].
-    // For small ranges (up to 8 cards) use a simple loop; otherwise
-    // use par_at_put_range.
-    if ((last_idx - start_idx) <= 8) {
-      for (BitMap::idx_t i = start_idx; i <= last_idx; i += 1) {
-        _card_bm->par_set_bit(i);
-      }
-    } else {
-      assert(last_idx < _card_bm->size(), "sanity");
-      // Note BitMap::par_at_put_range() is exclusive.
-      _card_bm->par_at_put_range(start_idx, last_idx+1, true);
-    }
-  }
-
-  // It takes a region that's not empty (i.e., it has at least one
-  // live object in it and sets its corresponding bit on the region
-  // bitmap to 1. If the region is "starts humongous" it will also set
-  // to 1 the bits on the region bitmap that correspond to its
-  // associated "continues humongous" regions.
-  void set_bit_for_region(HeapRegion* hr) {
-    assert(!hr->continuesHumongous(), "should have filtered those out");
-
-    BitMap::idx_t index = (BitMap::idx_t) hr->hrs_index();
-    if (!hr->startsHumongous()) {
-      // Normal (non-humongous) case: just set the bit.
-      _region_bm->par_set_bit(index);
-    } else {
-      // Starts humongous case: calculate how many regions are part of
-      // this humongous region and then set the bit range.
-      G1CollectedHeap* g1h = G1CollectedHeap::heap();
-      HeapRegion *last_hr = g1h->heap_region_containing_raw(hr->end() - 1);
-      BitMap::idx_t end_index = (BitMap::idx_t) last_hr->hrs_index() + 1;
-      _region_bm->par_at_put_range(index, end_index, true);
-    }
-  }
-
+// Closure that finalizes the liveness counting data.
+// Used during the cleanup pause.
+// Sets the bits corresponding to the interval [NTAMS, top]
+// (which contains the implicitly live objects) in the
+// card liveness bitmap. Also sets the bit for each region,
+// containing live data, in the region liveness bitmap.
+
+class FinalCountDataUpdateClosure: public CMCountDataClosureBase {
  public:
   FinalCountDataUpdateClosure(ConcurrentMark* cm,
                               BitMap* region_bm,
                               BitMap* card_bm) :
-    _cm(cm), _region_bm(region_bm), _card_bm(card_bm) { }
+    CMCountDataClosureBase(cm, region_bm, card_bm) { }
 
   bool doHeapRegion(HeapRegion* hr) {
 
@@ -1613,26 +1539,10 @@
       return false;
     }
 
-    HeapWord* start = hr->top_at_conc_mark_count();
     HeapWord* ntams = hr->next_top_at_mark_start();
     HeapWord* top   = hr->top();
 
-    assert(hr->bottom() <= start && start <= hr->end() &&
-           hr->bottom() <= ntams && ntams <= hr->end(), "Preconditions.");
-
-    if (start < ntams) {
-      // Region was changed between remark and cleanup pauses
-      // We need to add (ntams - start) to the marked bytes
-      // for this region, and set bits for the range
-      // [ card_idx(start), card_idx(ntams) ) in the card bitmap.
-      size_t live_bytes = (ntams - start) * HeapWordSize;
-      hr->add_to_marked_bytes(live_bytes);
-
-      // Record the new top at conc count
-      hr->set_top_at_conc_mark_count(ntams);
-
-      // The setting of the bits in the card bitmap takes place below
-    }
+    assert(hr->bottom() <= ntams && ntams <= hr->end(), "Preconditions.");
 
     // Mark the allocated-since-marking portion...
     if (ntams < top) {
@@ -1640,8 +1550,8 @@
       set_bit_for_region(hr);
     }
 
-    // Now set the bits for [start, top]
-    BitMap::idx_t start_idx = _cm->card_bitmap_index_for(start);
+    // Now set the bits for [ntams, top]
+    BitMap::idx_t start_idx = _cm->card_bitmap_index_for(ntams);
     BitMap::idx_t last_idx = _cm->card_bitmap_index_for(top);
     set_card_bitmap_range(start_idx, last_idx);
 
@@ -3072,9 +2982,6 @@
     // Update the marked bytes for this region.
     hr->add_to_marked_bytes(marked_bytes);
 
-    // Now set the top at count to NTAMS.
-    hr->set_top_at_conc_mark_count(limit);
-
     // Next heap region
     return false;
   }
--- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp	Wed Jul 05 18:09:43 2017 +0200
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp	Wed Jul 05 18:10:27 2017 +0200
@@ -368,16 +368,11 @@
     if (curr == NULL)
       gclog_or_tty->print_cr("  empty");
     while (curr != NULL) {
-      gclog_or_tty->print_cr("  [%08x-%08x], t: %08x, P: %08x, N: %08x, C: %08x, "
-                             "age: %4d, y: %d, surv: %d",
-                             curr->bottom(), curr->end(),
-                             curr->top(),
+      gclog_or_tty->print_cr("  "HR_FORMAT", P: "PTR_FORMAT "N: "PTR_FORMAT", age: %4d",
+                             HR_FORMAT_PARAMS(curr),
                              curr->prev_top_at_mark_start(),
                              curr->next_top_at_mark_start(),
-                             curr->top_at_conc_mark_count(),
-                             curr->age_in_surv_rate_group_cond(),
-                             curr->is_young(),
-                             curr->is_survivor());
+                             curr->age_in_surv_rate_group_cond());
       curr = curr->get_next_young_region();
     }
   }
@@ -1253,12 +1248,13 @@
     IsGCActiveMark x;
 
     // Timing
-    bool system_gc = (gc_cause() == GCCause::_java_lang_system_gc);
-    assert(!system_gc || explicit_gc, "invariant");
+    assert(gc_cause() != GCCause::_java_lang_system_gc || explicit_gc, "invariant");
     gclog_or_tty->date_stamp(G1Log::fine() && PrintGCDateStamps);
     TraceCPUTime tcpu(G1Log::finer(), true, gclog_or_tty);
-    TraceTime t(system_gc ? "Full GC (System.gc())" : "Full GC",
-                G1Log::fine(), true, gclog_or_tty);
+
+    char verbose_str[128];
+    sprintf(verbose_str, "Full GC (%s)", GCCause::to_string(gc_cause()));
+    TraceTime t(verbose_str, G1Log::fine(), true, gclog_or_tty);
 
     TraceCollectorStats tcs(g1mm()->full_collection_counters());
     TraceMemoryManagerStats tms(true /* fullGC */, gc_cause());
@@ -3593,25 +3589,22 @@
 
   // Inner scope for scope based logging, timers, and stats collection
   {
-    char verbose_str[128];
-    sprintf(verbose_str, "GC pause ");
-    if (g1_policy()->gcs_are_young()) {
-      strcat(verbose_str, "(young)");
-    } else {
-      strcat(verbose_str, "(mixed)");
-    }
     if (g1_policy()->during_initial_mark_pause()) {
-      strcat(verbose_str, " (initial-mark)");
       // We are about to start a marking cycle, so we increment the
       // full collection counter.
       increment_total_full_collections();
     }
-
     // if the log level is "finer" is on, we'll print long statistics information
     // in the collector policy code, so let's not print this as the output
     // is messy if we do.
     gclog_or_tty->date_stamp(G1Log::fine() && PrintGCDateStamps);
     TraceCPUTime tcpu(G1Log::finer(), true, gclog_or_tty);
+
+    char verbose_str[128];
+    sprintf(verbose_str, "GC pause (%s) (%s)%s",
+      GCCause::to_string(gc_cause()),
+      g1_policy()->gcs_are_young() ? "young" : "mixed",
+      g1_policy()->during_initial_mark_pause() ? " (initial-mark)" : "");
     TraceTime t(verbose_str, G1Log::fine() && !G1Log::finer(), true, gclog_or_tty);
 
     TraceCollectorStats tcs(g1mm()->incremental_collection_counters());
--- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp	Wed Jul 05 18:09:43 2017 +0200
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp	Wed Jul 05 18:10:27 2017 +0200
@@ -886,8 +886,9 @@
                                                       size_t start_used) {
   if (G1Log::finer()) {
     gclog_or_tty->stamp(PrintGCTimeStamps);
-    gclog_or_tty->print("[GC pause");
-    gclog_or_tty->print(" (%s)", gcs_are_young() ? "young" : "mixed");
+    gclog_or_tty->print("[GC pause (%s) (%s)",
+      GCCause::to_string(_g1->gc_cause()),
+      gcs_are_young() ? "young" : "mixed");
   }
 
   // We only need to do this here as the policy will only be applied
@@ -2459,16 +2460,10 @@
   while (csr != NULL) {
     HeapRegion* next = csr->next_in_collection_set();
     assert(csr->in_collection_set(), "bad CS");
-    st->print_cr("  [%08x-%08x], t: %08x, P: %08x, N: %08x, C: %08x, "
-                 "age: %4d, y: %d, surv: %d",
-                        csr->bottom(), csr->end(),
-                        csr->top(),
-                        csr->prev_top_at_mark_start(),
-                        csr->next_top_at_mark_start(),
-                        csr->top_at_conc_mark_count(),
-                        csr->age_in_surv_rate_group_cond(),
-                        csr->is_young(),
-                        csr->is_survivor());
+    st->print_cr("  "HR_FORMAT", P: "PTR_FORMAT "N: "PTR_FORMAT", age: %4d",
+                 HR_FORMAT_PARAMS(csr),
+                 csr->prev_top_at_mark_start(), csr->next_top_at_mark_start(),
+                 csr->age_in_surv_rate_group_cond());
     csr = next;
   }
 }
--- a/hotspot/src/share/vm/gc_implementation/g1/heapRegion.cpp	Wed Jul 05 18:09:43 2017 +0200
+++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegion.cpp	Wed Jul 05 18:10:27 2017 +0200
@@ -510,9 +510,6 @@
   _rem_set =  new HeapRegionRemSet(sharedOffsetArray, this);
 
   assert(HeapRegionRemSet::num_par_rem_sets() > 0, "Invariant.");
-  // In case the region is allocated during a pause, note the top.
-  // We haven't done any counting on a brand new region.
-  _top_at_conc_mark_count = bottom();
 }
 
 class NextCompactionHeapRegionClosure: public HeapRegionClosure {
@@ -585,14 +582,12 @@
     // we find to be self-forwarded on the next bitmap. So all
     // objects need to be below NTAMS.
     _next_top_at_mark_start = top();
-    set_top_at_conc_mark_count(bottom());
     _next_marked_bytes = 0;
   } else if (during_conc_mark) {
     // During concurrent mark, all objects in the CSet (including
     // the ones we find to be self-forwarded) are implicitly live.
     // So all objects need to be above NTAMS.
     _next_top_at_mark_start = bottom();
-    set_top_at_conc_mark_count(bottom());
     _next_marked_bytes = 0;
   }
 }
--- a/hotspot/src/share/vm/gc_implementation/g1/heapRegion.hpp	Wed Jul 05 18:09:43 2017 +0200
+++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegion.hpp	Wed Jul 05 18:10:27 2017 +0200
@@ -306,9 +306,6 @@
   // If a collection pause is in progress, this is the top at the start
   // of that pause.
 
-  // We've counted the marked bytes of objects below here.
-  HeapWord* _top_at_conc_mark_count;
-
   void init_top_at_mark_start() {
     assert(_prev_marked_bytes == 0 &&
            _next_marked_bytes == 0,
@@ -316,7 +313,6 @@
     HeapWord* bot = bottom();
     _prev_top_at_mark_start = bot;
     _next_top_at_mark_start = bot;
-    _top_at_conc_mark_count = bot;
   }
 
   void set_young_type(YoungType new_type) {
@@ -625,19 +621,6 @@
   // last mark phase ended.
   bool is_marked() { return _prev_top_at_mark_start != bottom(); }
 
-  void init_top_at_conc_mark_count() {
-    _top_at_conc_mark_count = bottom();
-  }
-
-  void set_top_at_conc_mark_count(HeapWord *cur) {
-    assert(bottom() <= cur && cur <= end(), "Sanity.");
-    _top_at_conc_mark_count = cur;
-  }
-
-  HeapWord* top_at_conc_mark_count() {
-    return _top_at_conc_mark_count;
-  }
-
   void reset_during_compaction() {
     guarantee( isHumongous() && startsHumongous(),
                "should only be called for humongous regions");
@@ -733,7 +716,6 @@
     _evacuation_failed = b;
 
     if (b) {
-      init_top_at_conc_mark_count();
       _next_marked_bytes = 0;
     }
   }
--- a/hotspot/src/share/vm/gc_implementation/g1/heapRegion.inline.hpp	Wed Jul 05 18:09:43 2017 +0200
+++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegion.inline.hpp	Wed Jul 05 18:10:27 2017 +0200
@@ -56,7 +56,6 @@
 }
 
 inline void HeapRegion::note_start_of_marking() {
-  init_top_at_conc_mark_count();
   _next_marked_bytes = 0;
   _next_top_at_mark_start = top();
 }
--- a/hotspot/src/share/vm/gc_implementation/shared/allocationStats.hpp	Wed Jul 05 18:09:43 2017 +0200
+++ b/hotspot/src/share/vm/gc_implementation/shared/allocationStats.hpp	Wed Jul 05 18:10:27 2017 +0200
@@ -39,7 +39,7 @@
   // We measure the demand between the end of the previous sweep and
   // beginning of this sweep:
   //   Count(end_last_sweep) - Count(start_this_sweep)
-  //     + splitBirths(between) - splitDeaths(between)
+  //     + split_births(between) - split_deaths(between)
   // The above number divided by the time since the end of the
   // previous sweep gives us a time rate of demand for blocks
   // of this size. We compute a padded average of this rate as
@@ -51,34 +51,34 @@
   AdaptivePaddedAverage _demand_rate_estimate;
 
   ssize_t     _desired;         // Demand stimate computed as described above
-  ssize_t     _coalDesired;     // desired +/- small-percent for tuning coalescing
+  ssize_t     _coal_desired;     // desired +/- small-percent for tuning coalescing
 
   ssize_t     _surplus;         // count - (desired +/- small-percent),
                                 // used to tune splitting in best fit
-  ssize_t     _bfrSurp;         // surplus at start of current sweep
-  ssize_t     _prevSweep;       // count from end of previous sweep
-  ssize_t     _beforeSweep;     // count from before current sweep
-  ssize_t     _coalBirths;      // additional chunks from coalescing
-  ssize_t     _coalDeaths;      // loss from coalescing
-  ssize_t     _splitBirths;     // additional chunks from splitting
-  ssize_t     _splitDeaths;     // loss from splitting
-  size_t      _returnedBytes;   // number of bytes returned to list.
+  ssize_t     _bfr_surp;         // surplus at start of current sweep
+  ssize_t     _prev_sweep;       // count from end of previous sweep
+  ssize_t     _before_sweep;     // count from before current sweep
+  ssize_t     _coal_births;      // additional chunks from coalescing
+  ssize_t     _coal_deaths;      // loss from coalescing
+  ssize_t     _split_births;     // additional chunks from splitting
+  ssize_t     _split_deaths;     // loss from splitting
+  size_t      _returned_bytes;   // number of bytes returned to list.
  public:
   void initialize(bool split_birth = false) {
     AdaptivePaddedAverage* dummy =
       new (&_demand_rate_estimate) AdaptivePaddedAverage(CMS_FLSWeight,
                                                          CMS_FLSPadding);
     _desired = 0;
-    _coalDesired = 0;
+    _coal_desired = 0;
     _surplus = 0;
-    _bfrSurp = 0;
-    _prevSweep = 0;
-    _beforeSweep = 0;
-    _coalBirths = 0;
-    _coalDeaths = 0;
-    _splitBirths = (split_birth ? 1 : 0);
-    _splitDeaths = 0;
-    _returnedBytes = 0;
+    _bfr_surp = 0;
+    _prev_sweep = 0;
+    _before_sweep = 0;
+    _coal_births = 0;
+    _coal_deaths = 0;
+    _split_births = (split_birth ? 1 : 0);
+    _split_deaths = 0;
+    _returned_bytes = 0;
   }
 
   AllocationStats() {
@@ -99,12 +99,12 @@
     // vulnerable to noisy glitches. In such cases, we
     // ignore the current sample and use currently available
     // historical estimates.
-    assert(prevSweep() + splitBirths() + coalBirths()        // "Total Production Stock"
-           >= splitDeaths() + coalDeaths() + (ssize_t)count, // "Current stock + depletion"
+    assert(prev_sweep() + split_births() + coal_births()        // "Total Production Stock"
+           >= split_deaths() + coal_deaths() + (ssize_t)count, // "Current stock + depletion"
            "Conservation Principle");
     if (inter_sweep_current > _threshold) {
-      ssize_t demand = prevSweep() - (ssize_t)count + splitBirths() + coalBirths()
-                       - splitDeaths() - coalDeaths();
+      ssize_t demand = prev_sweep() - (ssize_t)count + split_births() + coal_births()
+                       - split_deaths() - coal_deaths();
       assert(demand >= 0,
              err_msg("Demand (" SSIZE_FORMAT ") should be non-negative for "
                      PTR_FORMAT " (size=" SIZE_FORMAT ")",
@@ -130,40 +130,40 @@
   ssize_t desired() const { return _desired; }
   void set_desired(ssize_t v) { _desired = v; }
 
-  ssize_t coalDesired() const { return _coalDesired; }
-  void set_coalDesired(ssize_t v) { _coalDesired = v; }
+  ssize_t coal_desired() const { return _coal_desired; }
+  void set_coal_desired(ssize_t v) { _coal_desired = v; }
 
   ssize_t surplus() const { return _surplus; }
   void set_surplus(ssize_t v) { _surplus = v; }
   void increment_surplus() { _surplus++; }
   void decrement_surplus() { _surplus--; }
 
-  ssize_t bfrSurp() const { return _bfrSurp; }
-  void set_bfrSurp(ssize_t v) { _bfrSurp = v; }
-  ssize_t prevSweep() const { return _prevSweep; }
-  void set_prevSweep(ssize_t v) { _prevSweep = v; }
-  ssize_t beforeSweep() const { return _beforeSweep; }
-  void set_beforeSweep(ssize_t v) { _beforeSweep = v; }
+  ssize_t bfr_surp() const { return _bfr_surp; }
+  void set_bfr_surp(ssize_t v) { _bfr_surp = v; }
+  ssize_t prev_sweep() const { return _prev_sweep; }
+  void set_prev_sweep(ssize_t v) { _prev_sweep = v; }
+  ssize_t before_sweep() const { return _before_sweep; }
+  void set_before_sweep(ssize_t v) { _before_sweep = v; }
 
-  ssize_t coalBirths() const { return _coalBirths; }
-  void set_coalBirths(ssize_t v) { _coalBirths = v; }
-  void increment_coalBirths() { _coalBirths++; }
+  ssize_t coal_births() const { return _coal_births; }
+  void set_coal_births(ssize_t v) { _coal_births = v; }
+  void increment_coal_births() { _coal_births++; }
 
-  ssize_t coalDeaths() const { return _coalDeaths; }
-  void set_coalDeaths(ssize_t v) { _coalDeaths = v; }
-  void increment_coalDeaths() { _coalDeaths++; }
+  ssize_t coal_deaths() const { return _coal_deaths; }
+  void set_coal_deaths(ssize_t v) { _coal_deaths = v; }
+  void increment_coal_deaths() { _coal_deaths++; }
 
-  ssize_t splitBirths() const { return _splitBirths; }
-  void set_splitBirths(ssize_t v) { _splitBirths = v; }
-  void increment_splitBirths() { _splitBirths++; }
+  ssize_t split_births() const { return _split_births; }
+  void set_split_births(ssize_t v) { _split_births = v; }
+  void increment_split_births() { _split_births++; }
 
-  ssize_t splitDeaths() const { return _splitDeaths; }
-  void set_splitDeaths(ssize_t v) { _splitDeaths = v; }
-  void increment_splitDeaths() { _splitDeaths++; }
+  ssize_t split_deaths() const { return _split_deaths; }
+  void set_split_deaths(ssize_t v) { _split_deaths = v; }
+  void increment_split_deaths() { _split_deaths++; }
 
   NOT_PRODUCT(
-    size_t returnedBytes() const { return _returnedBytes; }
-    void set_returnedBytes(size_t v) { _returnedBytes = v; }
+    size_t returned_bytes() const { return _returned_bytes; }
+    void set_returned_bytes(size_t v) { _returned_bytes = v; }
   )
 };
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/memory/binaryTreeDictionary.cpp	Wed Jul 05 18:10:27 2017 +0200
@@ -0,0 +1,1343 @@
+/*
+ * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#include "precompiled.hpp"
+#include "gc_implementation/shared/allocationStats.hpp"
+#include "memory/binaryTreeDictionary.hpp"
+#include "runtime/globals.hpp"
+#include "utilities/ostream.hpp"
+#ifndef SERIALGC
+#include "gc_implementation/shared/spaceDecorator.hpp"
+#include "gc_implementation/concurrentMarkSweep/freeChunk.hpp"
+#endif // SERIALGC
+
+////////////////////////////////////////////////////////////////////////////////
+// A binary tree based search structure for free blocks.
+// This is currently used in the Concurrent Mark&Sweep implementation.
+////////////////////////////////////////////////////////////////////////////////
+
+template <class Chunk>
+TreeChunk<Chunk>* TreeChunk<Chunk>::as_TreeChunk(Chunk* fc) {
+  // Do some assertion checking here.
+  return (TreeChunk<Chunk>*) fc;
+}
+
+template <class Chunk>
+void TreeChunk<Chunk>::verify_tree_chunk_list() const {
+  TreeChunk<Chunk>* nextTC = (TreeChunk<Chunk>*)next();
+  if (prev() != NULL) { // interior list node shouldn'r have tree fields
+    guarantee(embedded_list()->parent() == NULL && embedded_list()->left() == NULL &&
+              embedded_list()->right()  == NULL, "should be clear");
+  }
+  if (nextTC != NULL) {
+    guarantee(as_TreeChunk(nextTC->prev()) == this, "broken chain");
+    guarantee(nextTC->size() == size(), "wrong size");
+    nextTC->verify_tree_chunk_list();
+  }
+}
+
+
+template <class Chunk>
+TreeList<Chunk>* TreeList<Chunk>::as_TreeList(TreeChunk<Chunk>* tc) {
+  // This first free chunk in the list will be the tree list.
+  assert(tc->size() >= BinaryTreeDictionary<Chunk>::min_tree_chunk_size, "Chunk is too small for a TreeChunk");
+  TreeList<Chunk>* tl = tc->embedded_list();
+  tc->set_list(tl);
+#ifdef ASSERT
+  tl->set_protecting_lock(NULL);
+#endif
+  tl->set_hint(0);
+  tl->set_size(tc->size());
+  tl->link_head(tc);
+  tl->link_tail(tc);
+  tl->set_count(1);
+  tl->init_statistics(true /* split_birth */);
+  tl->set_parent(NULL);
+  tl->set_left(NULL);
+  tl->set_right(NULL);
+  return tl;
+}
+
+template <class Chunk>
+TreeList<Chunk>* TreeList<Chunk>::as_TreeList(HeapWord* addr, size_t size) {
+  TreeChunk<Chunk>* tc = (TreeChunk<Chunk>*) addr;
+  assert(size >= BinaryTreeDictionary<Chunk>::min_tree_chunk_size, "Chunk is too small for a TreeChunk");
+  // The space in the heap will have been mangled initially but
+  // is not remangled when a free chunk is returned to the free list
+  // (since it is used to maintain the chunk on the free list).
+  assert((ZapUnusedHeapArea &&
+          SpaceMangler::is_mangled((HeapWord*) tc->size_addr()) &&
+          SpaceMangler::is_mangled((HeapWord*) tc->prev_addr()) &&
+          SpaceMangler::is_mangled((HeapWord*) tc->next_addr())) ||
+          (tc->size() == 0 && tc->prev() == NULL && tc->next() == NULL),
+    "Space should be clear or mangled");
+  tc->set_size(size);
+  tc->link_prev(NULL);
+  tc->link_next(NULL);
+  TreeList<Chunk>* tl = TreeList<Chunk>::as_TreeList(tc);
+  return tl;
+}
+
+template <class Chunk>
+TreeList<Chunk>* TreeList<Chunk>::remove_chunk_replace_if_needed(TreeChunk<Chunk>* tc) {
+
+  TreeList<Chunk>* retTL = this;
+  Chunk* list = head();
+  assert(!list || list != list->next(), "Chunk on list twice");
+  assert(tc != NULL, "Chunk being removed is NULL");
+  assert(parent() == NULL || this == parent()->left() ||
+    this == parent()->right(), "list is inconsistent");
+  assert(tc->is_free(), "Header is not marked correctly");
+  assert(head() == NULL || head()->prev() == NULL, "list invariant");
+  assert(tail() == NULL || tail()->next() == NULL, "list invariant");
+
+  Chunk* prevFC = tc->prev();
+  TreeChunk<Chunk>* nextTC = TreeChunk<Chunk>::as_TreeChunk(tc->next());
+  assert(list != NULL, "should have at least the target chunk");
+
+  // Is this the first item on the list?
+  if (tc == list) {
+    // The "getChunk..." functions for a TreeList<Chunk> will not return the
+    // first chunk in the list unless it is the last chunk in the list
+    // because the first chunk is also acting as the tree node.
+    // When coalescing happens, however, the first chunk in the a tree
+    // list can be the start of a free range.  Free ranges are removed
+    // from the free lists so that they are not available to be
+    // allocated when the sweeper yields (giving up the free list lock)
+    // to allow mutator activity.  If this chunk is the first in the
+    // list and is not the last in the list, do the work to copy the
+    // TreeList<Chunk> from the first chunk to the next chunk and update all
+    // the TreeList<Chunk> pointers in the chunks in the list.
+    if (nextTC == NULL) {
+      assert(prevFC == NULL, "Not last chunk in the list");
+      set_tail(NULL);
+      set_head(NULL);
+    } else {
+      // copy embedded list.
+      nextTC->set_embedded_list(tc->embedded_list());
+      retTL = nextTC->embedded_list();
+      // Fix the pointer to the list in each chunk in the list.
+      // This can be slow for a long list.  Consider having
+      // an option that does not allow the first chunk on the
+      // list to be coalesced.
+      for (TreeChunk<Chunk>* curTC = nextTC; curTC != NULL;
+          curTC = TreeChunk<Chunk>::as_TreeChunk(curTC->next())) {
+        curTC->set_list(retTL);
+      }
+      // Fix the parent to point to the new TreeList<Chunk>.
+      if (retTL->parent() != NULL) {
+        if (this == retTL->parent()->left()) {
+          retTL->parent()->set_left(retTL);
+        } else {
+          assert(this == retTL->parent()->right(), "Parent is incorrect");
+          retTL->parent()->set_right(retTL);
+        }
+      }
+      // Fix the children's parent pointers to point to the
+      // new list.
+      assert(right() == retTL->right(), "Should have been copied");
+      if (retTL->right() != NULL) {
+        retTL->right()->set_parent(retTL);
+      }
+      assert(left() == retTL->left(), "Should have been copied");
+      if (retTL->left() != NULL) {
+        retTL->left()->set_parent(retTL);
+      }
+      retTL->link_head(nextTC);
+      assert(nextTC->is_free(), "Should be a free chunk");
+    }
+  } else {
+    if (nextTC == NULL) {
+      // Removing chunk at tail of list
+      link_tail(prevFC);
+    }
+    // Chunk is interior to the list
+    prevFC->link_after(nextTC);
+  }
+
+  // Below this point the embeded TreeList<Chunk> being used for the
+  // tree node may have changed. Don't use "this"
+  // TreeList<Chunk>*.
+  // chunk should still be a free chunk (bit set in _prev)
+  assert(!retTL->head() || retTL->size() == retTL->head()->size(),
+    "Wrong sized chunk in list");
+  debug_only(
+    tc->link_prev(NULL);
+    tc->link_next(NULL);
+    tc->set_list(NULL);
+    bool prev_found = false;
+    bool next_found = false;
+    for (Chunk* curFC = retTL->head();
+         curFC != NULL; curFC = curFC->next()) {
+      assert(curFC != tc, "Chunk is still in list");
+      if (curFC == prevFC) {
+        prev_found = true;
+      }
+      if (curFC == nextTC) {
+        next_found = true;
+      }
+    }
+    assert(prevFC == NULL || prev_found, "Chunk was lost from list");
+    assert(nextTC == NULL || next_found, "Chunk was lost from list");
+    assert(retTL->parent() == NULL ||
+           retTL == retTL->parent()->left() ||
+           retTL == retTL->parent()->right(),
+           "list is inconsistent");
+  )
+  retTL->decrement_count();
+
+  assert(tc->is_free(), "Should still be a free chunk");
+  assert(retTL->head() == NULL || retTL->head()->prev() == NULL,
+    "list invariant");
+  assert(retTL->tail() == NULL || retTL->tail()->next() == NULL,
+    "list invariant");
+  return retTL;
+}
+
+template <class Chunk>
+void TreeList<Chunk>::return_chunk_at_tail(TreeChunk<Chunk>* chunk) {
+  assert(chunk != NULL, "returning NULL chunk");
+  assert(chunk->list() == this, "list should be set for chunk");
+  assert(tail() != NULL, "The tree list is embedded in the first chunk");
+  // which means that the list can never be empty.
+  assert(!verify_chunk_in_free_list(chunk), "Double entry");
+  assert(head() == NULL || head()->prev() == NULL, "list invariant");
+  assert(tail() == NULL || tail()->next() == NULL, "list invariant");
+
+  Chunk* fc = tail();
+  fc->link_after(chunk);
+  link_tail(chunk);
+
+  assert(!tail() || size() == tail()->size(), "Wrong sized chunk in list");
+  FreeList<Chunk>::increment_count();
+  debug_only(increment_returned_bytes_by(chunk->size()*sizeof(HeapWord));)
+  assert(head() == NULL || head()->prev() == NULL, "list invariant");
+  assert(tail() == NULL || tail()->next() == NULL, "list invariant");
+}
+
+// Add this chunk at the head of the list.  "At the head of the list"
+// is defined to be after the chunk pointer to by head().  This is
+// because the TreeList<Chunk> is embedded in the first TreeChunk<Chunk> in the
+// list.  See the definition of TreeChunk<Chunk>.
+template <class Chunk>
+void TreeList<Chunk>::return_chunk_at_head(TreeChunk<Chunk>* chunk) {
+  assert(chunk->list() == this, "list should be set for chunk");
+  assert(head() != NULL, "The tree list is embedded in the first chunk");
+  assert(chunk != NULL, "returning NULL chunk");
+  assert(!verify_chunk_in_free_list(chunk), "Double entry");
+  assert(head() == NULL || head()->prev() == NULL, "list invariant");
+  assert(tail() == NULL || tail()->next() == NULL, "list invariant");
+
+  Chunk* fc = head()->next();
+  if (fc != NULL) {
+    chunk->link_after(fc);
+  } else {
+    assert(tail() == NULL, "List is inconsistent");
+    link_tail(chunk);
+  }
+  head()->link_after(chunk);
+  assert(!head() || size() == head()->size(), "Wrong sized chunk in list");
+  FreeList<Chunk>::increment_count();
+  debug_only(increment_returned_bytes_by(chunk->size()*sizeof(HeapWord));)
+  assert(head() == NULL || head()->prev() == NULL, "list invariant");
+  assert(tail() == NULL || tail()->next() == NULL, "list invariant");
+}
+
+template <class Chunk>
+TreeChunk<Chunk>* TreeList<Chunk>::head_as_TreeChunk() {
+  assert(head() == NULL || TreeChunk<Chunk>::as_TreeChunk(head())->list() == this,
+    "Wrong type of chunk?");
+  return TreeChunk<Chunk>::as_TreeChunk(head());
+}
+
+template <class Chunk>
+TreeChunk<Chunk>* TreeList<Chunk>::first_available() {
+  assert(head() != NULL, "The head of the list cannot be NULL");
+  Chunk* fc = head()->next();
+  TreeChunk<Chunk>* retTC;
+  if (fc == NULL) {
+    retTC = head_as_TreeChunk();
+  } else {
+    retTC = TreeChunk<Chunk>::as_TreeChunk(fc);
+  }
+  assert(retTC->list() == this, "Wrong type of chunk.");
+  return retTC;
+}
+
+// Returns the block with the largest heap address amongst
+// those in the list for this size; potentially slow and expensive,
+// use with caution!
+template <class Chunk>
+TreeChunk<Chunk>* TreeList<Chunk>::largest_address() {
+  assert(head() != NULL, "The head of the list cannot be NULL");
+  Chunk* fc = head()->next();
+  TreeChunk<Chunk>* retTC;
+  if (fc == NULL) {
+    retTC = head_as_TreeChunk();
+  } else {
+    // walk down the list and return the one with the highest
+    // heap address among chunks of this size.
+    Chunk* last = fc;
+    while (fc->next() != NULL) {
+      if ((HeapWord*)last < (HeapWord*)fc) {
+        last = fc;
+      }
+      fc = fc->next();
+    }
+    retTC = TreeChunk<Chunk>::as_TreeChunk(last);
+  }
+  assert(retTC->list() == this, "Wrong type of chunk.");
+  return retTC;
+}
+
+template <class Chunk>
+BinaryTreeDictionary<Chunk>::BinaryTreeDictionary(bool adaptive_freelists, bool splay) :
+  _splay(splay), _adaptive_freelists(adaptive_freelists),
+  _total_size(0), _total_free_blocks(0), _root(0) {}
+
+template <class Chunk>
+BinaryTreeDictionary<Chunk>::BinaryTreeDictionary(MemRegion mr,
+                                           bool adaptive_freelists,
+                                           bool splay):
+  _adaptive_freelists(adaptive_freelists), _splay(splay)
+{
+  assert(mr.word_size() >= BinaryTreeDictionary<Chunk>::min_tree_chunk_size, "minimum chunk size");
+
+  reset(mr);
+  assert(root()->left() == NULL, "reset check failed");
+  assert(root()->right() == NULL, "reset check failed");
+  assert(root()->head()->next() == NULL, "reset check failed");
+  assert(root()->head()->prev() == NULL, "reset check failed");
+  assert(total_size() == root()->size(), "reset check failed");
+  assert(total_free_blocks() == 1, "reset check failed");
+}
+
+template <class Chunk>
+void BinaryTreeDictionary<Chunk>::inc_total_size(size_t inc) {
+  _total_size = _total_size + inc;
+}
+
+template <class Chunk>
+void BinaryTreeDictionary<Chunk>::dec_total_size(size_t dec) {
+  _total_size = _total_size - dec;
+}
+
+template <class Chunk>
+void BinaryTreeDictionary<Chunk>::reset(MemRegion mr) {
+  assert(mr.word_size() >= BinaryTreeDictionary<Chunk>::min_tree_chunk_size, "minimum chunk size");
+  set_root(TreeList<Chunk>::as_TreeList(mr.start(), mr.word_size()));
+  set_total_size(mr.word_size());
+  set_total_free_blocks(1);
+}
+
+template <class Chunk>
+void BinaryTreeDictionary<Chunk>::reset(HeapWord* addr, size_t byte_size) {
+  MemRegion mr(addr, heap_word_size(byte_size));
+  reset(mr);
+}
+
+template <class Chunk>
+void BinaryTreeDictionary<Chunk>::reset() {
+  set_root(NULL);
+  set_total_size(0);
+  set_total_free_blocks(0);
+}
+
+// Get a free block of size at least size from tree, or NULL.
+// If a splay step is requested, the removal algorithm (only) incorporates
+// a splay step as follows:
+// . the search proceeds down the tree looking for a possible
+//   match. At the (closest) matching location, an appropriate splay step is applied
+//   (zig, zig-zig or zig-zag). A chunk of the appropriate size is then returned
+//   if available, and if it's the last chunk, the node is deleted. A deteleted
+//   node is replaced in place by its tree successor.
+template <class Chunk>
+TreeChunk<Chunk>*
+BinaryTreeDictionary<Chunk>::get_chunk_from_tree(size_t size, enum FreeBlockDictionary<Chunk>::Dither dither, bool splay)
+{
+  TreeList<Chunk> *curTL, *prevTL;
+  TreeChunk<Chunk>* retTC = NULL;
+  assert(size >= BinaryTreeDictionary<Chunk>::min_tree_chunk_size, "minimum chunk size");
+  if (FLSVerifyDictionary) {
+    verify_tree();
+  }
+  // starting at the root, work downwards trying to find match.
+  // Remember the last node of size too great or too small.
+  for (prevTL = curTL = root(); curTL != NULL;) {
+    if (curTL->size() == size) {        // exact match
+      break;
+    }
+    prevTL = curTL;
+    if (curTL->size() < size) {        // proceed to right sub-tree
+      curTL = curTL->right();
+    } else {                           // proceed to left sub-tree
+      assert(curTL->size() > size, "size inconsistency");
+      curTL = curTL->left();
+    }
+  }
+  if (curTL == NULL) { // couldn't find exact match
+
+    if (dither == FreeBlockDictionary<Chunk>::exactly) return NULL;
+
+    // try and find the next larger size by walking back up the search path
+    for (curTL = prevTL; curTL != NULL;) {
+      if (curTL->size() >= size) break;
+      else curTL = curTL->parent();
+    }
+    assert(curTL == NULL || curTL->count() > 0,
+      "An empty list should not be in the tree");
+  }
+  if (curTL != NULL) {
+    assert(curTL->size() >= size, "size inconsistency");
+    if (adaptive_freelists()) {
+
+      // A candidate chunk has been found.  If it is already under
+      // populated, get a chunk associated with the hint for this
+      // chunk.
+      if (curTL->surplus() <= 0) {
+        /* Use the hint to find a size with a surplus, and reset the hint. */
+        TreeList<Chunk>* hintTL = curTL;
+        while (hintTL->hint() != 0) {
+          assert(hintTL->hint() == 0 || hintTL->hint() > hintTL->size(),
+            "hint points in the wrong direction");
+          hintTL = find_list(hintTL->hint());
+          assert(curTL != hintTL, "Infinite loop");
+          if (hintTL == NULL ||
+              hintTL == curTL /* Should not happen but protect against it */ ) {
+            // No useful hint.  Set the hint to NULL and go on.
+            curTL->set_hint(0);
+            break;
+          }
+          assert(hintTL->size() > size, "hint is inconsistent");
+          if (hintTL->surplus() > 0) {
+            // The hint led to a list that has a surplus.  Use it.
+            // Set the hint for the candidate to an overpopulated
+            // size.
+            curTL->set_hint(hintTL->size());
+            // Change the candidate.
+            curTL = hintTL;
+            break;
+          }
+          // The evm code reset the hint of the candidate as
+          // at an interim point.  Why?  Seems like this leaves
+          // the hint pointing to a list that didn't work.
+          // curTL->set_hint(hintTL->size());
+        }
+      }
+    }
+    // don't waste time splaying if chunk's singleton
+    if (splay && curTL->head()->next() != NULL) {
+      semi_splay_step(curTL);
+    }
+    retTC = curTL->first_available();
+    assert((retTC != NULL) && (curTL->count() > 0),
+      "A list in the binary tree should not be NULL");
+    assert(retTC->size() >= size,
+      "A chunk of the wrong size was found");
+    remove_chunk_from_tree(retTC);
+    assert(retTC->is_free(), "Header is not marked correctly");
+  }
+
+  if (FLSVerifyDictionary) {
+    verify();
+  }
+  return retTC;
+}
+
+template <class Chunk>
+TreeList<Chunk>* BinaryTreeDictionary<Chunk>::find_list(size_t size) const {
+  TreeList<Chunk>* curTL;
+  for (curTL = root(); curTL != NULL;) {
+    if (curTL->size() == size) {        // exact match
+      break;
+    }
+
+    if (curTL->size() < size) {        // proceed to right sub-tree
+      curTL = curTL->right();
+    } else {                           // proceed to left sub-tree
+      assert(curTL->size() > size, "size inconsistency");
+      curTL = curTL->left();
+    }
+  }
+  return curTL;
+}
+
+
+template <class Chunk>
+bool BinaryTreeDictionary<Chunk>::verify_chunk_in_free_list(Chunk* tc) const {
+  size_t size = tc->size();
+  TreeList<Chunk>* tl = find_list(size);
+  if (tl == NULL) {
+    return false;
+  } else {
+    return tl->verify_chunk_in_free_list(tc);
+  }
+}
+
+template <class Chunk>
+Chunk* BinaryTreeDictionary<Chunk>::find_largest_dict() const {
+  TreeList<Chunk> *curTL = root();
+  if (curTL != NULL) {
+    while(curTL->right() != NULL) curTL = curTL->right();
+    return curTL->largest_address();
+  } else {
+    return NULL;
+  }
+}
+
+// Remove the current chunk from the tree.  If it is not the last
+// chunk in a list on a tree node, just unlink it.
+// If it is the last chunk in the list (the next link is NULL),
+// remove the node and repair the tree.
+template <class Chunk>
+TreeChunk<Chunk>*
+BinaryTreeDictionary<Chunk>::remove_chunk_from_tree(TreeChunk<Chunk>* tc) {
+  assert(tc != NULL, "Should not call with a NULL chunk");
+  assert(tc->is_free(), "Header is not marked correctly");
+
+  TreeList<Chunk> *newTL, *parentTL;
+  TreeChunk<Chunk>* retTC;
+  TreeList<Chunk>* tl = tc->list();
+  debug_only(
+    bool removing_only_chunk = false;
+    if (tl == _root) {
+      if ((_root->left() == NULL) && (_root->right() == NULL)) {
+        if (_root->count() == 1) {
+          assert(_root->head() == tc, "Should only be this one chunk");
+          removing_only_chunk = true;
+        }
+      }
+    }
+  )
+  assert(tl != NULL, "List should be set");
+  assert(tl->parent() == NULL || tl == tl->parent()->left() ||
+         tl == tl->parent()->right(), "list is inconsistent");
+
+  bool complicated_splice = false;
+
+  retTC = tc;
+  // Removing this chunk can have the side effect of changing the node
+  // (TreeList<Chunk>*) in the tree.  If the node is the root, update it.
+  TreeList<Chunk>* replacementTL = tl->remove_chunk_replace_if_needed(tc);
+  assert(tc->is_free(), "Chunk should still be free");
+  assert(replacementTL->parent() == NULL ||
+         replacementTL == replacementTL->parent()->left() ||
+         replacementTL == replacementTL->parent()->right(),
+         "list is inconsistent");
+  if (tl == root()) {
+    assert(replacementTL->parent() == NULL, "Incorrectly replacing root");
+    set_root(replacementTL);
+  }
+  debug_only(
+    if (tl != replacementTL) {
+      assert(replacementTL->head() != NULL,
+        "If the tree list was replaced, it should not be a NULL list");
+      TreeList<Chunk>* rhl = replacementTL->head_as_TreeChunk()->list();
+      TreeList<Chunk>* rtl = TreeChunk<Chunk>::as_TreeChunk(replacementTL->tail())->list();
+      assert(rhl == replacementTL, "Broken head");
+      assert(rtl == replacementTL, "Broken tail");
+      assert(replacementTL->size() == tc->size(),  "Broken size");
+    }
+  )
+
+  // Does the tree need to be repaired?
+  if (replacementTL->count() == 0) {
+    assert(replacementTL->head() == NULL &&
+           replacementTL->tail() == NULL, "list count is incorrect");
+    // Find the replacement node for the (soon to be empty) node being removed.
+    // if we have a single (or no) child, splice child in our stead
+    if (replacementTL->left() == NULL) {
+      // left is NULL so pick right.  right may also be NULL.
+      newTL = replacementTL->right();
+      debug_only(replacementTL->clear_right();)
+    } else if (replacementTL->right() == NULL) {
+      // right is NULL
+      newTL = replacementTL->left();
+      debug_only(replacementTL->clearLeft();)
+    } else {  // we have both children, so, by patriarchal convention,
+              // my replacement is least node in right sub-tree
+      complicated_splice = true;
+      newTL = remove_tree_minimum(replacementTL->right());
+      assert(newTL != NULL && newTL->left() == NULL &&
+             newTL->right() == NULL, "sub-tree minimum exists");
+    }
+    // newTL is the replacement for the (soon to be empty) node.
+    // newTL may be NULL.
+    // should verify; we just cleanly excised our replacement
+    if (FLSVerifyDictionary) {
+      verify_tree();
+    }
+    // first make newTL my parent's child
+    if ((parentTL = replacementTL->parent()) == NULL) {
+      // newTL should be root
+      assert(tl == root(), "Incorrectly replacing root");
+      set_root(newTL);
+      if (newTL != NULL) {
+        newTL->clear_parent();
+      }
+    } else if (parentTL->right() == replacementTL) {
+      // replacementTL is a right child
+      parentTL->set_right(newTL);
+    } else {                                // replacementTL is a left child
+      assert(parentTL->left() == replacementTL, "should be left child");
+      parentTL->set_left(newTL);
+    }
+    debug_only(replacementTL->clear_parent();)
+    if (complicated_splice) {  // we need newTL to get replacementTL's
+                              // two children
+      assert(newTL != NULL &&
+             newTL->left() == NULL && newTL->right() == NULL,
+            "newTL should not have encumbrances from the past");
+      // we'd like to assert as below:
+      // assert(replacementTL->left() != NULL && replacementTL->right() != NULL,
+      //       "else !complicated_splice");
+      // ... however, the above assertion is too strong because we aren't
+      // guaranteed that replacementTL->right() is still NULL.
+      // Recall that we removed
+      // the right sub-tree minimum from replacementTL.
+      // That may well have been its right
+      // child! So we'll just assert half of the above:
+      assert(replacementTL->left() != NULL, "else !complicated_splice");
+      newTL->set_left(replacementTL->left());
+      newTL->set_right(replacementTL->right());
+      debug_only(
+        replacementTL->clear_right();
+        replacementTL->clearLeft();
+      )
+    }
+    assert(replacementTL->right() == NULL &&
+           replacementTL->left() == NULL &&
+           replacementTL->parent() == NULL,
+        "delete without encumbrances");
+  }
+
+  assert(total_size() >= retTC->size(), "Incorrect total size");
+  dec_total_size(retTC->size());     // size book-keeping
+  assert(total_free_blocks() > 0, "Incorrect total count");
+  set_total_free_blocks(total_free_blocks() - 1);
+
+  assert(retTC != NULL, "null chunk?");
+  assert(retTC->prev() == NULL && retTC->next() == NULL,
+         "should return without encumbrances");
+  if (FLSVerifyDictionary) {
+    verify_tree();
+  }
+  assert(!removing_only_chunk || _root == NULL, "root should be NULL");
+  return TreeChunk<Chunk>::as_TreeChunk(retTC);
+}
+
+// Remove the leftmost node (lm) in the tree and return it.
+// If lm has a right child, link it to the left node of
+// the parent of lm.
+template <class Chunk>
+TreeList<Chunk>* BinaryTreeDictionary<Chunk>::remove_tree_minimum(TreeList<Chunk>* tl) {
+  assert(tl != NULL && tl->parent() != NULL, "really need a proper sub-tree");
+  // locate the subtree minimum by walking down left branches
+  TreeList<Chunk>* curTL = tl;
+  for (; curTL->left() != NULL; curTL = curTL->left());
+  // obviously curTL now has at most one child, a right child
+  if (curTL != root()) {  // Should this test just be removed?
+    TreeList<Chunk>* parentTL = curTL->parent();
+    if (parentTL->left() == curTL) { // curTL is a left child
+      parentTL->set_left(curTL->right());
+    } else {
+      // If the list tl has no left child, then curTL may be
+      // the right child of parentTL.
+      assert(parentTL->right() == curTL, "should be a right child");
+      parentTL->set_right(curTL->right());
+    }
+  } else {
+    // The only use of this method would not pass the root of the
+    // tree (as indicated by the assertion above that the tree list
+    // has a parent) but the specification does not explicitly exclude the
+    // passing of the root so accomodate it.
+    set_root(NULL);
+  }
+  debug_only(
+    curTL->clear_parent();  // Test if this needs to be cleared
+    curTL->clear_right();    // recall, above, left child is already null
+  )
+  // we just excised a (non-root) node, we should still verify all tree invariants
+  if (FLSVerifyDictionary) {
+    verify_tree();
+  }
+  return curTL;
+}
+
+// Based on a simplification of the algorithm by Sleator and Tarjan (JACM 1985).
+// The simplifications are the following:
+// . we splay only when we delete (not when we insert)
+// . we apply a single spay step per deletion/access
+// By doing such partial splaying, we reduce the amount of restructuring,
+// while getting a reasonably efficient search tree (we think).
+// [Measurements will be needed to (in)validate this expectation.]
+
+template <class Chunk>
+void BinaryTreeDictionary<Chunk>::semi_splay_step(TreeList<Chunk>* tc) {
+  // apply a semi-splay step at the given node:
+  // . if root, norting needs to be done
+  // . if child of root, splay once
+  // . else zig-zig or sig-zag depending on path from grandparent
+  if (root() == tc) return;
+  warning("*** Splaying not yet implemented; "
+          "tree operations may be inefficient ***");
+}
+
+template <class Chunk>
+void BinaryTreeDictionary<Chunk>::insert_chunk_in_tree(Chunk* fc) {
+  TreeList<Chunk> *curTL, *prevTL;
+  size_t size = fc->size();
+
+  assert(size >= BinaryTreeDictionary<Chunk>::min_tree_chunk_size, "too small to be a TreeList<Chunk>");
+  if (FLSVerifyDictionary) {
+    verify_tree();
+  }
+
+  fc->clear_next();
+  fc->link_prev(NULL);
+
+  // work down from the _root, looking for insertion point
+  for (prevTL = curTL = root(); curTL != NULL;) {
+    if (curTL->size() == size)  // exact match
+      break;
+    prevTL = curTL;
+    if (curTL->size() > size) { // follow left branch
+      curTL = curTL->left();
+    } else {                    // follow right branch
+      assert(curTL->size() < size, "size inconsistency");
+      curTL = curTL->right();
+    }
+  }
+  TreeChunk<Chunk>* tc = TreeChunk<Chunk>::as_TreeChunk(fc);
+  // This chunk is being returned to the binary tree.  Its embedded
+  // TreeList<Chunk> should be unused at this point.
+  tc->initialize();
+  if (curTL != NULL) {          // exact match
+    tc->set_list(curTL);
+    curTL->return_chunk_at_tail(tc);
+  } else {                     // need a new node in tree
+    tc->clear_next();
+    tc->link_prev(NULL);
+    TreeList<Chunk>* newTL = TreeList<Chunk>::as_TreeList(tc);
+    assert(((TreeChunk<Chunk>*)tc)->list() == newTL,
+      "List was not initialized correctly");
+    if (prevTL == NULL) {      // we are the only tree node
+      assert(root() == NULL, "control point invariant");
+      set_root(newTL);
+    } else {                   // insert under prevTL ...
+      if (prevTL->size() < size) {   // am right child
+        assert(prevTL->right() == NULL, "control point invariant");
+        prevTL->set_right(newTL);
+      } else {                       // am left child
+        assert(prevTL->size() > size && prevTL->left() == NULL, "cpt pt inv");
+        prevTL->set_left(newTL);
+      }
+    }
+  }
+  assert(tc->list() != NULL, "Tree list should be set");
+
+  inc_total_size(size);
+  // Method 'total_size_in_tree' walks through the every block in the
+  // tree, so it can cause significant performance loss if there are
+  // many blocks in the tree
+  assert(!FLSVerifyDictionary || total_size_in_tree(root()) == total_size(), "_total_size inconsistency");
+  set_total_free_blocks(total_free_blocks() + 1);
+  if (FLSVerifyDictionary) {
+    verify_tree();
+  }
+}
+
+template <class Chunk>
+size_t BinaryTreeDictionary<Chunk>::max_chunk_size() const {
+  FreeBlockDictionary<Chunk>::verify_par_locked();
+  TreeList<Chunk>* tc = root();
+  if (tc == NULL) return 0;
+  for (; tc->right() != NULL; tc = tc->right());
+  return tc->size();
+}
+
+template <class Chunk>
+size_t BinaryTreeDictionary<Chunk>::total_list_length(TreeList<Chunk>* tl) const {
+  size_t res;
+  res = tl->count();
+#ifdef ASSERT
+  size_t cnt;
+  Chunk* tc = tl->head();
+  for (cnt = 0; tc != NULL; tc = tc->next(), cnt++);
+  assert(res == cnt, "The count is not being maintained correctly");
+#endif
+  return res;
+}
+
+template <class Chunk>
+size_t BinaryTreeDictionary<Chunk>::total_size_in_tree(TreeList<Chunk>* tl) const {
+  if (tl == NULL)
+    return 0;
+  return (tl->size() * total_list_length(tl)) +
+         total_size_in_tree(tl->left())    +
+         total_size_in_tree(tl->right());
+}
+
+template <class Chunk>
+double BinaryTreeDictionary<Chunk>::sum_of_squared_block_sizes(TreeList<Chunk>* const tl) const {
+  if (tl == NULL) {
+    return 0.0;
+  }
+  double size = (double)(tl->size());
+  double curr = size * size * total_list_length(tl);
+  curr += sum_of_squared_block_sizes(tl->left());
+  curr += sum_of_squared_block_sizes(tl->right());
+  return curr;
+}
+
+template <class Chunk>
+size_t BinaryTreeDictionary<Chunk>::total_free_blocks_in_tree(TreeList<Chunk>* tl) const {
+  if (tl == NULL)
+    return 0;
+  return total_list_length(tl) +
+         total_free_blocks_in_tree(tl->left()) +
+         total_free_blocks_in_tree(tl->right());
+}
+
+template <class Chunk>
+size_t BinaryTreeDictionary<Chunk>::num_free_blocks() const {
+  assert(total_free_blocks_in_tree(root()) == total_free_blocks(),
+         "_total_free_blocks inconsistency");
+  return total_free_blocks();
+}
+
+template <class Chunk>
+size_t BinaryTreeDictionary<Chunk>::tree_height_helper(TreeList<Chunk>* tl) const {
+  if (tl == NULL)
+    return 0;
+  return 1 + MAX2(tree_height_helper(tl->left()),
+                  tree_height_helper(tl->right()));
+}
+
+template <class Chunk>
+size_t BinaryTreeDictionary<Chunk>::treeHeight() const {
+  return tree_height_helper(root());
+}
+
+template <class Chunk>
+size_t BinaryTreeDictionary<Chunk>::total_nodes_helper(TreeList<Chunk>* tl) const {
+  if (tl == NULL) {
+    return 0;
+  }
+  return 1 + total_nodes_helper(tl->left()) +
+    total_nodes_helper(tl->right());
+}
+
+template <class Chunk>
+size_t BinaryTreeDictionary<Chunk>::total_nodes_in_tree(TreeList<Chunk>* tl) const {
+  return total_nodes_helper(root());
+}
+
+template <class Chunk>
+void BinaryTreeDictionary<Chunk>::dict_census_udpate(size_t size, bool split, bool birth){
+  TreeList<Chunk>* nd = find_list(size);
+  if (nd) {
+    if (split) {
+      if (birth) {
+        nd->increment_split_births();
+        nd->increment_surplus();
+      }  else {
+        nd->increment_split_deaths();
+        nd->decrement_surplus();
+      }
+    } else {
+      if (birth) {
+        nd->increment_coal_births();
+        nd->increment_surplus();
+      } else {
+        nd->increment_coal_deaths();
+        nd->decrement_surplus();
+      }
+    }
+  }
+  // A list for this size may not be found (nd == 0) if
+  //   This is a death where the appropriate list is now
+  //     empty and has been removed from the list.
+  //   This is a birth associated with a LinAB.  The chunk
+  //     for the LinAB is not in the dictionary.
+}
+
+template <class Chunk>
+bool BinaryTreeDictionary<Chunk>::coal_dict_over_populated(size_t size) {
+  if (FLSAlwaysCoalesceLarge) return true;
+
+  TreeList<Chunk>* list_of_size = find_list(size);
+  // None of requested size implies overpopulated.
+  return list_of_size == NULL || list_of_size->coal_desired() <= 0 ||
+         list_of_size->count() > list_of_size->coal_desired();
+}
+
+// Closures for walking the binary tree.
+//   do_list() walks the free list in a node applying the closure
+//     to each free chunk in the list
+//   do_tree() walks the nodes in the binary tree applying do_list()
+//     to each list at each node.
+
+template <class Chunk>
+class TreeCensusClosure : public StackObj {
+ protected:
+  virtual void do_list(FreeList<Chunk>* fl) = 0;
+ public:
+  virtual void do_tree(TreeList<Chunk>* tl) = 0;
+};
+
+template <class Chunk>
+class AscendTreeCensusClosure : public TreeCensusClosure<Chunk> {
+ public:
+  void do_tree(TreeList<Chunk>* tl) {
+    if (tl != NULL) {
+      do_tree(tl->left());
+      do_list(tl);
+      do_tree(tl->right());
+    }
+  }
+};
+
+template <class Chunk>
+class DescendTreeCensusClosure : public TreeCensusClosure<Chunk> {
+ public:
+  void do_tree(TreeList<Chunk>* tl) {
+    if (tl != NULL) {
+      do_tree(tl->right());
+      do_list(tl);
+      do_tree(tl->left());
+    }
+  }
+};
+
+// For each list in the tree, calculate the desired, desired
+// coalesce, count before sweep, and surplus before sweep.
+template <class Chunk>
+class BeginSweepClosure : public AscendTreeCensusClosure<Chunk> {
+  double _percentage;
+  float _inter_sweep_current;
+  float _inter_sweep_estimate;
+  float _intra_sweep_estimate;
+
+ public:
+  BeginSweepClosure(double p, float inter_sweep_current,
+                              float inter_sweep_estimate,
+                              float intra_sweep_estimate) :
+   _percentage(p),
+   _inter_sweep_current(inter_sweep_current),
+   _inter_sweep_estimate(inter_sweep_estimate),
+   _intra_sweep_estimate(intra_sweep_estimate) { }
+
+  void do_list(FreeList<Chunk>* fl) {
+    double coalSurplusPercent = _percentage;
+    fl->compute_desired(_inter_sweep_current, _inter_sweep_estimate, _intra_sweep_estimate);
+    fl->set_coal_desired((ssize_t)((double)fl->desired() * coalSurplusPercent));
+    fl->set_before_sweep(fl->count());
+    fl->set_bfr_surp(fl->surplus());
+  }
+};
+
+// Used to search the tree until a condition is met.
+// Similar to TreeCensusClosure but searches the
+// tree and returns promptly when found.
+
+template <class Chunk>
+class TreeSearchClosure : public StackObj {
+ protected:
+  virtual bool do_list(FreeList<Chunk>* fl) = 0;
+ public:
+  virtual bool do_tree(TreeList<Chunk>* tl) = 0;
+};
+
+#if 0 //  Don't need this yet but here for symmetry.
+template <class Chunk>
+class AscendTreeSearchClosure : public TreeSearchClosure {
+ public:
+  bool do_tree(TreeList<Chunk>* tl) {
+    if (tl != NULL) {
+      if (do_tree(tl->left())) return true;
+      if (do_list(tl)) return true;
+      if (do_tree(tl->right())) return true;
+    }
+    return false;
+  }
+};
+#endif
+
+template <class Chunk>
+class DescendTreeSearchClosure : public TreeSearchClosure<Chunk> {
+ public:
+  bool do_tree(TreeList<Chunk>* tl) {
+    if (tl != NULL) {
+      if (do_tree(tl->right())) return true;
+      if (do_list(tl)) return true;
+      if (do_tree(tl->left())) return true;
+    }
+    return false;
+  }
+};
+
+// Searches the tree for a chunk that ends at the
+// specified address.
+template <class Chunk>
+class EndTreeSearchClosure : public DescendTreeSearchClosure<Chunk> {
+  HeapWord* _target;
+  Chunk* _found;
+
+ public:
+  EndTreeSearchClosure(HeapWord* target) : _target(target), _found(NULL) {}
+  bool do_list(FreeList<Chunk>* fl) {
+    Chunk* item = fl->head();
+    while (item != NULL) {
+      if (item->end() == _target) {
+        _found = item;
+        return true;
+      }
+      item = item->next();
+    }
+    return false;
+  }
+  Chunk* found() { return _found; }
+};
+
+template <class Chunk>
+Chunk* BinaryTreeDictionary<Chunk>::find_chunk_ends_at(HeapWord* target) const {
+  EndTreeSearchClosure<Chunk> etsc(target);
+  bool found_target = etsc.do_tree(root());
+  assert(found_target || etsc.found() == NULL, "Consistency check");
+  assert(!found_target || etsc.found() != NULL, "Consistency check");
+  return etsc.found();
+}
+
+template <class Chunk>
+void BinaryTreeDictionary<Chunk>::begin_sweep_dict_census(double coalSurplusPercent,
+  float inter_sweep_current, float inter_sweep_estimate, float intra_sweep_estimate) {
+  BeginSweepClosure<Chunk> bsc(coalSurplusPercent, inter_sweep_current,
+                                            inter_sweep_estimate,
+                                            intra_sweep_estimate);
+  bsc.do_tree(root());
+}
+
+// Closures and methods for calculating total bytes returned to the
+// free lists in the tree.
+#ifndef PRODUCT
+template <class Chunk>
+class InitializeDictReturnedBytesClosure : public AscendTreeCensusClosure<Chunk> {
+   public:
+  void do_list(FreeList<Chunk>* fl) {
+    fl->set_returned_bytes(0);
+  }
+};
+
+template <class Chunk>
+void BinaryTreeDictionary<Chunk>::initialize_dict_returned_bytes() {
+  InitializeDictReturnedBytesClosure<Chunk> idrb;
+  idrb.do_tree(root());
+}
+
+template <class Chunk>
+class ReturnedBytesClosure : public AscendTreeCensusClosure<Chunk> {
+  size_t _dict_returned_bytes;
+ public:
+  ReturnedBytesClosure() { _dict_returned_bytes = 0; }
+  void do_list(FreeList<Chunk>* fl) {
+    _dict_returned_bytes += fl->returned_bytes();
+  }
+  size_t dict_returned_bytes() { return _dict_returned_bytes; }
+};
+
+template <class Chunk>
+size_t BinaryTreeDictionary<Chunk>::sum_dict_returned_bytes() {
+  ReturnedBytesClosure<Chunk> rbc;
+  rbc.do_tree(root());
+
+  return rbc.dict_returned_bytes();
+}
+
+// Count the number of entries in the tree.
+template <class Chunk>
+class treeCountClosure : public DescendTreeCensusClosure<Chunk> {
+ public:
+  uint count;
+  treeCountClosure(uint c) { count = c; }
+  void do_list(FreeList<Chunk>* fl) {
+    count++;
+  }
+};
+
+template <class Chunk>
+size_t BinaryTreeDictionary<Chunk>::total_count() {
+  treeCountClosure<Chunk> ctc(0);
+  ctc.do_tree(root());
+  return ctc.count;
+}
+#endif // PRODUCT
+
+// Calculate surpluses for the lists in the tree.
+template <class Chunk>
+class setTreeSurplusClosure : public AscendTreeCensusClosure<Chunk> {
+  double percentage;
+ public:
+  setTreeSurplusClosure(double v) { percentage = v; }
+  void do_list(FreeList<Chunk>* fl) {
+    double splitSurplusPercent = percentage;
+    fl->set_surplus(fl->count() -
+                   (ssize_t)((double)fl->desired() * splitSurplusPercent));
+  }
+};
+
+template <class Chunk>
+void BinaryTreeDictionary<Chunk>::set_tree_surplus(double splitSurplusPercent) {
+  setTreeSurplusClosure<Chunk> sts(splitSurplusPercent);
+  sts.do_tree(root());
+}
+
+// Set hints for the lists in the tree.
+template <class Chunk>
+class setTreeHintsClosure : public DescendTreeCensusClosure<Chunk> {
+  size_t hint;
+ public:
+  setTreeHintsClosure(size_t v) { hint = v; }
+  void do_list(FreeList<Chunk>* fl) {
+    fl->set_hint(hint);
+    assert(fl->hint() == 0 || fl->hint() > fl->size(),
+      "Current hint is inconsistent");
+    if (fl->surplus() > 0) {
+      hint = fl->size();
+    }
+  }
+};
+
+template <class Chunk>
+void BinaryTreeDictionary<Chunk>::set_tree_hints(void) {
+  setTreeHintsClosure<Chunk> sth(0);
+  sth.do_tree(root());
+}
+
+// Save count before previous sweep and splits and coalesces.
+template <class Chunk>
+class clearTreeCensusClosure : public AscendTreeCensusClosure<Chunk> {
+  void do_list(FreeList<Chunk>* fl) {
+    fl->set_prev_sweep(fl->count());
+    fl->set_coal_births(0);
+    fl->set_coal_deaths(0);
+    fl->set_split_births(0);
+    fl->set_split_deaths(0);
+  }
+};
+
+template <class Chunk>
+void BinaryTreeDictionary<Chunk>::clear_tree_census(void) {
+  clearTreeCensusClosure<Chunk> ctc;
+  ctc.do_tree(root());
+}
+
+// Do reporting and post sweep clean up.
+template <class Chunk>
+void BinaryTreeDictionary<Chunk>::end_sweep_dict_census(double splitSurplusPercent) {
+  // Does walking the tree 3 times hurt?
+  set_tree_surplus(splitSurplusPercent);
+  set_tree_hints();
+  if (PrintGC && Verbose) {
+    report_statistics();
+  }
+  clear_tree_census();
+}
+
+// Print summary statistics
+template <class Chunk>
+void BinaryTreeDictionary<Chunk>::report_statistics() const {
+  FreeBlockDictionary<Chunk>::verify_par_locked();
+  gclog_or_tty->print("Statistics for BinaryTreeDictionary:\n"
+         "------------------------------------\n");
+  size_t total_size = total_chunk_size(debug_only(NULL));
+  size_t    free_blocks = num_free_blocks();
+  gclog_or_tty->print("Total Free Space: %d\n", total_size);
+  gclog_or_tty->print("Max   Chunk Size: %d\n", max_chunk_size());
+  gclog_or_tty->print("Number of Blocks: %d\n", free_blocks);
+  if (free_blocks > 0) {
+    gclog_or_tty->print("Av.  Block  Size: %d\n", total_size/free_blocks);
+  }
+  gclog_or_tty->print("Tree      Height: %d\n", treeHeight());
+}
+
+// Print census information - counts, births, deaths, etc.
+// for each list in the tree.  Also print some summary
+// information.
+template <class Chunk>
+class PrintTreeCensusClosure : public AscendTreeCensusClosure<Chunk> {
+  int _print_line;
+  size_t _total_free;
+  FreeList<Chunk> _total;
+
+ public:
+  PrintTreeCensusClosure() {
+    _print_line = 0;
+    _total_free = 0;
+  }
+  FreeList<Chunk>* total() { return &_total; }
+  size_t total_free() { return _total_free; }
+  void do_list(FreeList<Chunk>* fl) {
+    if (++_print_line >= 40) {
+      FreeList<Chunk>::print_labels_on(gclog_or_tty, "size");
+      _print_line = 0;
+    }
+    fl->print_on(gclog_or_tty);
+    _total_free +=            fl->count()            * fl->size()        ;
+    total()->set_count(      total()->count()       + fl->count()      );
+    total()->set_bfr_surp(    total()->bfr_surp()     + fl->bfr_surp()    );
+    total()->set_surplus(    total()->split_deaths() + fl->surplus()    );
+    total()->set_desired(    total()->desired()     + fl->desired()    );
+    total()->set_prev_sweep(  total()->prev_sweep()   + fl->prev_sweep()  );
+    total()->set_before_sweep(total()->before_sweep() + fl->before_sweep());
+    total()->set_coal_births( total()->coal_births()  + fl->coal_births() );
+    total()->set_coal_deaths( total()->coal_deaths()  + fl->coal_deaths() );
+    total()->set_split_births(total()->split_births() + fl->split_births());
+    total()->set_split_deaths(total()->split_deaths() + fl->split_deaths());
+  }
+};
+
+template <class Chunk>
+void BinaryTreeDictionary<Chunk>::print_dict_census(void) const {
+
+  gclog_or_tty->print("\nBinaryTree\n");
+  FreeList<Chunk>::print_labels_on(gclog_or_tty, "size");
+  PrintTreeCensusClosure<Chunk> ptc;
+  ptc.do_tree(root());
+
+  FreeList<Chunk>* total = ptc.total();
+  FreeList<Chunk>::print_labels_on(gclog_or_tty, " ");
+  total->print_on(gclog_or_tty, "TOTAL\t");
+  gclog_or_tty->print(
+              "total_free(words): " SIZE_FORMAT_W(16)
+              " growth: %8.5f  deficit: %8.5f\n",
+              ptc.total_free(),
+              (double)(total->split_births() + total->coal_births()
+                     - total->split_deaths() - total->coal_deaths())
+              /(total->prev_sweep() != 0 ? (double)total->prev_sweep() : 1.0),
+             (double)(total->desired() - total->count())
+             /(total->desired() != 0 ? (double)total->desired() : 1.0));
+}
+
+template <class Chunk>
+class PrintFreeListsClosure : public AscendTreeCensusClosure<Chunk> {
+  outputStream* _st;
+  int _print_line;
+
+ public:
+  PrintFreeListsClosure(outputStream* st) {
+    _st = st;
+    _print_line = 0;
+  }
+  void do_list(FreeList<Chunk>* fl) {
+    if (++_print_line >= 40) {
+      FreeList<Chunk>::print_labels_on(_st, "size");
+      _print_line = 0;
+    }
+    fl->print_on(gclog_or_tty);
+    size_t sz = fl->size();
+    for (Chunk* fc = fl->head(); fc != NULL;
+         fc = fc->next()) {
+      _st->print_cr("\t[" PTR_FORMAT "," PTR_FORMAT ")  %s",
+                    fc, (HeapWord*)fc + sz,
+                    fc->cantCoalesce() ? "\t CC" : "");
+    }
+  }
+};
+
+template <class Chunk>
+void BinaryTreeDictionary<Chunk>::print_free_lists(outputStream* st) const {
+
+  FreeList<Chunk>::print_labels_on(st, "size");
+  PrintFreeListsClosure<Chunk> pflc(st);
+  pflc.do_tree(root());
+}
+
+// Verify the following tree invariants:
+// . _root has no parent
+// . parent and child point to each other
+// . each node's key correctly related to that of its child(ren)
+template <class Chunk>
+void BinaryTreeDictionary<Chunk>::verify_tree() const {
+  guarantee(root() == NULL || total_free_blocks() == 0 ||
+    total_size() != 0, "_total_size should't be 0?");
+  guarantee(root() == NULL || root()->parent() == NULL, "_root shouldn't have parent");
+  verify_tree_helper(root());
+}
+
+template <class Chunk>
+size_t BinaryTreeDictionary<Chunk>::verify_prev_free_ptrs(TreeList<Chunk>* tl) {
+  size_t ct = 0;
+  for (Chunk* curFC = tl->head(); curFC != NULL; curFC = curFC->next()) {
+    ct++;
+    assert(curFC->prev() == NULL || curFC->prev()->is_free(),
+      "Chunk should be free");
+  }
+  return ct;
+}
+
+// Note: this helper is recursive rather than iterative, so use with
+// caution on very deep trees; and watch out for stack overflow errors;
+// In general, to be used only for debugging.
+template <class Chunk>
+void BinaryTreeDictionary<Chunk>::verify_tree_helper(TreeList<Chunk>* tl) const {
+  if (tl == NULL)
+    return;
+  guarantee(tl->size() != 0, "A list must has a size");
+  guarantee(tl->left()  == NULL || tl->left()->parent()  == tl,
+         "parent<-/->left");
+  guarantee(tl->right() == NULL || tl->right()->parent() == tl,
+         "parent<-/->right");;
+  guarantee(tl->left() == NULL  || tl->left()->size()    <  tl->size(),
+         "parent !> left");
+  guarantee(tl->right() == NULL || tl->right()->size()   >  tl->size(),
+         "parent !< left");
+  guarantee(tl->head() == NULL || tl->head()->is_free(), "!Free");
+  guarantee(tl->head() == NULL || tl->head_as_TreeChunk()->list() == tl,
+    "list inconsistency");
+  guarantee(tl->count() > 0 || (tl->head() == NULL && tl->tail() == NULL),
+    "list count is inconsistent");
+  guarantee(tl->count() > 1 || tl->head() == tl->tail(),
+    "list is incorrectly constructed");
+  size_t count = verify_prev_free_ptrs(tl);
+  guarantee(count == (size_t)tl->count(), "Node count is incorrect");
+  if (tl->head() != NULL) {
+    tl->head_as_TreeChunk()->verify_tree_chunk_list();
+  }
+  verify_tree_helper(tl->left());
+  verify_tree_helper(tl->right());
+}
+
+template <class Chunk>
+void BinaryTreeDictionary<Chunk>::verify() const {
+  verify_tree();
+  guarantee(total_size() == total_size_in_tree(root()), "Total Size inconsistency");
+}
+
+#ifndef SERIALGC
+// Explicitly instantiate these types for FreeChunk.
+template class BinaryTreeDictionary<FreeChunk>;
+template class TreeChunk<FreeChunk>;
+template class TreeList<FreeChunk>;
+#endif // SERIALGC
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/memory/binaryTreeDictionary.hpp	Wed Jul 05 18:10:27 2017 +0200
@@ -0,0 +1,329 @@
+/*
+ * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef SHARE_VM_MEMORY_BINARYTREEDICTIONARY_HPP
+#define SHARE_VM_MEMORY_BINARYTREEDICTIONARY_HPP
+
+#include "memory/freeBlockDictionary.hpp"
+#include "memory/freeList.hpp"
+
+/*
+ * A binary tree based search structure for free blocks.
+ * This is currently used in the Concurrent Mark&Sweep implementation, but
+ * will be used for free block management for metadata.
+ */
+
+// A TreeList is a FreeList which can be used to maintain a
+// binary tree of free lists.
+
+template <class Chunk> class TreeChunk;
+template <class Chunk> class BinaryTreeDictionary;
+template <class Chunk> class AscendTreeCensusClosure;
+template <class Chunk> class DescendTreeCensusClosure;
+template <class Chunk> class DescendTreeSearchClosure;
+
+template <class Chunk>
+class TreeList: public FreeList<Chunk> {
+  friend class TreeChunk<Chunk>;
+  friend class BinaryTreeDictionary<Chunk>;
+  friend class AscendTreeCensusClosure<Chunk>;
+  friend class DescendTreeCensusClosure<Chunk>;
+  friend class DescendTreeSearchClosure<Chunk>;
+
+  TreeList<Chunk>* _parent;
+  TreeList<Chunk>* _left;
+  TreeList<Chunk>* _right;
+
+ protected:
+  TreeList<Chunk>* parent() const { return _parent; }
+  TreeList<Chunk>* left()   const { return _left;   }
+  TreeList<Chunk>* right()  const { return _right;  }
+
+  // Wrapper on call to base class, to get the template to compile.
+  Chunk* head() const { return FreeList<Chunk>::head(); }
+  Chunk* tail() const { return FreeList<Chunk>::tail(); }
+  void set_head(Chunk* head) { FreeList<Chunk>::set_head(head); }
+  void set_tail(Chunk* tail) { FreeList<Chunk>::set_tail(tail); }
+
+  size_t size() const { return FreeList<Chunk>::size(); }
+
+  // Accessors for links in tree.
+
+  void set_left(TreeList<Chunk>* tl) {
+    _left   = tl;
+    if (tl != NULL)
+      tl->set_parent(this);
+  }
+  void set_right(TreeList<Chunk>* tl) {
+    _right  = tl;
+    if (tl != NULL)
+      tl->set_parent(this);
+  }
+  void set_parent(TreeList<Chunk>* tl)  { _parent = tl;   }
+
+  void clearLeft()               { _left = NULL;   }
+  void clear_right()              { _right = NULL;  }
+  void clear_parent()             { _parent = NULL; }
+  void initialize()              { clearLeft(); clear_right(), clear_parent(); }
+
+  // For constructing a TreeList from a Tree chunk or
+  // address and size.
+  static TreeList<Chunk>* as_TreeList(TreeChunk<Chunk>* tc);
+  static TreeList<Chunk>* as_TreeList(HeapWord* addr, size_t size);
+
+  // Returns the head of the free list as a pointer to a TreeChunk.
+  TreeChunk<Chunk>* head_as_TreeChunk();
+
+  // Returns the first available chunk in the free list as a pointer
+  // to a TreeChunk.
+  TreeChunk<Chunk>* first_available();
+
+  // Returns the block with the largest heap address amongst
+  // those in the list for this size; potentially slow and expensive,
+  // use with caution!
+  TreeChunk<Chunk>* largest_address();
+
+  // remove_chunk_replace_if_needed() removes the given "tc" from the TreeList.
+  // If "tc" is the first chunk in the list, it is also the
+  // TreeList that is the node in the tree.  remove_chunk_replace_if_needed()
+  // returns the possibly replaced TreeList* for the node in
+  // the tree.  It also updates the parent of the original
+  // node to point to the new node.
+  TreeList<Chunk>* remove_chunk_replace_if_needed(TreeChunk<Chunk>* tc);
+  // See FreeList.
+  void return_chunk_at_head(TreeChunk<Chunk>* tc);
+  void return_chunk_at_tail(TreeChunk<Chunk>* tc);
+};
+
+// A TreeChunk is a subclass of a Chunk that additionally
+// maintains a pointer to the free list on which it is currently
+// linked.
+// A TreeChunk is also used as a node in the binary tree.  This
+// allows the binary tree to be maintained without any additional
+// storage (the free chunks are used).  In a binary tree the first
+// chunk in the free list is also the tree node.  Note that the
+// TreeChunk has an embedded TreeList for this purpose.  Because
+// the first chunk in the list is distinguished in this fashion
+// (also is the node in the tree), it is the last chunk to be found
+// on the free list for a node in the tree and is only removed if
+// it is the last chunk on the free list.
+
+template <class Chunk>
+class TreeChunk : public Chunk {
+  friend class TreeList<Chunk>;
+  TreeList<Chunk>* _list;
+  TreeList<Chunk> _embedded_list;  // if non-null, this chunk is on _list
+ protected:
+  TreeList<Chunk>* embedded_list() const { return (TreeList<Chunk>*) &_embedded_list; }
+  void set_embedded_list(TreeList<Chunk>* v) { _embedded_list = *v; }
+ public:
+  TreeList<Chunk>* list() { return _list; }
+  void set_list(TreeList<Chunk>* v) { _list = v; }
+  static TreeChunk<Chunk>* as_TreeChunk(Chunk* fc);
+  // Initialize fields in a TreeChunk that should be
+  // initialized when the TreeChunk is being added to
+  // a free list in the tree.
+  void initialize() { embedded_list()->initialize(); }
+
+  Chunk* next() const { return Chunk::next(); }
+  Chunk* prev() const { return Chunk::prev(); }
+  size_t size() const volatile { return Chunk::size(); }
+
+  // debugging
+  void verify_tree_chunk_list() const;
+};
+
+
+template <class Chunk>
+class BinaryTreeDictionary: public FreeBlockDictionary<Chunk> {
+  friend class VMStructs;
+  bool       _splay;
+  size_t     _total_size;
+  size_t     _total_free_blocks;
+  TreeList<Chunk>* _root;
+  bool       _adaptive_freelists;
+
+  // private accessors
+  bool splay() const { return _splay; }
+  void set_splay(bool v) { _splay = v; }
+  void set_total_size(size_t v) { _total_size = v; }
+  virtual void inc_total_size(size_t v);
+  virtual void dec_total_size(size_t v);
+  size_t total_free_blocks() const { return _total_free_blocks; }
+  void set_total_free_blocks(size_t v) { _total_free_blocks = v; }
+  TreeList<Chunk>* root() const { return _root; }
+  void set_root(TreeList<Chunk>* v) { _root = v; }
+  bool adaptive_freelists() { return _adaptive_freelists; }
+
+  // This field is added and can be set to point to the
+  // the Mutex used to synchronize access to the
+  // dictionary so that assertion checking can be done.
+  // For example it is set to point to _parDictionaryAllocLock.
+  NOT_PRODUCT(Mutex* _lock;)
+
+  // Remove a chunk of size "size" or larger from the tree and
+  // return it.  If the chunk
+  // is the last chunk of that size, remove the node for that size
+  // from the tree.
+  TreeChunk<Chunk>* get_chunk_from_tree(size_t size, enum FreeBlockDictionary<Chunk>::Dither dither, bool splay);
+  // Return a list of the specified size or NULL from the tree.
+  // The list is not removed from the tree.
+  TreeList<Chunk>* find_list (size_t size) const;
+  // Remove this chunk from the tree.  If the removal results
+  // in an empty list in the tree, remove the empty list.
+  TreeChunk<Chunk>* remove_chunk_from_tree(TreeChunk<Chunk>* tc);
+  // Remove the node in the trees starting at tl that has the
+  // minimum value and return it.  Repair the tree as needed.
+  TreeList<Chunk>* remove_tree_minimum(TreeList<Chunk>* tl);
+  void       semi_splay_step(TreeList<Chunk>* tl);
+  // Add this free chunk to the tree.
+  void       insert_chunk_in_tree(Chunk* freeChunk);
+ public:
+
+  static const size_t min_tree_chunk_size  = sizeof(TreeChunk<Chunk>)/HeapWordSize;
+
+  void       verify_tree() const;
+  // verify that the given chunk is in the tree.
+  bool       verify_chunk_in_free_list(Chunk* tc) const;
+ private:
+  void          verify_tree_helper(TreeList<Chunk>* tl) const;
+  static size_t verify_prev_free_ptrs(TreeList<Chunk>* tl);
+
+  // Returns the total number of chunks in the list.
+  size_t     total_list_length(TreeList<Chunk>* tl) const;
+  // Returns the total number of words in the chunks in the tree
+  // starting at "tl".
+  size_t     total_size_in_tree(TreeList<Chunk>* tl) const;
+  // Returns the sum of the square of the size of each block
+  // in the tree starting at "tl".
+  double     sum_of_squared_block_sizes(TreeList<Chunk>* const tl) const;
+  // Returns the total number of free blocks in the tree starting
+  // at "tl".
+  size_t     total_free_blocks_in_tree(TreeList<Chunk>* tl) const;
+  size_t     num_free_blocks() const;
+  size_t     treeHeight() const;
+  size_t     tree_height_helper(TreeList<Chunk>* tl) const;
+  size_t     total_nodes_in_tree(TreeList<Chunk>* tl) const;
+  size_t     total_nodes_helper(TreeList<Chunk>* tl) const;
+
+ public:
+  // Constructor
+  BinaryTreeDictionary(bool adaptive_freelists, bool splay = false);
+  BinaryTreeDictionary(MemRegion mr, bool adaptive_freelists, bool splay = false);
+
+  // Public accessors
+  size_t total_size() const { return _total_size; }
+
+  // Reset the dictionary to the initial conditions with
+  // a single free chunk.
+  void       reset(MemRegion mr);
+  void       reset(HeapWord* addr, size_t size);
+  // Reset the dictionary to be empty.
+  void       reset();
+
+  // Return a chunk of size "size" or greater from
+  // the tree.
+  // want a better dynamic splay strategy for the future.
+  Chunk* get_chunk(size_t size, enum FreeBlockDictionary<Chunk>::Dither dither) {
+    FreeBlockDictionary<Chunk>::verify_par_locked();
+    Chunk* res = get_chunk_from_tree(size, dither, splay());
+    assert(res == NULL || res->is_free(),
+           "Should be returning a free chunk");
+    return res;
+  }
+
+  void return_chunk(Chunk* chunk) {
+    FreeBlockDictionary<Chunk>::verify_par_locked();
+    insert_chunk_in_tree(chunk);
+  }
+
+  void remove_chunk(Chunk* chunk) {
+    FreeBlockDictionary<Chunk>::verify_par_locked();
+    remove_chunk_from_tree((TreeChunk<Chunk>*)chunk);
+    assert(chunk->is_free(), "Should still be a free chunk");
+  }
+
+  size_t     max_chunk_size() const;
+  size_t     total_chunk_size(debug_only(const Mutex* lock)) const {
+    debug_only(
+      if (lock != NULL && lock->owned_by_self()) {
+        assert(total_size_in_tree(root()) == total_size(),
+               "_total_size inconsistency");
+      }
+    )
+    return total_size();
+  }
+
+  size_t     min_size() const {
+    return min_tree_chunk_size;
+  }
+
+  double     sum_of_squared_block_sizes() const {
+    return sum_of_squared_block_sizes(root());
+  }
+
+  Chunk* find_chunk_ends_at(HeapWord* target) const;
+
+  // Find the list with size "size" in the binary tree and update
+  // the statistics in the list according to "split" (chunk was
+  // split or coalesce) and "birth" (chunk was added or removed).
+  void       dict_census_udpate(size_t size, bool split, bool birth);
+  // Return true if the dictionary is overpopulated (more chunks of
+  // this size than desired) for size "size".
+  bool       coal_dict_over_populated(size_t size);
+  // Methods called at the beginning of a sweep to prepare the
+  // statistics for the sweep.
+  void       begin_sweep_dict_census(double coalSurplusPercent,
+                                  float inter_sweep_current,
+                                  float inter_sweep_estimate,
+                                  float intra_sweep_estimate);
+  // Methods called after the end of a sweep to modify the
+  // statistics for the sweep.
+  void       end_sweep_dict_census(double splitSurplusPercent);
+  // Return the largest free chunk in the tree.
+  Chunk* find_largest_dict() const;
+  // Accessors for statistics
+  void       set_tree_surplus(double splitSurplusPercent);
+  void       set_tree_hints(void);
+  // Reset statistics for all the lists in the tree.
+  void       clear_tree_census(void);
+  // Print the statistcis for all the lists in the tree.  Also may
+  // print out summaries.
+  void       print_dict_census(void) const;
+  void       print_free_lists(outputStream* st) const;
+
+  // For debugging.  Returns the sum of the _returned_bytes for
+  // all lists in the tree.
+  size_t     sum_dict_returned_bytes()     PRODUCT_RETURN0;
+  // Sets the _returned_bytes for all the lists in the tree to zero.
+  void       initialize_dict_returned_bytes()      PRODUCT_RETURN;
+  // For debugging.  Return the total number of chunks in the dictionary.
+  size_t     total_count()       PRODUCT_RETURN0;
+
+  void       report_statistics() const;
+
+  void       verify() const;
+};
+
+#endif // SHARE_VM_MEMORY_BINARYTREEDICTIONARY_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/memory/freeBlockDictionary.cpp	Wed Jul 05 18:10:27 2017 +0200
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#include "precompiled.hpp"
+#ifndef SERIALGC
+#include "gc_implementation/concurrentMarkSweep/freeChunk.hpp"
+#endif // SERIALGC
+#include "memory/freeBlockDictionary.hpp"
+#ifdef TARGET_OS_FAMILY_linux
+# include "thread_linux.inline.hpp"
+#endif
+#ifdef TARGET_OS_FAMILY_solaris
+# include "thread_solaris.inline.hpp"
+#endif
+#ifdef TARGET_OS_FAMILY_windows
+# include "thread_windows.inline.hpp"
+#endif
+#ifdef TARGET_OS_FAMILY_bsd
+# include "thread_bsd.inline.hpp"
+#endif
+
+#ifndef PRODUCT
+template <class Chunk> Mutex* FreeBlockDictionary<Chunk>::par_lock() const {
+  return _lock;
+}
+
+template <class Chunk> void FreeBlockDictionary<Chunk>::set_par_lock(Mutex* lock) {
+  _lock = lock;
+}
+
+template <class Chunk> void FreeBlockDictionary<Chunk>::verify_par_locked() const {
+#ifdef ASSERT
+  if (ParallelGCThreads > 0) {
+    Thread* my_thread = Thread::current();
+    if (my_thread->is_GC_task_thread()) {
+      assert(par_lock() != NULL, "Should be using locking?");
+      assert_lock_strong(par_lock());
+    }
+  }
+#endif // ASSERT
+}
+#endif
+
+#ifndef SERIALGC
+// Explicitly instantiate for FreeChunk
+template class FreeBlockDictionary<FreeChunk>;
+#endif // SERIALGC
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/memory/freeBlockDictionary.hpp	Wed Jul 05 18:10:27 2017 +0200
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef SHARE_VM_MEMORY_FREEBLOCKDICTIONARY_HPP
+#define SHARE_VM_MEMORY_FREEBLOCKDICTIONARY_HPP
+
+#include "memory/allocation.hpp"
+#include "runtime/mutex.hpp"
+#include "utilities/debug.hpp"
+#include "utilities/globalDefinitions.hpp"
+#include "utilities/ostream.hpp"
+
+// A FreeBlockDictionary is an abstract superclass that will allow
+// a number of alternative implementations in the future.
+template <class Chunk>
+class FreeBlockDictionary: public CHeapObj {
+ public:
+  enum Dither {
+    atLeast,
+    exactly,
+    roughly
+  };
+  enum DictionaryChoice {
+    dictionaryBinaryTree = 0,
+    dictionarySplayTree  = 1,
+    dictionarySkipList   = 2
+  };
+
+ private:
+  NOT_PRODUCT(Mutex* _lock;)
+
+ public:
+  virtual void       remove_chunk(Chunk* fc) = 0;
+  virtual Chunk*     get_chunk(size_t size, Dither dither = atLeast) = 0;
+  virtual void       return_chunk(Chunk* chunk) = 0;
+  virtual size_t     total_chunk_size(debug_only(const Mutex* lock)) const = 0;
+  virtual size_t     max_chunk_size()   const = 0;
+  virtual size_t     min_size()        const = 0;
+  // Reset the dictionary to the initial conditions for a single
+  // block.
+  virtual void       reset(HeapWord* addr, size_t size) = 0;
+  virtual void       reset() = 0;
+
+  virtual void       dict_census_udpate(size_t size, bool split, bool birth) = 0;
+  virtual bool       coal_dict_over_populated(size_t size) = 0;
+  virtual void       begin_sweep_dict_census(double coalSurplusPercent,
+                       float inter_sweep_current, float inter_sweep_estimate,
+                       float intra__sweep_current) = 0;
+  virtual void       end_sweep_dict_census(double splitSurplusPercent) = 0;
+  virtual Chunk*     find_largest_dict() const = 0;
+  // verify that the given chunk is in the dictionary.
+  virtual bool verify_chunk_in_free_list(Chunk* tc) const = 0;
+
+  // Sigma_{all_free_blocks} (block_size^2)
+  virtual double sum_of_squared_block_sizes() const = 0;
+
+  virtual Chunk* find_chunk_ends_at(HeapWord* target) const = 0;
+  virtual void inc_total_size(size_t v) = 0;
+  virtual void dec_total_size(size_t v) = 0;
+
+  NOT_PRODUCT (
+    virtual size_t   sum_dict_returned_bytes() = 0;
+    virtual void     initialize_dict_returned_bytes() = 0;
+    virtual size_t   total_count() = 0;
+  )
+
+  virtual void       report_statistics() const {
+    gclog_or_tty->print("No statistics available");
+  }
+
+  virtual void       print_dict_census() const = 0;
+  virtual void       print_free_lists(outputStream* st) const = 0;
+
+  virtual void       verify()         const = 0;
+
+  Mutex* par_lock()                const PRODUCT_RETURN0;
+  void   set_par_lock(Mutex* lock)       PRODUCT_RETURN;
+  void   verify_par_locked()       const PRODUCT_RETURN;
+};
+
+#endif // SHARE_VM_MEMORY_FREEBLOCKDICTIONARY_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/memory/freeList.cpp	Wed Jul 05 18:10:27 2017 +0200
@@ -0,0 +1,370 @@
+/*
+ * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#include "precompiled.hpp"
+#include "memory/freeBlockDictionary.hpp"
+#include "memory/freeList.hpp"
+#include "memory/sharedHeap.hpp"
+#include "runtime/globals.hpp"
+#include "runtime/mutex.hpp"
+#include "runtime/vmThread.hpp"
+
+#ifndef SERIALGC
+#include "gc_implementation/concurrentMarkSweep/freeChunk.hpp"
+#endif // SERIALGC
+
+// Free list.  A FreeList is used to access a linked list of chunks
+// of space in the heap.  The head and tail are maintained so that
+// items can be (as in the current implementation) added at the
+// at the tail of the list and removed from the head of the list to
+// maintain a FIFO queue.
+
+template <class Chunk>
+FreeList<Chunk>::FreeList() :
+  _head(NULL), _tail(NULL)
+#ifdef ASSERT
+  , _protecting_lock(NULL)
+#endif
+{
+  _size         = 0;
+  _count        = 0;
+  _hint         = 0;
+  init_statistics();
+}
+
+template <class Chunk>
+FreeList<Chunk>::FreeList(Chunk* fc) :
+  _head(fc), _tail(fc)
+#ifdef ASSERT
+  , _protecting_lock(NULL)
+#endif
+{
+  _size         = fc->size();
+  _count        = 1;
+  _hint         = 0;
+  init_statistics();
+#ifndef PRODUCT
+  _allocation_stats.set_returned_bytes(size() * HeapWordSize);
+#endif
+}
+
+template <class Chunk>
+void FreeList<Chunk>::reset(size_t hint) {
+  set_count(0);
+  set_head(NULL);
+  set_tail(NULL);
+  set_hint(hint);
+}
+
+template <class Chunk>
+void FreeList<Chunk>::init_statistics(bool split_birth) {
+  _allocation_stats.initialize(split_birth);
+}
+
+template <class Chunk>
+Chunk* FreeList<Chunk>::get_chunk_at_head() {
+  assert_proper_lock_protection();
+  assert(head() == NULL || head()->prev() == NULL, "list invariant");
+  assert(tail() == NULL || tail()->next() == NULL, "list invariant");
+  Chunk* fc = head();
+  if (fc != NULL) {
+    Chunk* nextFC = fc->next();
+    if (nextFC != NULL) {
+      // The chunk fc being removed has a "next".  Set the "next" to the
+      // "prev" of fc.
+      nextFC->link_prev(NULL);
+    } else { // removed tail of list
+      link_tail(NULL);
+    }
+    link_head(nextFC);
+    decrement_count();
+  }
+  assert(head() == NULL || head()->prev() == NULL, "list invariant");
+  assert(tail() == NULL || tail()->next() == NULL, "list invariant");
+  return fc;
+}
+
+
+template <class Chunk>
+void FreeList<Chunk>::getFirstNChunksFromList(size_t n, FreeList<Chunk>* fl) {
+  assert_proper_lock_protection();
+  assert(fl->count() == 0, "Precondition");
+  if (count() > 0) {
+    int k = 1;
+    fl->set_head(head()); n--;
+    Chunk* tl = head();
+    while (tl->next() != NULL && n > 0) {
+      tl = tl->next(); n--; k++;
+    }
+    assert(tl != NULL, "Loop Inv.");
+
+    // First, fix up the list we took from.
+    Chunk* new_head = tl->next();
+    set_head(new_head);
+    set_count(count() - k);
+    if (new_head == NULL) {
+      set_tail(NULL);
+    } else {
+      new_head->link_prev(NULL);
+    }
+    // Now we can fix up the tail.
+    tl->link_next(NULL);
+    // And return the result.
+    fl->set_tail(tl);
+    fl->set_count(k);
+  }
+}
+
+// Remove this chunk from the list
+template <class Chunk>
+void FreeList<Chunk>::remove_chunk(Chunk*fc) {
+   assert_proper_lock_protection();
+   assert(head() != NULL, "Remove from empty list");
+   assert(fc != NULL, "Remove a NULL chunk");
+   assert(size() == fc->size(), "Wrong list");
+   assert(head() == NULL || head()->prev() == NULL, "list invariant");
+   assert(tail() == NULL || tail()->next() == NULL, "list invariant");
+
+   Chunk* prevFC = fc->prev();
+   Chunk* nextFC = fc->next();
+   if (nextFC != NULL) {
+     // The chunk fc being removed has a "next".  Set the "next" to the
+     // "prev" of fc.
+     nextFC->link_prev(prevFC);
+   } else { // removed tail of list
+     link_tail(prevFC);
+   }
+   if (prevFC == NULL) { // removed head of list
+     link_head(nextFC);
+     assert(nextFC == NULL || nextFC->prev() == NULL,
+       "Prev of head should be NULL");
+   } else {
+     prevFC->link_next(nextFC);
+     assert(tail() != prevFC || prevFC->next() == NULL,
+       "Next of tail should be NULL");
+   }
+   decrement_count();
+   assert(((head() == NULL) + (tail() == NULL) + (count() == 0)) % 3 == 0,
+          "H/T/C Inconsistency");
+   // clear next and prev fields of fc, debug only
+   NOT_PRODUCT(
+     fc->link_prev(NULL);
+     fc->link_next(NULL);
+   )
+   assert(fc->is_free(), "Should still be a free chunk");
+   assert(head() == NULL || head()->prev() == NULL, "list invariant");
+   assert(tail() == NULL || tail()->next() == NULL, "list invariant");
+   assert(head() == NULL || head()->size() == size(), "wrong item on list");
+   assert(tail() == NULL || tail()->size() == size(), "wrong item on list");
+}
+
+// Add this chunk at the head of the list.
+template <class Chunk>
+void FreeList<Chunk>::return_chunk_at_head(Chunk* chunk, bool record_return) {
+  assert_proper_lock_protection();
+  assert(chunk != NULL, "insert a NULL chunk");
+  assert(size() == chunk->size(), "Wrong size");
+  assert(head() == NULL || head()->prev() == NULL, "list invariant");
+  assert(tail() == NULL || tail()->next() == NULL, "list invariant");
+
+  Chunk* oldHead = head();
+  assert(chunk != oldHead, "double insertion");
+  chunk->link_after(oldHead);
+  link_head(chunk);
+  if (oldHead == NULL) { // only chunk in list
+    assert(tail() == NULL, "inconsistent FreeList");
+    link_tail(chunk);
+  }
+  increment_count(); // of # of chunks in list
+  DEBUG_ONLY(
+    if (record_return) {
+      increment_returned_bytes_by(size()*HeapWordSize);
+    }
+  )
+  assert(head() == NULL || head()->prev() == NULL, "list invariant");
+  assert(tail() == NULL || tail()->next() == NULL, "list invariant");
+  assert(head() == NULL || head()->size() == size(), "wrong item on list");
+  assert(tail() == NULL || tail()->size() == size(), "wrong item on list");
+}
+
+template <class Chunk>
+void FreeList<Chunk>::return_chunk_at_head(Chunk* chunk) {
+  assert_proper_lock_protection();
+  return_chunk_at_head(chunk, true);
+}
+
+// Add this chunk at the tail of the list.
+template <class Chunk>
+void FreeList<Chunk>::return_chunk_at_tail(Chunk* chunk, bool record_return) {
+  assert_proper_lock_protection();
+  assert(head() == NULL || head()->prev() == NULL, "list invariant");
+  assert(tail() == NULL || tail()->next() == NULL, "list invariant");
+  assert(chunk != NULL, "insert a NULL chunk");
+  assert(size() == chunk->size(), "wrong size");
+
+  Chunk* oldTail = tail();
+  assert(chunk != oldTail, "double insertion");
+  if (oldTail != NULL) {
+    oldTail->link_after(chunk);
+  } else { // only chunk in list
+    assert(head() == NULL, "inconsistent FreeList");
+    link_head(chunk);
+  }
+  link_tail(chunk);
+  increment_count();  // of # of chunks in list
+  DEBUG_ONLY(
+    if (record_return) {
+      increment_returned_bytes_by(size()*HeapWordSize);
+    }
+  )
+  assert(head() == NULL || head()->prev() == NULL, "list invariant");
+  assert(tail() == NULL || tail()->next() == NULL, "list invariant");
+  assert(head() == NULL || head()->size() == size(), "wrong item on list");
+  assert(tail() == NULL || tail()->size() == size(), "wrong item on list");
+}
+
+template <class Chunk>
+void FreeList<Chunk>::return_chunk_at_tail(Chunk* chunk) {
+  return_chunk_at_tail(chunk, true);
+}
+
+template <class Chunk>
+void FreeList<Chunk>::prepend(FreeList<Chunk>* fl) {
+  assert_proper_lock_protection();
+  if (fl->count() > 0) {
+    if (count() == 0) {
+      set_head(fl->head());
+      set_tail(fl->tail());
+      set_count(fl->count());
+    } else {
+      // Both are non-empty.
+      Chunk* fl_tail = fl->tail();
+      Chunk* this_head = head();
+      assert(fl_tail->next() == NULL, "Well-formedness of fl");
+      fl_tail->link_next(this_head);
+      this_head->link_prev(fl_tail);
+      set_head(fl->head());
+      set_count(count() + fl->count());
+    }
+    fl->set_head(NULL);
+    fl->set_tail(NULL);
+    fl->set_count(0);
+  }
+}
+
+// verify_chunk_in_free_list() is used to verify that an item is in this free list.
+// It is used as a debugging aid.
+template <class Chunk>
+bool FreeList<Chunk>::verify_chunk_in_free_list(Chunk* fc) const {
+  // This is an internal consistency check, not part of the check that the
+  // chunk is in the free lists.
+  guarantee(fc->size() == size(), "Wrong list is being searched");
+  Chunk* curFC = head();
+  while (curFC) {
+    // This is an internal consistency check.
+    guarantee(size() == curFC->size(), "Chunk is in wrong list.");
+    if (fc == curFC) {
+      return true;
+    }
+    curFC = curFC->next();
+  }
+  return false;
+}
+
+#ifndef PRODUCT
+template <class Chunk>
+void FreeList<Chunk>::verify_stats() const {
+  // The +1 of the LH comparand is to allow some "looseness" in
+  // checking: we usually call this interface when adding a block
+  // and we'll subsequently update the stats; we cannot update the
+  // stats beforehand because in the case of the large-block BT
+  // dictionary for example, this might be the first block and
+  // in that case there would be no place that we could record
+  // the stats (which are kept in the block itself).
+  assert((_allocation_stats.prev_sweep() + _allocation_stats.split_births()
+          + _allocation_stats.coal_births() + 1)   // Total Production Stock + 1
+         >= (_allocation_stats.split_deaths() + _allocation_stats.coal_deaths()
+             + (ssize_t)count()),                // Total Current Stock + depletion
+         err_msg("FreeList " PTR_FORMAT " of size " SIZE_FORMAT
+                 " violates Conservation Principle: "
+                 "prev_sweep(" SIZE_FORMAT ")"
+                 " + split_births(" SIZE_FORMAT ")"
+                 " + coal_births(" SIZE_FORMAT ") + 1 >= "
+                 " split_deaths(" SIZE_FORMAT ")"
+                 " coal_deaths(" SIZE_FORMAT ")"
+                 " + count(" SSIZE_FORMAT ")",
+                 this, _size, _allocation_stats.prev_sweep(), _allocation_stats.split_births(),
+                 _allocation_stats.split_births(), _allocation_stats.split_deaths(),
+                 _allocation_stats.coal_deaths(), count()));
+}
+
+template <class Chunk>
+void FreeList<Chunk>::assert_proper_lock_protection_work() const {
+  assert(_protecting_lock != NULL, "Don't call this directly");
+  assert(ParallelGCThreads > 0, "Don't call this directly");
+  Thread* thr = Thread::current();
+  if (thr->is_VM_thread() || thr->is_ConcurrentGC_thread()) {
+    // assert that we are holding the freelist lock
+  } else if (thr->is_GC_task_thread()) {
+    assert(_protecting_lock->owned_by_self(), "FreeList RACE DETECTED");
+  } else if (thr->is_Java_thread()) {
+    assert(!SafepointSynchronize::is_at_safepoint(), "Should not be executing");
+  } else {
+    ShouldNotReachHere();  // unaccounted thread type?
+  }
+}
+#endif
+
+// Print the "label line" for free list stats.
+template <class Chunk>
+void FreeList<Chunk>::print_labels_on(outputStream* st, const char* c) {
+  st->print("%16s\t", c);
+  st->print("%14s\t"    "%14s\t"    "%14s\t"    "%14s\t"    "%14s\t"
+            "%14s\t"    "%14s\t"    "%14s\t"    "%14s\t"    "%14s\t"    "\n",
+            "bfrsurp", "surplus", "desired", "prvSwep", "bfrSwep",
+            "count",   "cBirths", "cDeaths", "sBirths", "sDeaths");
+}
+
+// Print the AllocationStats for the given free list. If the second argument
+// to the call is a non-null string, it is printed in the first column;
+// otherwise, if the argument is null (the default), then the size of the
+// (free list) block is printed in the first column.
+template <class Chunk>
+void FreeList<Chunk>::print_on(outputStream* st, const char* c) const {
+  if (c != NULL) {
+    st->print("%16s", c);
+  } else {
+    st->print(SIZE_FORMAT_W(16), size());
+  }
+  st->print("\t"
+           SSIZE_FORMAT_W(14) "\t" SSIZE_FORMAT_W(14) "\t" SSIZE_FORMAT_W(14) "\t" SSIZE_FORMAT_W(14) "\t" SSIZE_FORMAT_W(14) "\t"
+           SSIZE_FORMAT_W(14) "\t" SSIZE_FORMAT_W(14) "\t" SSIZE_FORMAT_W(14) "\t" SSIZE_FORMAT_W(14) "\t" SSIZE_FORMAT_W(14) "\n",
+           bfr_surp(),             surplus(),             desired(),             prev_sweep(),           before_sweep(),
+           count(),               coal_births(),          coal_deaths(),          split_births(),         split_deaths());
+}
+
+#ifndef SERIALGC
+// Needs to be after the definitions have been seen.
+template class FreeList<FreeChunk>;
+#endif // SERIALGC
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/memory/freeList.hpp	Wed Jul 05 18:10:27 2017 +0200
@@ -0,0 +1,329 @@
+/*
+ * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef SHARE_VM_MEMORY_FREELIST_HPP
+#define SHARE_VM_MEMORY_FREELIST_HPP
+
+#include "gc_implementation/shared/allocationStats.hpp"
+
+class CompactibleFreeListSpace;
+
+// A class for maintaining a free list of Chunk's.  The FreeList
+// maintains a the structure of the list (head, tail, etc.) plus
+// statistics for allocations from the list.  The links between items
+// are not part of FreeList.  The statistics are
+// used to make decisions about coalescing Chunk's when they
+// are swept during collection.
+//
+// See the corresponding .cpp file for a description of the specifics
+// for that implementation.
+
+class Mutex;
+template <class Chunk> class TreeList;
+template <class Chunk> class PrintTreeCensusClosure;
+
+template <class Chunk>
+class FreeList VALUE_OBJ_CLASS_SPEC {
+  friend class CompactibleFreeListSpace;
+  friend class VMStructs;
+  friend class PrintTreeCensusClosure<Chunk>;
+
+ private:
+  Chunk*        _head;          // Head of list of free chunks
+  Chunk*        _tail;          // Tail of list of free chunks
+  size_t        _size;          // Size in Heap words of each chunk
+  ssize_t       _count;         // Number of entries in list
+  size_t        _hint;          // next larger size list with a positive surplus
+
+  AllocationStats _allocation_stats; // allocation-related statistics
+
+#ifdef ASSERT
+  Mutex*        _protecting_lock;
+#endif
+
+  // Asserts false if the protecting lock (if any) is not held.
+  void assert_proper_lock_protection_work() const PRODUCT_RETURN;
+  void assert_proper_lock_protection() const {
+#ifdef ASSERT
+    if (_protecting_lock != NULL)
+      assert_proper_lock_protection_work();
+#endif
+  }
+
+  // Initialize the allocation statistics.
+ protected:
+  void init_statistics(bool split_birth = false);
+  void set_count(ssize_t v) { _count = v;}
+  void increment_count()    {
+    _count++;
+  }
+
+  void decrement_count() {
+    _count--;
+    assert(_count >= 0, "Count should not be negative");
+  }
+
+ public:
+  // Constructor
+  // Construct a list without any entries.
+  FreeList();
+  // Construct a list with "fc" as the first (and lone) entry in the list.
+  FreeList(Chunk* fc);
+
+  // Reset the head, tail, hint, and count of a free list.
+  void reset(size_t hint);
+
+  // Declare the current free list to be protected by the given lock.
+#ifdef ASSERT
+  void set_protecting_lock(Mutex* protecting_lock) {
+    _protecting_lock = protecting_lock;
+  }
+#endif
+
+  // Accessors.
+  Chunk* head() const {
+    assert_proper_lock_protection();
+    return _head;
+  }
+  void set_head(Chunk* v) {
+    assert_proper_lock_protection();
+    _head = v;
+    assert(!_head || _head->size() == _size, "bad chunk size");
+  }
+  // Set the head of the list and set the prev field of non-null
+  // values to NULL.
+  void link_head(Chunk* v) {
+    assert_proper_lock_protection();
+    set_head(v);
+    // If this method is not used (just set the head instead),
+    // this check can be avoided.
+    if (v != NULL) {
+      v->link_prev(NULL);
+    }
+  }
+
+  Chunk* tail() const {
+    assert_proper_lock_protection();
+    return _tail;
+  }
+  void set_tail(Chunk* v) {
+    assert_proper_lock_protection();
+    _tail = v;
+    assert(!_tail || _tail->size() == _size, "bad chunk size");
+  }
+  // Set the tail of the list and set the next field of non-null
+  // values to NULL.
+  void link_tail(Chunk* v) {
+    assert_proper_lock_protection();
+    set_tail(v);
+    if (v != NULL) {
+      v->clear_next();
+    }
+  }
+
+  // No locking checks in read-accessors: lock-free reads (only) are benign.
+  // Readers are expected to have the lock if they are doing work that
+  // requires atomicity guarantees in sections of code.
+  size_t size() const {
+    return _size;
+  }
+  void set_size(size_t v) {
+    assert_proper_lock_protection();
+    _size = v;
+  }
+  ssize_t count() const {
+    return _count;
+  }
+  size_t hint() const {
+    return _hint;
+  }
+  void set_hint(size_t v) {
+    assert_proper_lock_protection();
+    assert(v == 0 || _size < v, "Bad hint"); _hint = v;
+  }
+
+  // Accessors for statistics
+  AllocationStats* allocation_stats() {
+    assert_proper_lock_protection();
+    return &_allocation_stats;
+  }
+
+  ssize_t desired() const {
+    return _allocation_stats.desired();
+  }
+  void set_desired(ssize_t v) {
+    assert_proper_lock_protection();
+    _allocation_stats.set_desired(v);
+  }
+  void compute_desired(float inter_sweep_current,
+                       float inter_sweep_estimate,
+                       float intra_sweep_estimate) {
+    assert_proper_lock_protection();
+    _allocation_stats.compute_desired(_count,
+                                      inter_sweep_current,
+                                      inter_sweep_estimate,
+                                      intra_sweep_estimate);
+  }
+  ssize_t coal_desired() const {
+    return _allocation_stats.coal_desired();
+  }
+  void set_coal_desired(ssize_t v) {
+    assert_proper_lock_protection();
+    _allocation_stats.set_coal_desired(v);
+  }
+
+  ssize_t surplus() const {
+    return _allocation_stats.surplus();
+  }
+  void set_surplus(ssize_t v) {
+    assert_proper_lock_protection();
+    _allocation_stats.set_surplus(v);
+  }
+  void increment_surplus() {
+    assert_proper_lock_protection();
+    _allocation_stats.increment_surplus();
+  }
+  void decrement_surplus() {
+    assert_proper_lock_protection();
+    _allocation_stats.decrement_surplus();
+  }
+
+  ssize_t bfr_surp() const {
+    return _allocation_stats.bfr_surp();
+  }
+  void set_bfr_surp(ssize_t v) {
+    assert_proper_lock_protection();
+    _allocation_stats.set_bfr_surp(v);
+  }
+  ssize_t prev_sweep() const {
+    return _allocation_stats.prev_sweep();
+  }
+  void set_prev_sweep(ssize_t v) {
+    assert_proper_lock_protection();
+    _allocation_stats.set_prev_sweep(v);
+  }
+  ssize_t before_sweep() const {
+    return _allocation_stats.before_sweep();
+  }
+  void set_before_sweep(ssize_t v) {
+    assert_proper_lock_protection();
+    _allocation_stats.set_before_sweep(v);
+  }
+
+  ssize_t coal_births() const {
+    return _allocation_stats.coal_births();
+  }
+  void set_coal_births(ssize_t v) {
+    assert_proper_lock_protection();
+    _allocation_stats.set_coal_births(v);
+  }
+  void increment_coal_births() {
+    assert_proper_lock_protection();
+    _allocation_stats.increment_coal_births();
+  }
+
+  ssize_t coal_deaths() const {
+    return _allocation_stats.coal_deaths();
+  }
+  void set_coal_deaths(ssize_t v) {
+    assert_proper_lock_protection();
+    _allocation_stats.set_coal_deaths(v);
+  }
+  void increment_coal_deaths() {
+    assert_proper_lock_protection();
+    _allocation_stats.increment_coal_deaths();
+  }
+
+  ssize_t split_births() const {
+    return _allocation_stats.split_births();
+  }
+  void set_split_births(ssize_t v) {
+    assert_proper_lock_protection();
+    _allocation_stats.set_split_births(v);
+  }
+  void increment_split_births() {
+    assert_proper_lock_protection();
+    _allocation_stats.increment_split_births();
+  }
+
+  ssize_t split_deaths() const {
+    return _allocation_stats.split_deaths();
+  }
+  void set_split_deaths(ssize_t v) {
+    assert_proper_lock_protection();
+    _allocation_stats.set_split_deaths(v);
+  }
+  void increment_split_deaths() {
+    assert_proper_lock_protection();
+    _allocation_stats.increment_split_deaths();
+  }
+
+  NOT_PRODUCT(
+    // For debugging.  The "_returned_bytes" in all the lists are summed
+    // and compared with the total number of bytes swept during a
+    // collection.
+    size_t returned_bytes() const { return _allocation_stats.returned_bytes(); }
+    void set_returned_bytes(size_t v) { _allocation_stats.set_returned_bytes(v); }
+    void increment_returned_bytes_by(size_t v) {
+      _allocation_stats.set_returned_bytes(_allocation_stats.returned_bytes() + v);
+    }
+  )
+
+  // Unlink head of list and return it.  Returns NULL if
+  // the list is empty.
+  Chunk* get_chunk_at_head();
+
+  // Remove the first "n" or "count", whichever is smaller, chunks from the
+  // list, setting "fl", which is required to be empty, to point to them.
+  void getFirstNChunksFromList(size_t n, FreeList<Chunk>* fl);
+
+  // Unlink this chunk from it's free list
+  void remove_chunk(Chunk* fc);
+
+  // Add this chunk to this free list.
+  void return_chunk_at_head(Chunk* fc);
+  void return_chunk_at_tail(Chunk* fc);
+
+  // Similar to returnChunk* but also records some diagnostic
+  // information.
+  void return_chunk_at_head(Chunk* fc, bool record_return);
+  void return_chunk_at_tail(Chunk* fc, bool record_return);
+
+  // Prepend "fl" (whose size is required to be the same as that of "this")
+  // to the front of "this" list.
+  void prepend(FreeList<Chunk>* fl);
+
+  // Verify that the chunk is in the list.
+  // found.  Return NULL if "fc" is not found.
+  bool verify_chunk_in_free_list(Chunk* fc) const;
+
+  // Stats verification
+  void verify_stats() const PRODUCT_RETURN;
+
+  // Printing support
+  static void print_labels_on(outputStream* st, const char* c);
+  void print_on(outputStream* st, const char* c = NULL) const;
+};
+
+#endif // SHARE_VM_MEMORY_FREELIST_HPP
--- a/hotspot/src/share/vm/memory/generationSpec.cpp	Wed Jul 05 18:09:43 2017 +0200
+++ b/hotspot/src/share/vm/memory/generationSpec.cpp	Wed Jul 05 18:10:27 2017 +0200
@@ -68,7 +68,7 @@
       ConcurrentMarkSweepGeneration* g = NULL;
       g = new ConcurrentMarkSweepGeneration(rs,
                  init_size(), level, ctrs, UseCMSAdaptiveFreeLists,
-                 (FreeBlockDictionary::DictionaryChoice)CMSDictionaryChoice);
+                 (FreeBlockDictionary<FreeChunk>::DictionaryChoice)CMSDictionaryChoice);
 
       g->initialize_performance_counters();
 
@@ -88,7 +88,7 @@
       ASConcurrentMarkSweepGeneration* g = NULL;
       g = new ASConcurrentMarkSweepGeneration(rs,
                  init_size(), level, ctrs, UseCMSAdaptiveFreeLists,
-                 (FreeBlockDictionary::DictionaryChoice)CMSDictionaryChoice);
+                 (FreeBlockDictionary<FreeChunk>::DictionaryChoice)CMSDictionaryChoice);
 
       g->initialize_performance_counters();
 
@@ -175,7 +175,7 @@
       }
       // XXXPERM
       return new CMSPermGen(perm_rs, init_size, ctrs,
-                   (FreeBlockDictionary::DictionaryChoice)CMSDictionaryChoice);
+                   (FreeBlockDictionary<FreeChunk>::DictionaryChoice)CMSDictionaryChoice);
     }
 #endif // SERIALGC
     default:
--- a/hotspot/src/share/vm/precompiled/precompiled.hpp	Wed Jul 05 18:09:43 2017 +0200
+++ b/hotspot/src/share/vm/precompiled/precompiled.hpp	Wed Jul 05 18:10:27 2017 +0200
@@ -293,13 +293,10 @@
 # include "c1/c1_globals.hpp"
 #endif // COMPILER1
 #ifndef SERIALGC
-# include "gc_implementation/concurrentMarkSweep/binaryTreeDictionary.hpp"
 # include "gc_implementation/concurrentMarkSweep/cmsOopClosures.hpp"
 # include "gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.hpp"
 # include "gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp"
-# include "gc_implementation/concurrentMarkSweep/freeBlockDictionary.hpp"
 # include "gc_implementation/concurrentMarkSweep/freeChunk.hpp"
-# include "gc_implementation/concurrentMarkSweep/freeList.hpp"
 # include "gc_implementation/concurrentMarkSweep/promotionInfo.hpp"
 # include "gc_implementation/g1/dirtyCardQueue.hpp"
 # include "gc_implementation/g1/g1BlockOffsetTable.hpp"
--- a/hotspot/src/share/vm/runtime/arguments.cpp	Wed Jul 05 18:09:43 2017 +0200
+++ b/hotspot/src/share/vm/runtime/arguments.cpp	Wed Jul 05 18:10:27 2017 +0200
@@ -829,6 +829,9 @@
     } else {
       jio_fprintf(defaultStream::error_stream(), "%s", locked_message_buf);
     }
+  } else {
+    jio_fprintf(defaultStream::error_stream(),
+                "Unrecognized VM option '%s'\n", argname);
   }
 
   // allow for commandline "commenting out" options like -XX:#+Verbose
--- a/hotspot/src/share/vm/runtime/vmStructs.cpp	Wed Jul 05 18:09:43 2017 +0200
+++ b/hotspot/src/share/vm/runtime/vmStructs.cpp	Wed Jul 05 18:10:27 2017 +0200
@@ -44,7 +44,6 @@
 #include "code/vmreg.hpp"
 #include "compiler/oopMap.hpp"
 #include "compiler/compileBroker.hpp"
-#include "gc_implementation/concurrentMarkSweep/freeBlockDictionary.hpp"
 #include "gc_implementation/shared/immutableSpace.hpp"
 #include "gc_implementation/shared/markSweep.hpp"
 #include "gc_implementation/shared/mutableSpace.hpp"
@@ -55,6 +54,7 @@
 #include "memory/cardTableRS.hpp"
 #include "memory/compactPermGen.hpp"
 #include "memory/defNewGeneration.hpp"
+#include "memory/freeBlockDictionary.hpp"
 #include "memory/genCollectedHeap.hpp"
 #include "memory/generation.hpp"
 #include "memory/generationSpec.hpp"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/7162488/Test7162488.sh	Wed Jul 05 18:10:27 2017 +0200
@@ -0,0 +1,77 @@
+#
+#  Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+#  DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+#  This code is free software; you can redistribute it and/or modify it
+#  under the terms of the GNU General Public License version 2 only, as
+#  published by the Free Software Foundation.
+#
+#  This code is distributed in the hope that it will be useful, but WITHOUT
+#  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+#  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+#  version 2 for more details (a copy is included in the LICENSE file that
+#  accompanied this code).
+#
+#  You should have received a copy of the GNU General Public License version
+#  2 along with this work; if not, write to the Free Software Foundation,
+#  Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+#  Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+#  or visit www.oracle.com if you need additional information or have any
+#  questions.
+#
+
+
+# @test Test7162488.sh
+# @bug 7162488
+# @summary VM not printing unknown -XX options
+# @run shell Test7162488.sh
+#
+
+if [ "${TESTSRC}" = "" ]
+  then TESTSRC=.
+fi
+
+if [ "${TESTJAVA}" = "" ]
+then
+  PARENT=`dirname \`which java\``
+  TESTJAVA=`dirname ${PARENT}`
+  printf "TESTJAVA not set, selecting " ${TESTJAVA}
+  printf "  If this is incorrect, try setting the variable manually.\n"
+fi
+
+# set platform-dependent variables
+OS=`uname -s`
+case "$OS" in
+  Windows_* )
+    FS="\\"
+    ;;
+  * )
+    FS="/"
+    ;;
+esac
+
+JAVA=${TESTJAVA}${FS}bin${FS}java
+
+#
+# Just run with an option we are confident will not be recognized,
+# and check for the message:
+#
+OPTION=this_is_not_an_option
+
+${JAVA} ${TESTVMOPTS} -showversion -XX:${OPTION} 2>&1 | grep "Unrecognized VM option" 
+if [ "$?" != "0" ]
+then
+  printf "FAILED: option not flagged as unrecognized.\n"
+  exit 1
+fi
+
+${JAVA} ${TESTVMOPTS} -showversion -XX:${OPTION} 2>&1 | grep ${OPTION}
+if [ "$?" != "0" ]
+then
+  printf "FAILED: bad option not named as being bad.\n"
+  exit 1
+fi
+
+printf "Passed.\n"
+
--- a/jaxp/.hgtags	Wed Jul 05 18:09:43 2017 +0200
+++ b/jaxp/.hgtags	Wed Jul 05 18:10:27 2017 +0200
@@ -158,3 +158,4 @@
 8b91a897a04486cf901af0de7f684a3eb31f121f jdk8-b34
 e187f3ede64965dc2979df9a211107cd3d38eacb jdk8-b35
 cfd288fe1d3e2b700838342e70d71d44ac991af5 jdk8-b36
+90204bfab4e2bed402badcc997cbf8446ab5669f jdk8-b37
--- a/jaxws/.hgtags	Wed Jul 05 18:09:43 2017 +0200
+++ b/jaxws/.hgtags	Wed Jul 05 18:10:27 2017 +0200
@@ -158,3 +158,4 @@
 f1d020a49c8c33667fb10c8caa255206a78a3675 jdk8-b34
 e8afc16522e190cb93c66bcb15d6fba0fe9e6833 jdk8-b35
 89b36c658e39f0a2957be55453a3a3befd9c8a6b jdk8-b36
+b05a948db1b6c933c980f24e4dc8fd897b7cf4ef jdk8-b37
--- a/jdk/.hgtags	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/.hgtags	Wed Jul 05 18:10:27 2017 +0200
@@ -158,3 +158,4 @@
 29b680393f33bf953688c17d93aca7a870ca4024 jdk8-b34
 2e3e1356ffbddb2ae95c08da72830ba9ab8b3181 jdk8-b35
 45da9cb055ee258dc09e69c1718e27eadea38e45 jdk8-b36
+9e82ac15ab80370d6e021aea7b98c7c9626adb5e jdk8-b37
--- a/jdk/make/common/Defs-macosx.gmk	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/make/common/Defs-macosx.gmk	Wed Jul 05 18:10:27 2017 +0200
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
@@ -111,10 +111,10 @@
 
 # For all platforms, do not omit the frame pointer register usage. 
 #    We need this frame pointer to make it easy to walk the stacks.
-#    This should be the default on X86, but ia64 and amd64 may not have this
-#    as the default.
-CFLAGS_REQUIRED_amd64   += -m64 -fno-omit-frame-pointer -D_LITTLE_ENDIAN
-LDFLAGS_COMMON_amd64    += -m64
+#    This should be the default on X86, but ia64, and x86_64
+#    may not have this as the default.
+CFLAGS_REQUIRED_x86_64  += -m64 -fno-omit-frame-pointer -D_LITTLE_ENDIAN
+LDFLAGS_COMMON_x86_64   += -m64
 CFLAGS_REQUIRED_i586    += -m32 -fno-omit-frame-pointer -D_LITTLE_ENDIAN
 LDFLAGS_COMMON_i586     += -m32
 CFLAGS_REQUIRED_ia64    += -m64 -fno-omit-frame-pointer -D_LITTLE_ENDIAN
@@ -168,7 +168,7 @@
 PIC_CODE_SMALL = -fpic
 GLOBAL_KPIC = $(PIC_CODE_LARGE)
 CFLAGS_COMMON   += $(GLOBAL_KPIC) $(GCC_WARNINGS)
-ifeq ($(ARCH), amd64)
+ifeq ($(ARCH), x86_64)
  CFLAGS_COMMON += -pipe
 endif
 
--- a/jdk/make/common/Release-macosx.gmk	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/make/common/Release-macosx.gmk	Wed Jul 05 18:10:27 2017 +0200
@@ -29,14 +29,14 @@
 
 # Defines the release targets for Mac OS X build products
 
-JDK_BUNDLE_DIR = $(ABS_OUTPUTDIR)/j2sdk-bundle/$(THIS_JDK_VERSION).jdk/Contents
-JRE_BUNDLE_DIR = $(ABS_OUTPUTDIR)/j2re-bundle/$(THIS_JDK_VERSION).jre/Contents
+JDK_BUNDLE_DIR = $(ABS_OUTPUTDIR)/j2sdk-bundle/jdk$(JDK_VERSION).jdk/Contents
+JRE_BUNDLE_DIR = $(ABS_OUTPUTDIR)/j2re-bundle/jre$(JDK_VERSION).jre/Contents
 
 MACOSX_SRC	 = $(JDK_TOPDIR)/src/macosx
 
 BUNDLE_ID ?= net.java.openjdk
-BUNLDE_ID_JRE ?= $(BUNDLE_ID).jre
-BUNLDE_ID_JDK ?= $(BUNDLE_ID).jdk
+BUNDLE_ID_JRE ?= $(BUNDLE_ID).jre
+BUNDLE_ID_JDK ?= $(BUNDLE_ID).jdk
 
 BUNDLE_NAME ?= OpenJDK $(JDK_MINOR_VERSION)
 BUNDLE_NAME_JRE ?= $(BUNDLE_NAME)
--- a/jdk/make/common/shared/Platform.gmk	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/make/common/shared/Platform.gmk	Wed Jul 05 18:10:27 2017 +0200
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
@@ -264,7 +264,7 @@
                     echo sparc \
                     ;; \
                 x86_64) \
-                    echo amd64 \
+                    echo x86_64 \
                     ;; \
                 universal) \
                     echo universal \
--- a/jdk/make/launchers/Makefile.launcher	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/make/launchers/Makefile.launcher	Wed Jul 05 18:10:27 2017 +0200
@@ -81,6 +81,7 @@
 # SA tools
 ifeq ($(PROGRAM),jstack)
   SA_TOOL=true
+  INFO_PLIST_FILE=Info-privileged.plist
 endif
 ifeq ($(PROGRAM),jsadebugd)
   SA_TOOL=true
--- a/jdk/src/macosx/bin/amd64/jvm.cfg	Wed Jul 05 18:09:43 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,38 +0,0 @@
-# Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
-#
-# This code is free software; you can redistribute it and/or modify it
-# under the terms of the GNU General Public License version 2 only, as
-# published by the Free Software Foundation.  Oracle designates this
-# particular file as subject to the "Classpath" exception as provided
-# by Oracle in the LICENSE file that accompanied this code.
-#
-# This code is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-# version 2 for more details (a copy is included in the LICENSE file that
-# accompanied this code).
-#
-# You should have received a copy of the GNU General Public License version
-# 2 along with this work; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
-# or visit www.oracle.com if you need additional information or have any
-# questions.
-#
-# List of JVMs that can be used as an option to java, javac, etc.
-# Order is important -- first in this list is the default JVM.
-# NOTE that this both this file and its format are UNSUPPORTED and
-# WILL GO AWAY in a future release.
-#
-# You may also select a JVM in an arbitrary location with the
-# "-XXaltjvm=<jvm_dir>" option, but that too is unsupported
-# and may not be available in a future release.
-#
--server KNOWN
--client IGNORE
--hotspot ERROR
--classic WARN
--native ERROR
--green ERROR
--- a/jdk/src/macosx/bin/java_md_macosx.c	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/src/macosx/bin/java_md_macosx.c	Wed Jul 05 18:10:27 2017 +0200
@@ -906,11 +906,41 @@
 {
     char envVar[80];
     if (strstr(arg, "-Xdock:name=") == arg) {
+        /*
+         * The APP_NAME_<pid> environment variable is used to pass
+         * an application name as specified with the -Xdock:name command
+         * line option from Java launcher code to the AWT code in order
+         * to assign this name to the app's dock tile on the Mac.
+         * The _<pid> part is added to avoid collisions with child processes.
+         *
+         * WARNING: This environment variable is an implementation detail and
+         * isn't meant for use outside of the core platform. The mechanism for
+         * passing this information from Java launcher to other modules may
+         * change drastically between update release, and it may even be
+         * removed or replaced with another mechanism.
+         *
+         * NOTE: It is used by SWT, and JavaFX.
+         */
         snprintf(envVar, sizeof(envVar), "APP_NAME_%d", getpid());
         setenv(envVar, (arg + 12), 1);
     }
 
     if (strstr(arg, "-Xdock:icon=") == arg) {
+        /*
+         * The APP_ICON_<pid> environment variable is used to pass
+         * an application icon as specified with the -Xdock:icon command
+         * line option from Java launcher code to the AWT code in order
+         * to assign this icon to the app's dock tile on the Mac.
+         * The _<pid> part is added to avoid collisions with child processes.
+         *
+         * WARNING: This environment variable is an implementation detail and
+         * isn't meant for use outside of the core platform. The mechanism for
+         * passing this information from Java launcher to other modules may
+         * change drastically between update release, and it may even be
+         * removed or replaced with another mechanism.
+         *
+         * NOTE: It is used by SWT, and JavaFX.
+         */
         snprintf(envVar, sizeof(envVar), "APP_ICON_%d", getpid());
         setenv(envVar, (arg + 12), 1);
     }
@@ -931,6 +961,22 @@
     NULL_CHECK(mainClassName = (*env)->GetStringUTFChars(env, mainClassString, NULL));
 
     char envVar[80];
+    /*
+     * The JAVA_MAIN_CLASS_<pid> environment variable is used to pass
+     * the name of a Java class whose main() method is invoked by
+     * the Java launcher code to start the application, to the AWT code
+     * in order to assign the name to the Apple menu bar when the app
+     * is active on the Mac.
+     * The _<pid> part is added to avoid collisions with child processes.
+     *
+     * WARNING: This environment variable is an implementation detail and
+     * isn't meant for use outside of the core platform. The mechanism for
+     * passing this information from Java launcher to other modules may
+     * change drastically between update release, and it may even be
+     * removed or replaced with another mechanism.
+     *
+     * NOTE: It is used by SWT, and JavaFX.
+     */
     snprintf(envVar, sizeof(envVar), "JAVA_MAIN_CLASS_%d", getpid());
     setenv(envVar, mainClassName, 1);
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/macosx/bin/x86_64/jvm.cfg	Wed Jul 05 18:10:27 2017 +0200
@@ -0,0 +1,38 @@
+# Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.  Oracle designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Oracle in the LICENSE file that accompanied this code.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+# List of JVMs that can be used as an option to java, javac, etc.
+# Order is important -- first in this list is the default JVM.
+# NOTE that this both this file and its format are UNSUPPORTED and
+# WILL GO AWAY in a future release.
+#
+# You may also select a JVM in an arbitrary location with the
+# "-XXaltjvm=<jvm_dir>" option, but that too is unsupported
+# and may not be available in a future release.
+#
+-server KNOWN
+-client IGNORE
+-hotspot ERROR
+-classic WARN
+-native ERROR
+-green ERROR
--- a/jdk/src/macosx/classes/apple/launcher/JavaAppLauncher.java	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/src/macosx/classes/apple/launcher/JavaAppLauncher.java	Wed Jul 05 18:10:27 2017 +0200
@@ -27,7 +27,6 @@
 
 import java.io.*;
 import java.lang.reflect.*;
-import java.security.PrivilegedAction;
 import java.text.MessageFormat;
 import java.util.*;
 import java.util.jar.*;
@@ -36,7 +35,13 @@
 
 class JavaAppLauncher implements Runnable {
     static {
-        java.security.AccessController.doPrivileged((PrivilegedAction<?>)new sun.security.action.LoadLibraryAction("osx"));
+        java.security.AccessController.doPrivileged(
+            new java.security.PrivilegedAction<Void>() {
+                public Void run() {
+                    System.loadLibrary("osx");
+                    return null;
+                }
+            });
     }
 
     private static native <T> T nativeConvertAndRelease(final long ptr);
--- a/jdk/src/macosx/classes/apple/security/KeychainStore.java	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/src/macosx/classes/apple/security/KeychainStore.java	Wed Jul 05 18:10:27 2017 +0200
@@ -103,7 +103,13 @@
     private static final int SALT_LEN = 20;
 
     static {
-        java.security.AccessController.doPrivileged((PrivilegedAction<?>)new sun.security.action.LoadLibraryAction("osx"));
+        AccessController.doPrivileged(
+            new PrivilegedAction<Void>() {
+                public Void run() {
+                    System.loadLibrary("osx");
+                    return null;
+                }
+            });
         try {
             PKCS8ShroudedKeyBag_OID = new ObjectIdentifier(keyBag);
             pbeWithSHAAnd3KeyTripleDESCBC_OID = new ObjectIdentifier(pbeWithSHAAnd3KeyTripleDESCBC);
--- a/jdk/src/macosx/classes/com/apple/concurrent/LibDispatchNative.java	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/src/macosx/classes/com/apple/concurrent/LibDispatchNative.java	Wed Jul 05 18:10:27 2017 +0200
@@ -26,17 +26,23 @@
 package com.apple.concurrent;
 
 final class LibDispatchNative {
-        static {
-                java.security.AccessController.doPrivileged((java.security.PrivilegedAction<?>)new sun.security.action.LoadLibraryAction("osx"));
-        }
+    static {
+        java.security.AccessController.doPrivileged(
+            new java.security.PrivilegedAction<Void>() {
+                public Void run() {
+                    System.loadLibrary("osx");
+                    return null;
+                }
+            });
+    }
 
-        static native boolean nativeIsDispatchSupported();
-        static native long nativeGetMainQueue();
-        static native long nativeCreateConcurrentQueue(int priority);
-        static native long nativeCreateSerialQueue(String name);
-        static native void nativeReleaseQueue(long nativeQueue);
-        static native void nativeExecuteAsync(long nativeQueue, Runnable task);
-        static native void nativeExecuteSync(long nativeQueue, Runnable task);
+    static native boolean nativeIsDispatchSupported();
+    static native long nativeGetMainQueue();
+    static native long nativeCreateConcurrentQueue(int priority);
+    static native long nativeCreateSerialQueue(String name);
+    static native void nativeReleaseQueue(long nativeQueue);
+    static native void nativeExecuteAsync(long nativeQueue, Runnable task);
+    static native void nativeExecuteSync(long nativeQueue, Runnable task);
 
-        private LibDispatchNative() { }
+    private LibDispatchNative() { }
 }
--- a/jdk/src/macosx/classes/com/apple/eawt/Application.java	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/src/macosx/classes/com/apple/eawt/Application.java	Wed Jul 05 18:10:27 2017 +0200
@@ -28,7 +28,6 @@
 import java.awt.*;
 import java.awt.peer.*;
 import java.beans.Beans;
-import java.security.PrivilegedAction;
 
 import javax.swing.JMenuBar;
 
@@ -59,7 +58,13 @@
     static Application sApplication = null;
 
     static {
-        java.security.AccessController.doPrivileged((PrivilegedAction<?>)new sun.security.action.LoadLibraryAction("awt"));
+        java.security.AccessController.doPrivileged(
+            new java.security.PrivilegedAction<Void>() {
+                public Void run() {
+                    System.loadLibrary("awt");
+                    return null;
+                }
+            });
 
         checkSecurity();
         if (!Beans.isDesignTime()) {
--- a/jdk/src/macosx/classes/com/apple/eio/FileManager.java	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/src/macosx/classes/com/apple/eio/FileManager.java	Wed Jul 05 18:10:27 2017 +0200
@@ -55,7 +55,13 @@
  */
 public class FileManager {
     static {
-        java.security.AccessController.doPrivileged((java.security.PrivilegedAction<?>)new sun.security.action.LoadLibraryAction("osx"));
+        java.security.AccessController.doPrivileged(
+            new java.security.PrivilegedAction<Void>() {
+                public Void run() {
+                    System.loadLibrary("osx");
+                    return null;
+                }
+            });
     }
 
     /**
--- a/jdk/src/macosx/classes/com/apple/laf/AquaFileView.java	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/src/macosx/classes/com/apple/laf/AquaFileView.java	Wed Jul 05 18:10:27 2017 +0200
@@ -26,7 +26,6 @@
 package com.apple.laf;
 
 import java.io.*;
-import java.security.PrivilegedAction;
 import java.util.*;
 import java.util.Map.Entry;
 
@@ -57,7 +56,13 @@
     static final int kLSItemInfoExtensionIsHidden  = 0x00100000; /* Item has a hidden extension*/
 
     static {
-        java.security.AccessController.doPrivileged((PrivilegedAction<?>)new sun.security.action.LoadLibraryAction("osxui"));
+        java.security.AccessController.doPrivileged(
+            new java.security.PrivilegedAction<Void>() {
+                public Void run() {
+                    System.loadLibrary("osxui");
+                    return null;
+                }
+            });
     }
 
     // TODO: Un-comment this out when the native version exists
--- a/jdk/src/macosx/classes/com/apple/laf/AquaLookAndFeel.java	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/src/macosx/classes/com/apple/laf/AquaLookAndFeel.java	Wed Jul 05 18:10:27 2017 +0200
@@ -134,10 +134,16 @@
      * @see UIManager#setLookAndFeel
      */
     public void initialize() {
-        java.security.AccessController.doPrivileged((PrivilegedAction<?>)new sun.security.action.LoadLibraryAction("osxui"));
-        java.security.AccessController.doPrivileged(new PrivilegedAction<Object>(){
+        java.security.AccessController.doPrivileged(new PrivilegedAction<Void>() {
+                public Void run() {
+                    System.loadLibrary("osxui");
+                    return null;
+                }
+            });
+
+        java.security.AccessController.doPrivileged(new PrivilegedAction<Void>(){
             @Override
-            public Object run() {
+            public Void run() {
                 JRSUIControl.initJRSUI();
                 return null;
             }
--- a/jdk/src/macosx/classes/com/apple/laf/AquaNativeResources.java	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/src/macosx/classes/com/apple/laf/AquaNativeResources.java	Wed Jul 05 18:10:27 2017 +0200
@@ -27,7 +27,6 @@
 
 import java.awt.*;
 import java.awt.image.BufferedImage;
-import java.security.PrivilegedAction;
 
 import javax.swing.plaf.UIResource;
 
@@ -35,7 +34,13 @@
 
 public class AquaNativeResources {
     static {
-        java.security.AccessController.doPrivileged((PrivilegedAction<?>)new sun.security.action.LoadLibraryAction("osxui"));
+        java.security.AccessController.doPrivileged(
+            new java.security.PrivilegedAction<Void>() {
+                public Void run() {
+                    System.loadLibrary("osxui");
+                    return null;
+                }
+            });
     }
 
     // TODO: removing CColorPaint for now
--- a/jdk/src/macosx/classes/com/apple/laf/ScreenMenu.java	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/src/macosx/classes/com/apple/laf/ScreenMenu.java	Wed Jul 05 18:10:27 2017 +0200
@@ -28,7 +28,6 @@
 import java.awt.*;
 import java.awt.event.*;
 import java.awt.peer.MenuComponentPeer;
-import java.security.PrivilegedAction;
 import java.util.Hashtable;
 
 import javax.swing.*;
@@ -38,7 +37,13 @@
 
 class ScreenMenu extends Menu implements ContainerListener, ComponentListener, ScreenMenuPropertyHandler {
     static {
-        java.security.AccessController.doPrivileged((PrivilegedAction<?>)new sun.security.action.LoadLibraryAction("awt"));
+        java.security.AccessController.doPrivileged(
+            new java.security.PrivilegedAction<Void>() {
+                public Void run() {
+                    System.loadLibrary("awt");
+                    return null;
+                }
+            });
     }
 
     // screen menu stuff
--- a/jdk/src/macosx/classes/com/apple/laf/ScreenPopupFactory.java	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/src/macosx/classes/com/apple/laf/ScreenPopupFactory.java	Wed Jul 05 18:10:27 2017 +0200
@@ -26,15 +26,19 @@
 package com.apple.laf;
 
 import java.awt.*;
-import java.security.PrivilegedAction;
-
 import javax.swing.*;
 
 import sun.lwawt.macosx.CPlatformWindow;
 
 class ScreenPopupFactory extends PopupFactory {
     static {
-        java.security.AccessController.doPrivileged((PrivilegedAction<?>)new sun.security.action.LoadLibraryAction("osxui"));
+        java.security.AccessController.doPrivileged(
+            new java.security.PrivilegedAction<Void>() {
+                public Void run() {
+                    System.loadLibrary("osxui");
+                    return null;
+                }
+            });
     }
 
     static final Float TRANSLUCENT = new Float(248f/255f);
--- a/jdk/src/macosx/classes/java/util/prefs/MacOSXPreferences.java	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/src/macosx/classes/java/util/prefs/MacOSXPreferences.java	Wed Jul 05 18:10:27 2017 +0200
@@ -25,6 +25,8 @@
 
 package java.util.prefs;
 
+import java.util.Objects;
+
 class MacOSXPreferences extends AbstractPreferences {
     // fixme need security checks?
 
@@ -147,6 +149,7 @@
     // AbstractPreferences implementation
     protected void removeSpi(String key)
     {
+        Objects.requireNonNull(key, "Specified key cannot be null");
         file.removeKeyFromNode(path, key);
     }
 
@@ -228,8 +231,14 @@
             if (isRemoved())
                 throw new IllegalStateException("Node has been removed");
             // fixme! overkill
-            if (!MacOSXPreferencesFile.syncWorld()) {
-                throw new BackingStoreException("Synchronization failed for node '" + path + "'");
+            if (isUser) {
+                if (!MacOSXPreferencesFile.syncUser()) {
+                    throw new BackingStoreException("Synchronization failed for node '" + path + "'");
+                }
+            } else {
+                if (!MacOSXPreferencesFile.syncWorld()) {
+                    throw new BackingStoreException("Synchronization failed for node '" + path + "'");
+                }
             }
         }
     }
--- a/jdk/src/macosx/classes/java/util/prefs/MacOSXPreferencesFile.java	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/src/macosx/classes/java/util/prefs/MacOSXPreferencesFile.java	Wed Jul 05 18:10:27 2017 +0200
@@ -79,7 +79,13 @@
 class MacOSXPreferencesFile {
 
     static {
-        java.security.AccessController.doPrivileged(new sun.security.action.LoadLibraryAction("osx"));
+        java.security.AccessController.doPrivileged(
+            new java.security.PrivilegedAction<Void>() {
+                public Void run() {
+                    System.loadLibrary("osx");
+                    return null;
+                }
+            });
     }
 
     private class FlushTask extends TimerTask {
@@ -192,6 +198,39 @@
     }
 
 
+    // Sync only current user preferences
+    static synchronized boolean syncUser() {
+        boolean ok = true;
+        if (cachedFiles != null  &&  !cachedFiles.isEmpty()) {
+            Iterator<WeakReference> iter = cachedFiles.values().iterator();
+            while (iter.hasNext()) {
+                WeakReference ref = iter.next();
+                MacOSXPreferencesFile f = (MacOSXPreferencesFile)ref.get();
+                if (f != null && f.user == cfCurrentUser) {
+                    if (!f.synchronize()) {
+                        ok = false;
+                    }
+                } else {
+                    iter.remove();
+                }
+            }
+        }
+        // Remove synchronized file from changed file list. The changed files were
+        // guaranteed to have been in the cached file list (because there was a strong
+        // reference from changedFiles.
+        if (changedFiles != null) {
+            Iterator<MacOSXPreferencesFile> iterChanged = changedFiles.iterator();
+            while (iterChanged.hasNext()) {
+                MacOSXPreferencesFile f = iterChanged.next();
+                if (f != null && f.user == cfCurrentUser)
+                    iterChanged.remove();
+             }
+        }
+        return ok;
+    }
+
+
+
     // Write all prefs changes to disk, but do not clear all cached prefs
     // values. Also kills any scheduled flush task.
     // There's no CFPreferencesFlush() (<rdar://problem/3049129>), so lots of cached prefs
--- a/jdk/src/macosx/classes/sun/awt/CGraphicsEnvironment.java	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/src/macosx/classes/sun/awt/CGraphicsEnvironment.java	Wed Jul 05 18:10:27 2017 +0200
@@ -58,9 +58,15 @@
     public static void init() { }
 
     static {
-        java.security.AccessController.doPrivileged(new sun.security.action.LoadLibraryAction("awt"));
-        java.security.AccessController.doPrivileged(new java.security.PrivilegedAction<Object>() {
-            public Object run() {
+        java.security.AccessController.doPrivileged(new java.security.PrivilegedAction<Void>() {
+            public Void run() {
+                System.loadLibrary("awt");
+                return null;
+            }
+        });
+
+        java.security.AccessController.doPrivileged(new java.security.PrivilegedAction<Void>() {
+            public Void run() {
                 if (isHeadless()) return null;
                 initCocoa();
                 return null;
--- a/jdk/src/macosx/classes/sun/lwawt/LWTextAreaPeer.java	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/src/macosx/classes/sun/lwawt/LWTextAreaPeer.java	Wed Jul 05 18:10:27 2017 +0200
@@ -211,6 +211,15 @@
             }
 
             @Override
+            public void replaceSelection(String content) {
+                getDocument().removeDocumentListener(LWTextAreaPeer.this);
+                super.replaceSelection(content);
+                // post only one text event in this case
+                postTextEvent();
+                getDocument().addDocumentListener(LWTextAreaPeer.this);
+            }
+
+            @Override
             public boolean hasFocus() {
                 return getTarget().hasFocus();
             }
--- a/jdk/src/macosx/classes/sun/lwawt/LWTextComponentPeer.java	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/src/macosx/classes/sun/lwawt/LWTextComponentPeer.java	Wed Jul 05 18:10:27 2017 +0200
@@ -187,7 +187,7 @@
         }
     }
 
-    private void sendTextEvent(final DocumentEvent e) {
+    protected final void postTextEvent() {
         postEvent(new TextEvent(getTarget(), TextEvent.TEXT_VALUE_CHANGED));
         synchronized (getDelegateLock()) {
             revalidate();
@@ -196,17 +196,17 @@
 
     @Override
     public final void changedUpdate(final DocumentEvent e) {
-        sendTextEvent(e);
+        postTextEvent();
     }
 
     @Override
     public final void insertUpdate(final DocumentEvent e) {
-        sendTextEvent(e);
+        postTextEvent();
     }
 
     @Override
     public final void removeUpdate(final DocumentEvent e) {
-        sendTextEvent(e);
+        postTextEvent();
     }
 
     @Override
--- a/jdk/src/macosx/classes/sun/lwawt/LWTextFieldPeer.java	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/src/macosx/classes/sun/lwawt/LWTextFieldPeer.java	Wed Jul 05 18:10:27 2017 +0200
@@ -95,7 +95,7 @@
     @Override
     public void actionPerformed(final ActionEvent e) {
         postEvent(new ActionEvent(getTarget(), ActionEvent.ACTION_PERFORMED,
-                                  getText(), e.getWhen(), e.getModifiers()));
+                getText(), e.getWhen(), e.getModifiers()));
     }
 
     /**
@@ -122,6 +122,15 @@
         }
 
         @Override
+        public void replaceSelection(String content) {
+            getDocument().removeDocumentListener(LWTextFieldPeer.this);
+            super.replaceSelection(content);
+            // post only one text event in this case
+            postTextEvent();
+            getDocument().addDocumentListener(LWTextFieldPeer.this);
+        }
+
+        @Override
         public boolean hasFocus() {
             return getTarget().hasFocus();
         }
--- a/jdk/src/macosx/classes/sun/lwawt/LWWindowPeer.java	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/src/macosx/classes/sun/lwawt/LWWindowPeer.java	Wed Jul 05 18:10:27 2017 +0200
@@ -669,39 +669,42 @@
             }
         } else {
             if (targetPeer != lastMouseEventPeer) {
-                // lastMouseEventPeer may be null if mouse was out of Java windows
-                if (lastMouseEventPeer != null && lastMouseEventPeer.isEnabled()) {
-                    // Sometimes, MOUSE_EXITED is not sent by delegate (or is sent a bit
-                    // later), in which case lastWindowPeer is another window
-                    if (lastWindowPeer != this) {
-                        Point oldp = lastMouseEventPeer.windowToLocal(x, y, lastWindowPeer);
-                        // Additionally translate from this to lastWindowPeer coordinates
-                        Rectangle lr = lastWindowPeer.getBounds();
-                        oldp.x += r.x - lr.x;
-                        oldp.y += r.y - lr.y;
-                        postEvent(new MouseEvent(lastMouseEventPeer.getTarget(),
-                                                 MouseEvent.MOUSE_EXITED,
+
+                if (id != MouseEvent.MOUSE_DRAGGED || lastMouseEventPeer == null) {
+                    // lastMouseEventPeer may be null if mouse was out of Java windows
+                    if (lastMouseEventPeer != null && lastMouseEventPeer.isEnabled()) {
+                        // Sometimes, MOUSE_EXITED is not sent by delegate (or is sent a bit
+                        // later), in which case lastWindowPeer is another window
+                        if (lastWindowPeer != this) {
+                            Point oldp = lastMouseEventPeer.windowToLocal(x, y, lastWindowPeer);
+                            // Additionally translate from this to lastWindowPeer coordinates
+                            Rectangle lr = lastWindowPeer.getBounds();
+                            oldp.x += r.x - lr.x;
+                            oldp.y += r.y - lr.y;
+                            postEvent(new MouseEvent(lastMouseEventPeer.getTarget(),
+                                                     MouseEvent.MOUSE_EXITED,
+                                                     when, modifiers,
+                                                     oldp.x, oldp.y, screenX, screenY,
+                                                     clickCount, popupTrigger, button));
+                        } else {
+                            Point oldp = lastMouseEventPeer.windowToLocal(x, y, this);
+                            postEvent(new MouseEvent(lastMouseEventPeer.getTarget(),
+                                                     MouseEvent.MOUSE_EXITED,
+                                                     when, modifiers,
+                                                     oldp.x, oldp.y, screenX, screenY,
+                                                     clickCount, popupTrigger, button));
+                        }
+                    }
+                    if (targetPeer != null && targetPeer.isEnabled() && id != MouseEvent.MOUSE_ENTERED) {
+                        Point newp = targetPeer.windowToLocal(x, y, curWindowPeer);
+                        postEvent(new MouseEvent(targetPeer.getTarget(),
+                                                 MouseEvent.MOUSE_ENTERED,
                                                  when, modifiers,
-                                                 oldp.x, oldp.y, screenX, screenY,
-                                                 clickCount, popupTrigger, button));
-                    } else {
-                        Point oldp = lastMouseEventPeer.windowToLocal(x, y, this);
-                        postEvent(new MouseEvent(lastMouseEventPeer.getTarget(),
-                                                 MouseEvent.MOUSE_EXITED,
-                                                 when, modifiers,
-                                                 oldp.x, oldp.y, screenX, screenY,
+                                                 newp.x, newp.y, screenX, screenY,
                                                  clickCount, popupTrigger, button));
                     }
                 }
                 lastMouseEventPeer = targetPeer;
-                if (targetPeer != null && targetPeer.isEnabled() && id != MouseEvent.MOUSE_ENTERED) {
-                    Point newp = targetPeer.windowToLocal(x, y, curWindowPeer);
-                    postEvent(new MouseEvent(targetPeer.getTarget(),
-                                             MouseEvent.MOUSE_ENTERED,
-                                             when, modifiers,
-                                             newp.x, newp.y, screenX, screenY,
-                                             clickCount, popupTrigger, button));
-                }
             }
             // TODO: fill "bdata" member of AWTEvent
 
--- a/jdk/src/macosx/classes/sun/lwawt/macosx/CAccessibility.java	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/src/macosx/classes/sun/lwawt/macosx/CAccessibility.java	Wed Jul 05 18:10:27 2017 +0200
@@ -29,7 +29,6 @@
 import java.beans.*;
 import java.lang.reflect.Field;
 import java.lang.reflect.InvocationTargetException;
-import java.security.PrivilegedAction;
 import java.util.*;
 import java.util.concurrent.Callable;
 
@@ -41,7 +40,13 @@
 
     static {
         // Need to load the native library for this code.
-        java.security.AccessController.doPrivileged((PrivilegedAction<?>)new sun.security.action.LoadLibraryAction("awt"));
+        java.security.AccessController.doPrivileged(
+            new java.security.PrivilegedAction<Void>() {
+                public Void run() {
+                    System.loadLibrary("awt");
+                    return null;
+                }
+            });
     }
 
     static CAccessibility sAccessibility;
--- a/jdk/src/macosx/classes/sun/lwawt/macosx/CCursorManager.java	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/src/macosx/classes/sun/lwawt/macosx/CCursorManager.java	Wed Jul 05 18:10:27 2017 +0200
@@ -36,6 +36,7 @@
     private static native Point2D nativeGetCursorPosition();
     private static native void nativeSetBuiltInCursor(final int type, final String name);
     private static native void nativeSetCustomCursor(final long imgPtr, final double x, final double y);
+    public static native void nativeSetAllowsCursorSetInBackground(final boolean allows);
 
     private static final int NAMED_CURSOR = -1;
 
--- a/jdk/src/macosx/classes/sun/lwawt/macosx/CEmbeddedFrame.java	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/src/macosx/classes/sun/lwawt/macosx/CEmbeddedFrame.java	Wed Jul 05 18:10:27 2017 +0200
@@ -76,6 +76,12 @@
         int screenX = locationOnScreen.x + x;
         int screenY = locationOnScreen.y + y;
 
+        if (eventType == CocoaConstants.NPCocoaEventMouseEntered) {
+            CCursorManager.nativeSetAllowsCursorSetInBackground(true);
+        } else if (eventType == CocoaConstants.NPCocoaEventMouseExited) {
+            CCursorManager.nativeSetAllowsCursorSetInBackground(false);
+        }
+
         responder.handleMouseEvent(eventType, modifierFlags, buttonNumber,
                                    clickCount, x, y, screenX, screenY);
     }
--- a/jdk/src/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/src/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java	Wed Jul 05 18:10:27 2017 +0200
@@ -61,6 +61,7 @@
     private static native void nativeSetNSWindowMinimizedIcon(long nsWindowPtr, long nsImage);
     private static native void nativeSetNSWindowRepresentedFilename(long nsWindowPtr, String representedFilename);
     private static native void nativeSetNSWindowSecurityWarningPositioning(long nsWindowPtr, double x, double y, float biasX, float biasY);
+    private static native void nativeSynthesizeMouseEnteredExitedEvents(long nsWindowPtr);
 
     private static native int nativeGetScreenNSWindowIsOn_AppKitThread(long nsWindowPtr);
 
@@ -582,6 +583,8 @@
             }
         }
 
+        nativeSynthesizeMouseEnteredExitedEvents(nsWindowPtr);
+
         // 6. Configure stuff #2
         updateFocusabilityForAutoRequestFocus(true);
 
@@ -791,6 +794,8 @@
                 throw new RuntimeException("Unknown window state: " + windowState);
         }
 
+        nativeSynthesizeMouseEnteredExitedEvents(nsWindowPtr);
+
         // NOTE: the SWP.windowState field gets updated to the newWindowState
         //       value when the native notification comes to us
     }
--- a/jdk/src/macosx/classes/sun/lwawt/macosx/LWCToolkit.java	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/src/macosx/classes/sun/lwawt/macosx/LWCToolkit.java	Wed Jul 05 18:10:27 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -656,6 +656,14 @@
         return ((mods & (InputEvent.META_MASK | InputEvent.CTRL_MASK)) == 0);
     }
 
+    /**
+     * Returns whether popup is allowed to be shown above the task bar.
+     */
+    @Override
+    public boolean canPopupOverlapTaskBar() {
+        return false;
+    }
+
     // Extends PeerEvent because we want to pass long an ObjC mediator object and because we want these events to be posted early
     // Typically, rather than relying on the notifier to call notifyAll(), we use the mediator to stop the runloop
     public static class CPeerEvent extends PeerEvent {
--- a/jdk/src/macosx/native/sun/awt/AWTView.h	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/src/macosx/native/sun/awt/AWTView.h	Wed Jul 05 18:10:27 2017 +0200
@@ -52,9 +52,12 @@
     BOOL fPAHNeedsToSelect;
 
     id cglLayer; // is a sublayer of view.layer
+
+    BOOL mouseIsOver;
 }
 
 @property (nonatomic, retain) id cglLayer;
+@property (nonatomic) BOOL mouseIsOver;
 
 - (id) initWithRect:(NSRect) rect platformView:(jobject)cPlatformView windowLayer:(CALayer*)windowLayer;
 - (void) deliverJavaMouseEvent: (NSEvent *) event;
--- a/jdk/src/macosx/native/sun/awt/AWTView.m	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/src/macosx/native/sun/awt/AWTView.m	Wed Jul 05 18:10:27 2017 +0200
@@ -61,6 +61,7 @@
 @synthesize _dropTarget;
 @synthesize _dragSource;
 @synthesize cglLayer;
+@synthesize mouseIsOver;
 
 // Note: Must be called on main (AppKit) thread only
 - (id) initWithRect: (NSRect) rect
@@ -80,6 +81,8 @@
     fEnablePressAndHold = shouldUsePressAndHold();
     fInPressAndHold = NO;
     fPAHNeedsToSelect = NO;
+    
+    mouseIsOver = NO;
 
     if (windowLayer != nil) {
         self.cglLayer = windowLayer;
@@ -299,6 +302,16 @@
  */
 
 -(void) deliverJavaMouseEvent: (NSEvent *) event {
+    
+    NSEventType type = [event type];    
+    
+    // check synthesized mouse entered/exited events
+    if ((type == NSMouseEntered && mouseIsOver) || (type == NSMouseExited && !mouseIsOver)) {
+        return;
+    }else if ((type == NSMouseEntered && !mouseIsOver) || (type == NSMouseExited && mouseIsOver)) {
+        mouseIsOver = !mouseIsOver;
+    }
+    
     [AWTToolkit eventCountPlusPlus];
 
     JNIEnv *env = [ThreadUtilities getJNIEnv];
@@ -306,7 +319,6 @@
     NSPoint eventLocation = [event locationInWindow];
     NSPoint localPoint = [self convertPoint: eventLocation fromView: nil];
     NSPoint absP = [NSEvent mouseLocation];
-    NSEventType type = [event type];
 
     // Convert global numbers between Cocoa's coordinate system and Java.
     // TODO: need consitent way for doing that both with global as well as with local coordinates.
--- a/jdk/src/macosx/native/sun/awt/AWTWindow.h	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/src/macosx/native/sun/awt/AWTWindow.h	Wed Jul 05 18:10:27 2017 +0200
@@ -56,6 +56,7 @@
                   contentView:(NSView *)contentView;
 
 - (void) adjustGrowBoxWindow;
+- (BOOL) isTopmostWindowUnderMouse;
 @end
 
 #endif _AWTWINDOW_H
--- a/jdk/src/macosx/native/sun/awt/AWTWindow.m	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/src/macosx/native/sun/awt/AWTWindow.m	Wed Jul 05 18:10:27 2017 +0200
@@ -170,6 +170,66 @@
     return self;
 }
 
+// checks that this window is under the mouse cursor and this point is not overlapped by others windows 
+- (BOOL) isTopmostWindowUnderMouse {
+    
+    int currentWinID = [self windowNumber]; 
+    
+    NSRect screenRect = [[NSScreen mainScreen] frame];    
+    NSPoint nsMouseLocation = [NSEvent mouseLocation];
+    CGPoint cgMouseLocation = CGPointMake(nsMouseLocation.x, screenRect.size.height - nsMouseLocation.y);    
+    
+    NSMutableArray *windows = (NSMutableArray *)CGWindowListCopyWindowInfo(kCGWindowListOptionOnScreenOnly | kCGWindowListExcludeDesktopElements, kCGNullWindowID);
+    
+    
+    for (NSDictionary *window in windows) {
+        int layer = [[window objectForKey:(id)kCGWindowLayer] intValue];
+        if (layer == 0) {
+            int winID = [[window objectForKey:(id)kCGWindowNumber] intValue];            
+            CGRect rect;
+            CGRectMakeWithDictionaryRepresentation((CFDictionaryRef)[window objectForKey:(id)kCGWindowBounds], &rect);
+            if (CGRectContainsPoint(rect, cgMouseLocation)) {
+                return currentWinID == winID;
+            } else if (currentWinID == winID) {
+                return NO;
+            }
+        }
+    }
+    return NO;
+}
+
+- (void) synthesizeMouseEnteredExitedEvents {
+    
+    int eventType = 0;
+    BOOL isUnderMouse = [self isTopmostWindowUnderMouse];
+    BOOL mouseIsOver = [[self contentView] mouseIsOver];
+    
+    if (isUnderMouse && !mouseIsOver) {
+        eventType = NSMouseEntered;
+    } else if (!isUnderMouse && mouseIsOver) {
+        eventType = NSMouseExited;        
+    } else {
+        return;
+    }
+    
+    NSPoint screenLocation = [NSEvent mouseLocation];        
+    NSPoint windowLocation = [self convertScreenToBase: screenLocation];        
+    int modifierFlags = (eventType == NSMouseEntered) ? NSMouseEnteredMask : NSMouseExitedMask;
+    
+    NSEvent *mouseEvent = [NSEvent enterExitEventWithType: eventType
+                                                  location: windowLocation
+                                             modifierFlags: modifierFlags
+                                                 timestamp: 0
+                                              windowNumber: [self windowNumber]
+                                                   context: nil
+                                               eventNumber: 0
+                                            trackingNumber: 0
+                                                  userData: nil
+                            ];
+    
+    [[self contentView] deliverJavaMouseEvent: mouseEvent];
+}
+
 - (void) dealloc {
 AWT_ASSERT_APPKIT_THREAD;
 
@@ -669,6 +729,8 @@
         // ensure we repaint the whole window after the resize operation
         // (this will also re-enable screen updates, which were disabled above)
         // TODO: send PaintEvent
+        
+        [window synthesizeMouseEnteredExitedEvents];
     }];
 
 JNF_COCOA_EXIT(env);
@@ -899,6 +961,27 @@
 
 /*
  * Class:     sun_lwawt_macosx_CPlatformWindow
+ * Method:    nativeSynthesizeMouseEnteredExitedEvents
+ * Signature: (J)V
+ */
+JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeSynthesizeMouseEnteredExitedEvents
+(JNIEnv *env, jclass clazz, jlong windowPtr)
+{
+    JNF_COCOA_ENTER(env);
+    AWT_ASSERT_NOT_APPKIT_THREAD;
+    
+    AWTWindow *window = OBJC(windowPtr);
+    [JNFRunLoop performOnMainThreadWaiting:NO withBlock:^(){
+        AWT_ASSERT_APPKIT_THREAD;
+        
+        [window synthesizeMouseEnteredExitedEvents];
+    }];
+    
+    JNF_COCOA_EXIT(env);
+}
+
+/*
+ * Class:     sun_lwawt_macosx_CPlatformWindow
  * Method:    nativeGetScreenNSWindowIsOn_AppKitThread
  * Signature: (J)I
  */
--- a/jdk/src/macosx/native/sun/awt/CCursorManager.m	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/src/macosx/native/sun/awt/CCursorManager.m	Wed Jul 05 18:10:27 2017 +0200
@@ -137,3 +137,30 @@
 
     return jpt;
 }
+
+
+JNIEXPORT void JNICALL
+Java_sun_lwawt_macosx_CCursorManager_nativeSetAllowsCursorSetInBackground
+(JNIEnv *env, jclass class, jboolean allows)
+{
+
+JNF_COCOA_ENTER(env);
+AWT_ASSERT_NOT_APPKIT_THREAD;
+
+    SEL allowsSetInBackground_SEL = @selector(javaSetAllowsCursorSetInBackground:);
+    if ([[NSCursor class] respondsToSelector:allowsSetInBackground_SEL]) {
+        [JNFRunLoop performOnMainThreadWaiting:YES withBlock:^(){
+            NSMethodSignature *allowsSetInBackground_sig =
+                [[NSCursor class] methodSignatureForSelector:allowsSetInBackground_SEL];
+            NSInvocation *invocation =
+                [NSInvocation invocationWithMethodSignature:allowsSetInBackground_sig];
+            BOOL arg = (BOOL)allows;
+            [invocation setSelector:allowsSetInBackground_SEL];
+            [invocation setArgument:&arg atIndex:2];
+            [invocation invokeWithTarget:[NSCursor class]];
+        }];
+    }
+
+JNF_COCOA_EXIT(env);
+
+}
--- a/jdk/src/macosx/native/sun/awt/PrinterView.m	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/src/macosx/native/sun/awt/PrinterView.m	Wed Jul 05 18:10:27 2017 +0200
@@ -27,6 +27,7 @@
 
 #import "java_awt_print_Pageable.h"
 #import "java_awt_print_Printable.h"
+#import "java_awt_print_PageFormat.h"
 
 #import <JavaNativeFoundation/JavaNativeFoundation.h>
 
@@ -35,6 +36,7 @@
 
 
 static JNF_CLASS_CACHE(sjc_CPrinterJob, "sun/lwawt/macosx/CPrinterJob");
+static JNF_CLASS_CACHE(sjc_PageFormat, "java/awt/print/PageFormat");
 
 @implementation PrinterView
 
@@ -152,6 +154,7 @@
 
     static JNF_MEMBER_CACHE(jm_getPageformatPrintablePeekgraphics, sjc_CPrinterJob, "getPageformatPrintablePeekgraphics", "(I)[Ljava/lang/Object;");
     static JNF_MEMBER_CACHE(jm_printAndGetPageFormatArea, sjc_CPrinterJob, "printAndGetPageFormatArea", "(Ljava/awt/print/Printable;Ljava/awt/Graphics;Ljava/awt/print/PageFormat;I)Ljava/awt/geom/Rectangle2D;");
+    static JNF_MEMBER_CACHE(jm_getOrientation, sjc_PageFormat, "getOrientation", "()I");
 
     // Assertions removed, and corresponding JNFDeleteGlobalRefs added, for radr://3962543
     // Actual fix that will keep these assertions from being true is radr://3205462 ,
@@ -201,6 +204,26 @@
         // Actually print and get the PageFormatArea
         jobject pageFormatArea = JNFCallObjectMethod(env, fPrinterJob, jm_printAndGetPageFormatArea, fCurPainter, fCurPeekGraphics, fCurPageFormat, jPageNumber); // AWT_THREADING Safe (AWTRunLoopMode)
         if (pageFormatArea != NULL) {
+            NSPrintingOrientation currentOrientation = 
+                    [[[NSPrintOperation currentOperation] printInfo] orientation];
+            // set page orientation
+            switch (JNFCallIntMethod(env, fCurPageFormat, jm_getOrientation)) { 
+                case java_awt_print_PageFormat_PORTRAIT:
+                default:
+                    if (currentOrientation != NSPortraitOrientation) {
+                        [[[NSPrintOperation currentOperation] printInfo] 
+                                            setOrientation:NSPortraitOrientation];
+                    }
+                    break;
+
+                case java_awt_print_PageFormat_LANDSCAPE:
+                case java_awt_print_PageFormat_REVERSE_LANDSCAPE:
+                    if (currentOrientation != NSLandscapeOrientation) {
+                        [[[NSPrintOperation currentOperation] printInfo] 
+                                            setOrientation:NSLandscapeOrientation];
+                    }
+                    break;
+                }
             result = JavaToNSRect(env, pageFormatArea);
             (*env)->DeleteLocalRef(env, pageFormatArea);
         } else {
--- a/jdk/src/share/bin/java.c	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/src/share/bin/java.c	Wed Jul 05 18:10:27 2017 +0200
@@ -695,6 +695,13 @@
     char *def;
     const char *orig = s;
     static const char format[] = "-Djava.class.path=%s";
+    /*
+     * usually we should not get a null pointer, but there are cases where
+     * we might just get one, in which case we simply ignore it, and let the
+     * caller deal with it
+     */
+    if (s == NULL)
+        return;
     s = JLI_WildcardExpandClasspath(s);
     def = JLI_MemAlloc(sizeof(format)
                        - 2 /* strlen("%s") */
--- a/jdk/src/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageReader.java	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/src/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageReader.java	Wed Jul 05 18:10:27 2017 +0200
@@ -87,7 +87,12 @@
 
     static {
         java.security.AccessController.doPrivileged(
-            new sun.security.action.LoadLibraryAction("jpeg"));
+            new java.security.PrivilegedAction<Void>() {
+                public Void run() {
+                    System.loadLibrary("jpeg");
+                    return null;
+                }
+            });
         initReaderIDs(ImageInputStream.class,
                       JPEGQTable.class,
                       JPEGHuffmanTable.class);
--- a/jdk/src/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageWriter.java	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/src/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageWriter.java	Wed Jul 05 18:10:27 2017 +0200
@@ -177,7 +177,12 @@
 
     static {
         java.security.AccessController.doPrivileged(
-            new sun.security.action.LoadLibraryAction("jpeg"));
+            new java.security.PrivilegedAction<Void>() {
+                public Void run() {
+                    System.loadLibrary("jpeg");
+                    return null;
+                }
+            });
         initWriterIDs(ImageOutputStream.class,
                       JPEGQTable.class,
                       JPEGHuffmanTable.class);
--- a/jdk/src/share/classes/com/sun/java/util/jar/pack/Attribute.java	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/src/share/classes/com/sun/java/util/jar/pack/Attribute.java	Wed Jul 05 18:10:27 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -166,6 +166,7 @@
         define(sd, ATTR_CONTEXT_CLASS, "SourceFile", "RUH");
         define(sd, ATTR_CONTEXT_CLASS, "EnclosingMethod", "RCHRDNH");
         define(sd, ATTR_CONTEXT_CLASS, "InnerClasses", "NH[RCHRCNHRUNHFH]");
+        define(sd, ATTR_CONTEXT_CLASS, "BootstrapMethods", "NH[RMHNH[KLH]]");
 
         define(sd, ATTR_CONTEXT_FIELD, "Signature", "RSH");
         define(sd, ATTR_CONTEXT_FIELD, "Synthetic", "");
@@ -203,6 +204,8 @@
         // Their layout specs. are given here for completeness.
         // The Code spec is incomplete, in that it does not distinguish
         // bytecode bytes or locate CP references.
+        // The BootstrapMethods attribute is also special-cased
+        // elsewhere as an appendix to the local constant pool.
     }
 
     // Metadata.
@@ -822,9 +825,9 @@
   reference_type:
         ( constant_ref | schema_ref | utf8_ref | untyped_ref )
   constant_ref:
-        ( 'KI' | 'KJ' | 'KF' | 'KD' | 'KS' | 'KQ' )
+        ( 'KI' | 'KJ' | 'KF' | 'KD' | 'KS' | 'KQ' | 'KM' | 'KT' | 'KL' )
   schema_ref:
-        ( 'RC' | 'RS' | 'RD' | 'RF' | 'RM' | 'RI' )
+        ( 'RC' | 'RS' | 'RD' | 'RF' | 'RM' | 'RI' | 'RY' | 'RB' | 'RN' )
   utf8_ref:
         'RU'
   untyped_ref:
@@ -1012,7 +1015,12 @@
                 case 'F': e.refKind = CONSTANT_Float; break;
                 case 'D': e.refKind = CONSTANT_Double; break;
                 case 'S': e.refKind = CONSTANT_String; break;
-                case 'Q': e.refKind = CONSTANT_Literal; break;
+                case 'Q': e.refKind = CONSTANT_FieldSpecific; break;
+
+                // new in 1.7:
+                case 'M': e.refKind = CONSTANT_MethodHandle; break;
+                case 'T': e.refKind = CONSTANT_MethodType; break;
+                case 'L': e.refKind = CONSTANT_LoadableValue; break;
                 default: { i = -i; continue; } // fail
                 }
                 break;
@@ -1029,6 +1037,11 @@
                 case 'U': e.refKind = CONSTANT_Utf8; break; //utf8_ref
                 case 'Q': e.refKind = CONSTANT_All; break; //untyped_ref
 
+                // new in 1.7:
+                case 'Y': e.refKind = CONSTANT_InvokeDynamic; break;
+                case 'B': e.refKind = CONSTANT_BootstrapMethod; break;
+                case 'N': e.refKind = CONSTANT_AnyMember; break;
+
                 default: { i = -i; continue; } // fail
                 }
                 break;
@@ -1279,10 +1292,12 @@
                         // Cf. ClassReader.readSignatureRef.
                         String typeName = globalRef.stringValue();
                         globalRef = ConstantPool.getSignatureEntry(typeName);
-                    } else if (e.refKind == CONSTANT_Literal) {
+                    } else if (e.refKind == CONSTANT_FieldSpecific) {
                         assert(globalRef.getTag() >= CONSTANT_Integer);
-                        assert(globalRef.getTag() <= CONSTANT_String);
-                    } else if (e.refKind != CONSTANT_All) {
+                        assert(globalRef.getTag() <= CONSTANT_String ||
+                               globalRef.getTag() >= CONSTANT_MethodHandle);
+                        assert(globalRef.getTag() <= CONSTANT_MethodType);
+                    } else if (e.refKind < CONSTANT_GroupFirst) {
                         assert(e.refKind == globalRef.getTag());
                     }
                 }
@@ -1462,27 +1477,29 @@
                 "NH[PHPOHIIH]",         // CharacterRangeTable
                 "NH[PHHII]",            // CoverageTable
                 "NH[RCHRCNHRUNHFH]",    // InnerClasses
+                "NH[RMHNH[KLH]]",       // BootstrapMethods
                 "HHNI[B]NH[PHPOHPOHRCNH]NH[RUHNI[B]]", // Code
                 "=AnnotationDefault",
                 // Like metadata, but with a compact tag set:
                 "[NH[(1)]]"
-                +"[NH[(2)]]"
-                +"[RSHNH[RUH(3)]]"
-                +"[TB(0,1,3)[KIH](2)[KDH](5)[KFH](4)[KJH](7)[RSH](8)[RSHRUH](9)[RUH](10)[(2)](6)[NH[(3)]]()[]]",
+                +"[NH[(1)]]"
+                +"[RSHNH[RUH(1)]]"
+                +"[TB(0,1,3)[KIH](2)[KDH](5)[KFH](4)[KJH](7)[RSH](8)[RSHRUH](9)[RUH](10)[(-1)](6)[NH[(0)]]()[]]",
                 ""
             };
             ap = 0;
         }
+        Utils.currentInstance.set(new PackerImpl());
         final int[][] counts = new int[2][3];  // int bci ref
         final Entry[] cpMap = new Entry[maxVal+1];
         for (int i = 0; i < cpMap.length; i++) {
             if (i == 0)  continue;  // 0 => null
             cpMap[i] = ConstantPool.getLiteralEntry(new Integer(i));
         }
-        Class cls = new Package().new Class("");
+        Package.Class cls = new Package().new Class("");
         cls.cpMap = cpMap;
         class TestValueStream extends ValueStream {
-            Random rand = new Random(0);
+            java.util.Random rand = new java.util.Random(0);
             ArrayList history = new ArrayList();
             int ckidx = 0;
             int maxVal;
@@ -1570,8 +1587,7 @@
                 String layout = av[i];
                 if (layout.startsWith("=")) {
                     String name = layout.substring(1);
-                    for (Iterator j = standardDefs.values().iterator(); j.hasNext(); ) {
-                        Attribute a = (Attribute) j.next();
+                    for (Attribute a : standardDefs.values()) {
                         if (a.name().equals(name)) {
                             layout = a.layout().layout();
                             break;
@@ -1604,7 +1620,7 @@
                 if (verbose) {
                     System.out.print("  parse: {");
                 }
-                self.parse(0, cls, bytes, 0, bytes.length, tts);
+                self.parse(cls, bytes, 0, bytes.length, tts);
                 if (verbose) {
                     System.out.println("}");
                 }
--- a/jdk/src/share/classes/com/sun/java/util/jar/pack/BandStructure.java	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/src/share/classes/com/sun/java/util/jar/pack/BandStructure.java	Wed Jul 05 18:10:27 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -1372,17 +1372,17 @@
     protected long archiveSize1; // size reported in archive_header
     protected int  archiveNextCount; // reported in archive_header
 
-    static final int AH_LENGTH_0 = 3; //minver, majver, options
-    static final int AH_ARCHIVE_SIZE_HI = 0;
-    static final int AH_ARCHIVE_SIZE_LO = 1;
-    static final int AH_LENGTH_S = 2; //optional size hi/lo
-    static final int AH_LENGTH = 26;  // mentioned in spec
+    static final int AH_LENGTH_0 = 3;     // archive_header_0 = {minver, majver, options}
+    static final int AH_LENGTH_MIN = 15;  // observed in spec {header_0[3], cp_counts[8], class_counts[4]}
+    // Length contributions from optional archive size fields:
+    static final int AH_LENGTH_S = 2; // archive_header_S = optional {size_hi, size_lo}
+    static final int AH_ARCHIVE_SIZE_HI = 0; // offset in archive_header_S
+    static final int AH_ARCHIVE_SIZE_LO = 1; // offset in archive_header_S
     // Length contributions from optional header fields:
-    static final int AH_FILE_HEADER_LEN = 5; // sizehi/lo/next/modtime/files
-    static final int AH_SPECIAL_FORMAT_LEN = 2; // layouts/band-headers
-    static final int AH_CP_NUMBER_LEN = 4;  // int/float/long/double
-    static final int AH_LENGTH_MIN = AH_LENGTH
-        -(AH_SPECIAL_FORMAT_LEN+AH_FILE_HEADER_LEN+AH_CP_NUMBER_LEN);
+    static final int AH_FILE_HEADER_LEN = 5; // file_counts = {{size_hi, size_lo}, next, modtime, files}
+    static final int AH_SPECIAL_FORMAT_LEN = 2; // special_counts = {layouts, band_headers}
+    static final int AH_CP_NUMBER_LEN = 4;  // cp_number_counts = {int, float, long, double}
+    static final int AH_CP_EXTRA_LEN = 4;  // cp_attr_counts = {MH, MT, InDy, BSM}
 
     // Common structure of attribute band groups:
     static final int AB_FLAGS_HI = 0;
@@ -1446,6 +1446,14 @@
     CPRefBand cp_Method_desc = cp_bands.newCPRefBand("cp_Method_desc", UDELTA5, CONSTANT_NameandType);
     CPRefBand cp_Imethod_class = cp_bands.newCPRefBand("cp_Imethod_class", CONSTANT_Class);
     CPRefBand cp_Imethod_desc = cp_bands.newCPRefBand("cp_Imethod_desc", UDELTA5, CONSTANT_NameandType);
+    IntBand   cp_MethodHandle_refkind = cp_bands.newIntBand("cp_MethodHandle_refkind", DELTA5);
+    CPRefBand cp_MethodHandle_member = cp_bands.newCPRefBand("cp_MethodHandle_member", UDELTA5, CONSTANT_AnyMember);
+    CPRefBand cp_MethodType = cp_bands.newCPRefBand("cp_MethodType", UDELTA5, CONSTANT_Signature);
+    CPRefBand cp_BootstrapMethod_ref = cp_bands.newCPRefBand("cp_BootstrapMethod_ref", DELTA5, CONSTANT_MethodHandle);
+    IntBand   cp_BootstrapMethod_arg_count = cp_bands.newIntBand("cp_BootstrapMethod_arg_count", UDELTA5);
+    CPRefBand cp_BootstrapMethod_arg = cp_bands.newCPRefBand("cp_BootstrapMethod_arg", DELTA5, CONSTANT_LoadableValue);
+    CPRefBand cp_InvokeDynamic_spec = cp_bands.newCPRefBand("cp_InvokeDynamic_spec", DELTA5, CONSTANT_BootstrapMethod);
+    CPRefBand cp_InvokeDynamic_desc = cp_bands.newCPRefBand("cp_InvokeDynamic_desc", UDELTA5, CONSTANT_NameandType);
 
     // bands for carrying attribute definitions:
     MultiBand attr_definition_bands = all_bands.newMultiBand("(attr_definition_bands)", UNSIGNED5);
@@ -1481,7 +1489,7 @@
     IntBand field_attr_calls = field_attr_bands.newIntBand("field_attr_calls");
 
     // bands for predefined field attributes
-    CPRefBand field_ConstantValue_KQ = field_attr_bands.newCPRefBand("field_ConstantValue_KQ", CONSTANT_Literal);
+    CPRefBand field_ConstantValue_KQ = field_attr_bands.newCPRefBand("field_ConstantValue_KQ", CONSTANT_FieldSpecific);
     CPRefBand field_Signature_RS = field_attr_bands.newCPRefBand("field_Signature_RS", CONSTANT_Signature);
     MultiBand field_metadata_bands = field_attr_bands.newMultiBand("(field_metadata_bands)", UNSIGNED5);
 
@@ -1585,12 +1593,14 @@
     CPRefBand bc_longref = bc_bands.newCPRefBand("bc_longref", DELTA5, CONSTANT_Long);
     CPRefBand bc_doubleref = bc_bands.newCPRefBand("bc_doubleref", DELTA5, CONSTANT_Double);
     CPRefBand bc_stringref = bc_bands.newCPRefBand("bc_stringref", DELTA5, CONSTANT_String);
+    CPRefBand bc_loadablevalueref = bc_bands.newCPRefBand("bc_loadablevalueref", DELTA5, CONSTANT_LoadableValue);
 
     // nulls produced by bc_classref are taken to mean the current class
     CPRefBand bc_classref = bc_bands.newCPRefBand("bc_classref", UNSIGNED5, CONSTANT_Class, NULL_IS_OK);   // new, *anew*, c*cast, i*of, ldc
     CPRefBand bc_fieldref = bc_bands.newCPRefBand("bc_fieldref", DELTA5, CONSTANT_Fieldref);   // get*, put*
     CPRefBand bc_methodref = bc_bands.newCPRefBand("bc_methodref", CONSTANT_Methodref); // invoke[vs]*
     CPRefBand bc_imethodref = bc_bands.newCPRefBand("bc_imethodref", DELTA5, CONSTANT_InterfaceMethodref); // invokeinterface
+    CPRefBand bc_indyref = bc_bands.newCPRefBand("bc_indyref", DELTA5, CONSTANT_InvokeDynamic); // invokedynamic
 
     // _self_linker_op family
     CPRefBand bc_thisfield = bc_bands.newCPRefBand("bc_thisfield", CONSTANT_None);     // any field within cur. class
@@ -1633,7 +1643,7 @@
 
     protected void setBandIndex(CPRefBand b, byte which) {
         Object[] need = { b, Byte.valueOf(which) };
-        if (which == CONSTANT_Literal) {
+        if (which == CONSTANT_FieldSpecific) {
             // I.e., attribute layouts KQ (no null) or KQN (null ok).
             allKQBands.add(b);
         } else if (needPredefIndex != null) {
@@ -1856,12 +1866,20 @@
         attrClassFileVersionMask = (1<<CLASS_ATTR_ClassFile_version);
     }
 
-    private void adjustToMajver() {
+    private void adjustToMajver() throws IOException {
         if (getPackageMajver() < JAVA6_PACKAGE_MAJOR_VERSION) {
             if (verbose > 0)  Utils.log.fine("Legacy package version");
             // Revoke definition of pre-1.6 attribute type.
             undefineAttribute(CODE_ATTR_StackMapTable, ATTR_CONTEXT_CODE);
         }
+        if (getPackageMajver() < JAVA7_PACKAGE_MAJOR_VERSION) {
+            if (testBit(archiveOptions, AO_HAVE_CP_EXTRAS))
+                // this bit was reserved for future use in previous versions
+                throw new IOException("Format bits for Java 7 must be zero in previous releases");
+        }
+        if (testBit(archiveOptions, AO_UNUSED_MBZ)) {
+            throw new IOException("High archive option bits are reserved and must be zero: "+Integer.toHexString(archiveOptions));
+        }
     }
 
     protected void initAttrIndexLimit() {
@@ -2323,7 +2341,9 @@
             return bc_methodref;
         case CONSTANT_InterfaceMethodref:
             return bc_imethodref;
-        case CONSTANT_Literal:
+        case CONSTANT_InvokeDynamic:
+            return bc_indyref;
+        case CONSTANT_LoadableValue:
             switch (bc) {
             case _ildc: case _ildc_w:
                 return bc_intref;
@@ -2333,10 +2353,12 @@
                 return bc_longref;
             case _dldc2_w:
                 return bc_doubleref;
-            case _aldc: case _aldc_w:
+            case _sldc: case _sldc_w:
                 return bc_stringref;
             case _cldc: case _cldc_w:
                 return bc_classref;
+            case _qldc: case _qldc_w:
+                return bc_loadablevalueref;
             }
             break;
         }
@@ -2623,15 +2645,23 @@
     }
 
     static void printArrayTo(PrintStream ps, Entry[] cpMap, int start, int end) {
+        printArrayTo(ps, cpMap, start, end, false);
+    }
+    static void printArrayTo(PrintStream ps, Entry[] cpMap, int start, int end, boolean showTags) {
         StringBuffer buf = new StringBuffer();
         int len = end-start;
         for (int i = 0; i < len; i++) {
-            String s = cpMap[start+i].stringValue();
+            Entry e = cpMap[start+i];
+            ps.print(start+i); ps.print("=");
+            if (showTags) { ps.print(e.tag); ps.print(":"); }
+            String s = e.stringValue();
             buf.setLength(0);
             for (int j = 0; j < s.length(); j++) {
                 char ch = s.charAt(j);
                 if (!(ch < ' ' || ch > '~' || ch == '\\')) {
                     buf.append(ch);
+                } else if (ch == '\\') {
+                    buf.append("\\\\");
                 } else if (ch == '\n') {
                     buf.append("\\n");
                 } else if (ch == '\t') {
@@ -2639,7 +2669,8 @@
                 } else if (ch == '\r') {
                     buf.append("\\r");
                 } else {
-                    buf.append("\\x"+Integer.toHexString(ch));
+                    String str = "000"+Integer.toHexString(ch);
+                    buf.append("\\u"+str.substring(str.length()-4));
                 }
             }
             ps.println(buf);
--- a/jdk/src/share/classes/com/sun/java/util/jar/pack/ClassReader.java	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/src/share/classes/com/sun/java/util/jar/pack/ClassReader.java	Wed Jul 05 18:10:27 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -29,6 +29,9 @@
 import com.sun.java.util.jar.pack.ConstantPool.DescriptorEntry;
 import com.sun.java.util.jar.pack.ConstantPool.Entry;
 import com.sun.java.util.jar.pack.ConstantPool.SignatureEntry;
+import com.sun.java.util.jar.pack.ConstantPool.MemberEntry;
+import com.sun.java.util.jar.pack.ConstantPool.MethodHandleEntry;
+import com.sun.java.util.jar.pack.ConstantPool.BootstrapMethodEntry;
 import com.sun.java.util.jar.pack.ConstantPool.Utf8Entry;
 import com.sun.java.util.jar.pack.Package.Class;
 import com.sun.java.util.jar.pack.Package.InnerClass;
@@ -37,6 +40,7 @@
 import java.io.IOException;
 import java.io.InputStream;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Map;
 import static com.sun.java.util.jar.pack.Constants.*;
 
@@ -114,6 +118,7 @@
     private Entry readRef(byte tag) throws IOException {
         Entry e = readRef();
         assert(e != null);
+        assert(!(e instanceof UnresolvedEntry));
         assert(e.tagMatches(tag));
         return e;
     }
@@ -151,6 +156,7 @@
             readMembers(false);  // fields
             readMembers(true);   // methods
             readAttributes(ATTR_CONTEXT_CLASS, cls);
+            fixUnresolvedEntries();
             cls.finishReading();
             assert(0 >= in.read(new byte[1]));
             ok = true;
@@ -236,6 +242,7 @@
                 // just read the refs; do not attempt to resolve while reading
                 case CONSTANT_Class:
                 case CONSTANT_String:
+                case CONSTANT_MethodType:
                     fixups[fptr++] = i;
                     fixups[fptr++] = tag;
                     fixups[fptr++] = in.readUnsignedShort();
@@ -250,6 +257,18 @@
                     fixups[fptr++] = in.readUnsignedShort();
                     fixups[fptr++] = in.readUnsignedShort();
                     break;
+                case CONSTANT_InvokeDynamic:
+                    fixups[fptr++] = i;
+                    fixups[fptr++] = tag;
+                    fixups[fptr++] = -1 ^ in.readUnsignedShort();  // not a ref
+                    fixups[fptr++] = in.readUnsignedShort();
+                    break;
+                case CONSTANT_MethodHandle:
+                    fixups[fptr++] = i;
+                    fixups[fptr++] = tag;
+                    fixups[fptr++] = -1 ^ in.readUnsignedByte();
+                    fixups[fptr++] = in.readUnsignedShort();
+                    break;
                 default:
                     throw new ClassFormatException("Bad constant pool tag " +
                             tag + " in File: " + cls.file.nameString +
@@ -270,7 +289,7 @@
                 int ref2 = fixups[fi++];
                 if (verbose > 3)
                     Utils.log.fine("  cp["+cpi+"] = "+ConstantPool.tagName(tag)+"{"+ref+","+ref2+"}");
-                if (cpMap[ref] == null || ref2 >= 0 && cpMap[ref2] == null) {
+                if (ref >= 0 && cpMap[ref] == null || ref2 >= 0 && cpMap[ref2] == null) {
                     // Defer.
                     fixups[fptr++] = cpi;
                     fixups[fptr++] = tag;
@@ -297,6 +316,19 @@
                     Utf8Entry mtype = (Utf8Entry) cpMap[ref2];
                     cpMap[cpi] = ConstantPool.getDescriptorEntry(mname, mtype);
                     break;
+                case CONSTANT_MethodType:
+                    cpMap[cpi] = ConstantPool.getMethodTypeEntry((Utf8Entry) cpMap[ref]);
+                    break;
+                case CONSTANT_MethodHandle:
+                    byte refKind = (byte)(-1 ^ ref);
+                    MemberEntry memRef = (MemberEntry) cpMap[ref2];
+                    cpMap[cpi] = ConstantPool.getMethodHandleEntry(refKind, memRef);
+                    break;
+                case CONSTANT_InvokeDynamic:
+                    DescriptorEntry idescr = (DescriptorEntry) cpMap[ref2];
+                    cpMap[cpi] = new UnresolvedEntry((byte)tag, (-1 ^ ref), idescr);
+                    // Note that ref must be resolved later, using the BootstrapMethods attribute.
+                    break;
                 default:
                     assert(false);
                 }
@@ -307,6 +339,50 @@
         cls.cpMap = cpMap;
     }
 
+    private /*non-static*/
+    class UnresolvedEntry extends Entry {
+        final Object[] refsOrIndexes;
+        UnresolvedEntry(byte tag, Object... refsOrIndexes) {
+            super(tag);
+            this.refsOrIndexes = refsOrIndexes;
+            ClassReader.this.haveUnresolvedEntry = true;
+        }
+        Entry resolve() {
+            Class cls = ClassReader.this.cls;
+            Entry res;
+            switch (tag) {
+            case CONSTANT_InvokeDynamic:
+                BootstrapMethodEntry iboots = cls.bootstrapMethods.get((Integer) refsOrIndexes[0]);
+                DescriptorEntry         idescr = (DescriptorEntry) refsOrIndexes[1];
+                res = ConstantPool.getInvokeDynamicEntry(iboots, idescr);
+                break;
+            default:
+                throw new AssertionError();
+            }
+            return res;
+        }
+        private void unresolved() { throw new RuntimeException("unresolved entry has no string"); }
+        public int compareTo(Object x) { unresolved(); return 0; }
+        public boolean equals(Object x) { unresolved(); return false; }
+        protected int computeValueHash() { unresolved(); return 0; }
+        public String stringValue() { unresolved(); return toString(); }
+        public String toString() { return "(unresolved "+ConstantPool.tagName(tag)+")"; }
+    }
+
+    boolean haveUnresolvedEntry;
+    private void fixUnresolvedEntries() {
+        if (!haveUnresolvedEntry)  return;
+        Entry[] cpMap = cls.getCPMap();
+        for (int i = 0; i < cpMap.length; i++) {
+            Entry e = cpMap[i];
+            if (e instanceof UnresolvedEntry) {
+                cpMap[i] = e = ((UnresolvedEntry)e).resolve();
+                assert(!(e instanceof UnresolvedEntry));
+            }
+        }
+        haveUnresolvedEntry = false;
+    }
+
     void readHeader() throws IOException {
         cls.flags = readUnsignedShort();
         cls.thisClass = readClassRef();
@@ -416,25 +492,31 @@
                                                         unknownAttrCommand);
                 }
             }
-            if (a.layout() == Package.attrCodeEmpty ||
-                a.layout() == Package.attrInnerClassesEmpty) {
+            long pos0 = inPos;  // in case we want to check it
+            if (a.layout() == Package.attrCodeEmpty) {
                 // These are hardwired.
-                long pos0 = inPos;
-                if ("Code".equals(a.name())) {
-                    Class.Method m = (Class.Method) h;
-                    m.code = new Code(m);
-                    try {
-                        readCode(m.code);
-                    } catch (Instruction.FormatException iie) {
-                        String message = iie.getMessage() + " in " + h;
-                        throw new ClassReader.ClassFormatException(message, iie);
-                    }
-                } else {
-                    assert(h == cls);
-                    readInnerClasses(cls);
+                Class.Method m = (Class.Method) h;
+                m.code = new Code(m);
+                try {
+                    readCode(m.code);
+                } catch (Instruction.FormatException iie) {
+                    String message = iie.getMessage() + " in " + h;
+                    throw new ClassReader.ClassFormatException(message, iie);
                 }
                 assert(length == inPos - pos0);
                 // Keep empty attribute a...
+            } else if (a.layout() == Package.attrBootstrapMethodsEmpty) {
+                assert(h == cls);
+                readBootstrapMethods(cls);
+                assert(length == inPos - pos0);
+                // Delete the attribute; it is logically part of the constant pool.
+                continue;
+            } else if (a.layout() == Package.attrInnerClassesEmpty) {
+                // These are hardwired also.
+                assert(h == cls);
+                readInnerClasses(cls);
+                assert(length == inPos - pos0);
+                // Keep empty attribute a...
             } else if (length > 0) {
                 byte[] bytes = new byte[length];
                 in.readFully(bytes);
@@ -467,6 +549,19 @@
         readAttributes(ATTR_CONTEXT_CODE, code);
     }
 
+    void readBootstrapMethods(Class cls) throws IOException {
+        BootstrapMethodEntry[] bsms = new BootstrapMethodEntry[readUnsignedShort()];
+        for (int i = 0; i < bsms.length; i++) {
+            MethodHandleEntry bsmRef = (MethodHandleEntry) readRef(CONSTANT_MethodHandle);
+            Entry[] argRefs = new Entry[readUnsignedShort()];
+            for (int j = 0; j < argRefs.length; j++) {
+                argRefs[j] = readRef();
+            }
+            bsms[i] = ConstantPool.getBootstrapMethodEntry(bsmRef, argRefs);
+        }
+        cls.setBootstrapMethods(Arrays.asList(bsms));
+    }
+
     void readInnerClasses(Class cls) throws IOException {
         int nc = readUnsignedShort();
         ArrayList<InnerClass> ics = new ArrayList<>(nc);
--- a/jdk/src/share/classes/com/sun/java/util/jar/pack/ClassWriter.java	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/src/share/classes/com/sun/java/util/jar/pack/ClassWriter.java	Wed Jul 05 18:10:27 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -29,6 +29,8 @@
 import com.sun.java.util.jar.pack.ConstantPool.Entry;
 import com.sun.java.util.jar.pack.ConstantPool.Index;
 import com.sun.java.util.jar.pack.ConstantPool.NumberEntry;
+import com.sun.java.util.jar.pack.ConstantPool.MethodHandleEntry;
+import com.sun.java.util.jar.pack.ConstantPool.BootstrapMethodEntry;
 import com.sun.java.util.jar.pack.Package.Class;
 import com.sun.java.util.jar.pack.Package.InnerClass;
 import java.io.BufferedOutputStream;
@@ -49,6 +51,7 @@
     Class cls;
     DataOutputStream out;
     Index cpIndex;
+    Index bsmIndex;
 
     ClassWriter(Class cls, OutputStream out) throws IOException {
         this.pkg = cls.getPackage();
@@ -57,6 +60,10 @@
         this.out = new DataOutputStream(new BufferedOutputStream(out));
         this.cpIndex = ConstantPool.makeIndex(cls.toString(), cls.getCPMap());
         this.cpIndex.flattenSigs = true;
+        if (cls.hasBootstrapMethods()) {
+            this.bsmIndex = ConstantPool.makeIndex(cpIndex.debugName+".BootstrapMethods",
+                                                   cls.getBootstrapMethodMap());
+        }
         if (verbose > 1)
             Utils.log.fine("local CP="+(verbose > 2 ? cpIndex.dumpString() : cpIndex.toString()));
     }
@@ -71,6 +78,11 @@
 
     /** Write a 2-byte int representing a CP entry, using the local cpIndex. */
     private void writeRef(Entry e) throws IOException {
+        writeRef(e, cpIndex);
+    }
+
+    /** Write a 2-byte int representing a CP entry, using the given cpIndex. */
+    private void writeRef(Entry e, Index cpIndex) throws IOException {
         int i = (e == null) ? 0 : cpIndex.indexOf(e);
         writeShort(i);
     }
@@ -117,8 +129,7 @@
             out.write(tag);
             switch (tag) {
                 case CONSTANT_Signature:
-                    assert(false);  // should not reach here
-                    break;
+                    throw new AssertionError("CP should have Signatures remapped to Utf8");
                 case CONSTANT_Utf8:
                     out.writeUTF(e.stringValue());
                     break;
@@ -138,8 +149,14 @@
                     break;
                 case CONSTANT_Class:
                 case CONSTANT_String:
+                case CONSTANT_MethodType:
                     writeRef(e.getRef(0));
                     break;
+                case CONSTANT_MethodHandle:
+                    MethodHandleEntry mhe = (MethodHandleEntry) e;
+                    out.writeByte(mhe.refKind);
+                    writeRef(mhe.getRef(0));
+                    break;
                 case CONSTANT_Fieldref:
                 case CONSTANT_Methodref:
                 case CONSTANT_InterfaceMethodref:
@@ -147,6 +164,12 @@
                     writeRef(e.getRef(0));
                     writeRef(e.getRef(1));
                     break;
+                case CONSTANT_InvokeDynamic:
+                    writeRef(e.getRef(0), bsmIndex);
+                    writeRef(e.getRef(1));
+                    break;
+                case CONSTANT_BootstrapMethod:
+                    throw new AssertionError("CP should have BootstrapMethods moved to side-table");
                 default:
                     throw new IOException("Bad constant pool tag "+tag);
             }
@@ -198,6 +221,7 @@
             a.finishRefs(cpIndex);
             writeRef(a.getNameRef());
             if (a.layout() == Package.attrCodeEmpty ||
+                a.layout() == Package.attrBootstrapMethodsEmpty ||
                 a.layout() == Package.attrInnerClassesEmpty) {
                 // These are hardwired.
                 DataOutputStream savedOut = out;
@@ -207,9 +231,14 @@
                 if ("Code".equals(a.name())) {
                     Class.Method m = (Class.Method) h;
                     writeCode(m.code);
-                } else {
+                } else if ("BootstrapMethods".equals(a.name())) {
+                    assert(h == cls);
+                    writeBootstrapMethods(cls);
+                } else if ("InnerClasses".equals(a.name())) {
                     assert(h == cls);
                     writeInnerClasses(cls);
+                } else {
+                    throw new AssertionError();
                 }
                 out = savedOut;
                 if (verbose > 2)
@@ -242,6 +271,18 @@
         writeAttributes(ATTR_CONTEXT_CODE, code);
     }
 
+    void writeBootstrapMethods(Class cls) throws IOException {
+        List<BootstrapMethodEntry> bsms = cls.getBootstrapMethods();
+        writeShort(bsms.size());
+        for (BootstrapMethodEntry e : bsms) {
+            writeRef(e.bsmRef);
+            writeShort(e.argRefs.length);
+            for (Entry argRef : e.argRefs) {
+                writeRef(argRef);
+            }
+        }
+    }
+
     void writeInnerClasses(Class cls) throws IOException {
         List<InnerClass> ics = cls.getInnerClasses();
         writeShort(ics.size());
--- a/jdk/src/share/classes/com/sun/java/util/jar/pack/ConstantPool.java	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/src/share/classes/com/sun/java/util/jar/pack/ConstantPool.java	Wed Jul 05 18:10:27 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -52,7 +52,7 @@
      *  Also used to back up more complex constant pool entries, like Class.
      */
     public static synchronized Utf8Entry getUtf8Entry(String value) {
-        Map<String, Utf8Entry> utf8Entries  = Utils.getUtf8Entries();
+        Map<String, Utf8Entry> utf8Entries  = Utils.getTLGlobals().getUtf8Entries();
         Utf8Entry e = utf8Entries.get(value);
         if (e == null) {
             e = new Utf8Entry(value);
@@ -61,8 +61,8 @@
         return e;
     }
     /** Factory for Class constants. */
-    public static synchronized ClassEntry getClassEntry(String name) {
-        Map<String, ClassEntry> classEntries = Utils.getClassEntries();
+    public static ClassEntry getClassEntry(String name) {
+        Map<String, ClassEntry> classEntries = Utils.getTLGlobals().getClassEntries();
         ClassEntry e = classEntries.get(name);
         if (e == null) {
             e = new ClassEntry(getUtf8Entry(name));
@@ -72,8 +72,8 @@
         return e;
     }
     /** Factory for literal constants (String, Integer, etc.). */
-    public static synchronized LiteralEntry getLiteralEntry(Comparable<?> value) {
-        Map<Object, LiteralEntry> literalEntries = Utils.getLiteralEntries();
+    public static LiteralEntry getLiteralEntry(Comparable<?> value) {
+        Map<Object, LiteralEntry> literalEntries = Utils.getTLGlobals().getLiteralEntries();
         LiteralEntry e = literalEntries.get(value);
         if (e == null) {
             if (value instanceof String)
@@ -85,13 +85,13 @@
         return e;
     }
     /** Factory for literal constants (String, Integer, etc.). */
-    public static synchronized StringEntry getStringEntry(String value) {
+    public static StringEntry getStringEntry(String value) {
         return (StringEntry) getLiteralEntry(value);
     }
 
     /** Factory for signature (type) constants. */
-    public static synchronized SignatureEntry getSignatureEntry(String type) {
-        Map<String, SignatureEntry> signatureEntries = Utils.getSignatureEntries();
+    public static SignatureEntry getSignatureEntry(String type) {
+        Map<String, SignatureEntry> signatureEntries = Utils.getTLGlobals().getSignatureEntries();
         SignatureEntry e = signatureEntries.get(type);
         if (e == null) {
             e = new SignatureEntry(type);
@@ -106,8 +106,8 @@
     }
 
     /** Factory for descriptor (name-and-type) constants. */
-    public static synchronized DescriptorEntry getDescriptorEntry(Utf8Entry nameRef, SignatureEntry typeRef) {
-        Map<String, DescriptorEntry> descriptorEntries = Utils.getDescriptorEntries();
+    public static DescriptorEntry getDescriptorEntry(Utf8Entry nameRef, SignatureEntry typeRef) {
+        Map<String, DescriptorEntry> descriptorEntries = Utils.getTLGlobals().getDescriptorEntries();
         String key = DescriptorEntry.stringValueOf(nameRef, typeRef);
         DescriptorEntry e = descriptorEntries.get(key);
         if (e == null) {
@@ -124,8 +124,8 @@
     }
 
     /** Factory for member reference constants. */
-    public static synchronized MemberEntry getMemberEntry(byte tag, ClassEntry classRef, DescriptorEntry descRef) {
-        Map<String, MemberEntry> memberEntries = Utils.getMemberEntries();
+    public static MemberEntry getMemberEntry(byte tag, ClassEntry classRef, DescriptorEntry descRef) {
+        Map<String, MemberEntry> memberEntries = Utils.getTLGlobals().getMemberEntries();
         String key = MemberEntry.stringValueOf(tag, classRef, descRef);
         MemberEntry e = memberEntries.get(key);
         if (e == null) {
@@ -137,6 +137,61 @@
         return e;
     }
 
+    /** Factory for MethodHandle constants. */
+    public static MethodHandleEntry getMethodHandleEntry(byte refKind, MemberEntry memRef) {
+        Map<String, MethodHandleEntry> methodHandleEntries = Utils.getTLGlobals().getMethodHandleEntries();
+        String key = MethodHandleEntry.stringValueOf(refKind, memRef);
+        MethodHandleEntry e = methodHandleEntries.get(key);
+        if (e == null) {
+            e = new MethodHandleEntry(refKind, memRef);
+            assert(e.stringValue().equals(key));
+            methodHandleEntries.put(key, e);
+        }
+        return e;
+    }
+
+    /** Factory for MethodType constants. */
+    public static MethodTypeEntry getMethodTypeEntry(SignatureEntry sigRef) {
+        Map<String, MethodTypeEntry> methodTypeEntries = Utils.getTLGlobals().getMethodTypeEntries();
+        String key = sigRef.stringValue();
+        MethodTypeEntry e = methodTypeEntries.get(key);
+        if (e == null) {
+            e = new MethodTypeEntry(sigRef);
+            assert(e.stringValue().equals(key));
+            methodTypeEntries.put(key, e);
+        }
+        return e;
+    }
+    public static MethodTypeEntry getMethodTypeEntry(Utf8Entry typeRef) {
+        return getMethodTypeEntry(getSignatureEntry(typeRef.stringValue()));
+    }
+
+    /** Factory for InvokeDynamic constants. */
+    public static InvokeDynamicEntry getInvokeDynamicEntry(BootstrapMethodEntry bssRef, DescriptorEntry descRef) {
+        Map<String, InvokeDynamicEntry> invokeDynamicEntries = Utils.getTLGlobals().getInvokeDynamicEntries();
+        String key = InvokeDynamicEntry.stringValueOf(bssRef, descRef);
+        InvokeDynamicEntry e = invokeDynamicEntries.get(key);
+        if (e == null) {
+            e = new InvokeDynamicEntry(bssRef, descRef);
+            assert(e.stringValue().equals(key));
+            invokeDynamicEntries.put(key, e);
+        }
+        return e;
+    }
+
+    /** Factory for BootstrapMethod pseudo-constants. */
+    public static BootstrapMethodEntry getBootstrapMethodEntry(MethodHandleEntry bsmRef, Entry[] argRefs) {
+        Map<String, BootstrapMethodEntry> bootstrapMethodEntries = Utils.getTLGlobals().getBootstrapMethodEntries();
+        String key = BootstrapMethodEntry.stringValueOf(bsmRef, argRefs);
+        BootstrapMethodEntry e = bootstrapMethodEntries.get(key);
+        if (e == null) {
+            e = new BootstrapMethodEntry(bsmRef, argRefs);
+            assert(e.stringValue().equals(key));
+            bootstrapMethodEntries.put(key, e);
+        }
+        return e;
+    }
+
 
     /** Entries in the constant pool. */
     public static abstract
@@ -251,6 +306,10 @@
         throw new RuntimeException("bad literal value "+value);
     }
 
+    static boolean isRefKind(byte refKind) {
+        return (REF_getField <= refKind && refKind <= REF_invokeInterface);
+    }
+
     public static abstract
     class LiteralEntry extends Entry {
         protected LiteralEntry(byte tag) {
@@ -404,7 +463,7 @@
         }
         static
         String stringValueOf(Entry nameRef, Entry typeRef) {
-            return typeRef.stringValue()+","+nameRef.stringValue();
+            return qualifiedStringValue(typeRef, nameRef);
         }
 
         public String prettyString() {
@@ -420,6 +479,15 @@
         }
     }
 
+    static String qualifiedStringValue(Entry e1, Entry e2) {
+        return qualifiedStringValue(e1.stringValue(), e2.stringValue());
+    }
+    static String qualifiedStringValue(String s1, String s234) {
+        // Qualification by dot must decompose uniquely.  Second string might already be qualified.
+        assert(s1.indexOf(".") < 0);
+        return s1+"."+s234;
+    }
+
     public static
     class MemberEntry extends Entry {
         final ClassEntry classRef;
@@ -453,8 +521,12 @@
             int x = superCompareTo(o);
             if (x == 0) {
                 MemberEntry that = (MemberEntry)o;
+                if (Utils.SORT_MEMBERS_DESCR_MAJOR)
+                    // descRef is transmitted as UDELTA5; sort it first?
+                    x = this.descRef.compareTo(that.descRef);
                 // Primary key is classRef.
-                x = this.classRef.compareTo(that.classRef);
+                if (x == 0)
+                    x = this.classRef.compareTo(that.classRef);
                 if (x == 0)
                     x = this.descRef.compareTo(that.descRef);
             }
@@ -473,7 +545,7 @@
             case CONSTANT_InterfaceMethodref:  pfx = "IMethod:"; break;
             default:                           pfx = tag+"???";  break;
             }
-            return pfx+classRef.stringValue()+","+descRef.stringValue();
+            return pfx+qualifiedStringValue(classRef, descRef);
         }
 
         public boolean isMethod() {
@@ -581,13 +653,26 @@
         }
         public byte getLiteralTag() {
             switch (formRef.stringValue().charAt(0)) {
-            case 'L': return CONSTANT_String;
             case 'I': return CONSTANT_Integer;
             case 'J': return CONSTANT_Long;
             case 'F': return CONSTANT_Float;
             case 'D': return CONSTANT_Double;
             case 'B': case 'S': case 'C': case 'Z':
                 return CONSTANT_Integer;
+            case 'L':
+                /*
+                switch (classRefs[0].stringValue()) {
+                case "java/lang/String":
+                    return CONSTANT_String;
+                case "java/lang/invoke/MethodHandle":
+                    return CONSTANT_MethodHandle;
+                case "java/lang/invoke/MethodType":
+                    return CONSTANT_MethodType;
+                default:  // java/lang/Object, etc.
+                    return CONSTANT_LoadableValue;
+                }
+                */
+                return CONSTANT_String;  // JDK 7 ConstantValue limited to String
             }
             assert(false);
             return CONSTANT_None;
@@ -724,6 +809,218 @@
         return parts;
     }
 
+    /** @since JDK 7, JSR 292 */
+    public static
+    class MethodHandleEntry extends Entry {
+        final int refKind;
+        final MemberEntry memRef;
+        public Entry getRef(int i) { return i == 0 ? memRef : null; }
+
+        protected int computeValueHash() {
+            int hc2 = refKind;
+            return (memRef.hashCode() + (hc2 << 8)) ^ hc2;
+        }
+
+        MethodHandleEntry(byte refKind, MemberEntry memRef) {
+            super(CONSTANT_MethodHandle);
+            assert(isRefKind(refKind));
+            this.refKind = refKind;
+            this.memRef  = memRef;
+            hashCode();  // force computation of valueHash
+        }
+        public boolean equals(Object o) {
+            if (o == null || o.getClass() != MethodHandleEntry.class) {
+                return false;
+            }
+            MethodHandleEntry that = (MethodHandleEntry)o;
+            return this.refKind == that.refKind
+                && this.memRef.eq(that.memRef);
+        }
+        public int compareTo(Object o) {
+            int x = superCompareTo(o);
+            if (x == 0) {
+                MethodHandleEntry that = (MethodHandleEntry)o;
+                if (Utils.SORT_HANDLES_KIND_MAJOR)
+                    // Primary key could be refKind.
+                    x = this.refKind - that.refKind;
+                // Primary key is memRef, which is transmitted as UDELTA5.
+                if (x == 0)
+                    x = this.memRef.compareTo(that.memRef);
+                if (x == 0)
+                    x = this.refKind - that.refKind;
+            }
+            return x;
+        }
+        public static String stringValueOf(int refKind, MemberEntry memRef) {
+            return refKindName(refKind)+":"+memRef.stringValue();
+        }
+        public String stringValue() {
+            return stringValueOf(refKind, memRef);
+        }
+    }
+
+    /** @since JDK 7, JSR 292 */
+    public static
+    class MethodTypeEntry extends Entry {
+        final SignatureEntry typeRef;
+        public Entry getRef(int i) { return i == 0 ? typeRef : null; }
+
+        protected int computeValueHash() {
+            return typeRef.hashCode() + tag;
+        }
+
+        MethodTypeEntry(SignatureEntry typeRef) {
+            super(CONSTANT_MethodType);
+            this.typeRef  = typeRef;
+            hashCode();  // force computation of valueHash
+        }
+        public boolean equals(Object o) {
+            if (o == null || o.getClass() != MethodTypeEntry.class) {
+                return false;
+            }
+            MethodTypeEntry that = (MethodTypeEntry)o;
+            return this.typeRef.eq(that.typeRef);
+        }
+        public int compareTo(Object o) {
+            int x = superCompareTo(o);
+            if (x == 0) {
+                MethodTypeEntry that = (MethodTypeEntry)o;
+                x = this.typeRef.compareTo(that.typeRef);
+            }
+            return x;
+        }
+        public String stringValue() {
+            return typeRef.stringValue();
+        }
+    }
+
+    /** @since JDK 7, JSR 292 */
+    public static
+    class InvokeDynamicEntry extends Entry {
+        final BootstrapMethodEntry bssRef;
+        final DescriptorEntry descRef;
+        public Entry getRef(int i) {
+            if (i == 0)  return bssRef;
+            if (i == 1)  return descRef;
+            return null;
+        }
+        protected int computeValueHash() {
+            int hc2 = descRef.hashCode();
+            return (bssRef.hashCode() + (hc2 << 8)) ^ hc2;
+        }
+
+        InvokeDynamicEntry(BootstrapMethodEntry bssRef, DescriptorEntry descRef) {
+            super(CONSTANT_InvokeDynamic);
+            this.bssRef  = bssRef;
+            this.descRef = descRef;
+            hashCode();  // force computation of valueHash
+        }
+        public boolean equals(Object o) {
+            if (o == null || o.getClass() != InvokeDynamicEntry.class) {
+                return false;
+            }
+            InvokeDynamicEntry that = (InvokeDynamicEntry)o;
+            return this.bssRef.eq(that.bssRef)
+                && this.descRef.eq(that.descRef);
+        }
+        public int compareTo(Object o) {
+            int x = superCompareTo(o);
+            if (x == 0) {
+                InvokeDynamicEntry that = (InvokeDynamicEntry)o;
+                if (Utils.SORT_INDY_BSS_MAJOR)
+                    // Primary key could be bsmRef.
+                    x = this.bssRef.compareTo(that.bssRef);
+                // Primary key is descriptor, which is transmitted as UDELTA5.
+                if (x == 0)
+                    x = this.descRef.compareTo(that.descRef);
+                if (x == 0)
+                    x = this.bssRef.compareTo(that.bssRef);
+            }
+            return x;
+        }
+        public String stringValue() {
+            return stringValueOf(bssRef, descRef);
+        }
+        static
+        String stringValueOf(BootstrapMethodEntry bssRef, DescriptorEntry descRef) {
+            return "Indy:"+bssRef.stringValue()+"."+descRef.stringValue();
+        }
+    }
+
+    /** @since JDK 7, JSR 292 */
+    public static
+    class BootstrapMethodEntry extends Entry {
+        final MethodHandleEntry bsmRef;
+        final Entry[] argRefs;
+        public Entry getRef(int i) {
+            if (i == 0)  return bsmRef;
+            if (i-1 < argRefs.length)  return argRefs[i-1];
+            return null;
+        }
+        protected int computeValueHash() {
+            int hc2 = bsmRef.hashCode();
+            return (Arrays.hashCode(argRefs) + (hc2 << 8)) ^ hc2;
+        }
+
+        BootstrapMethodEntry(MethodHandleEntry bsmRef, Entry[] argRefs) {
+            super(CONSTANT_BootstrapMethod);
+            this.bsmRef  = bsmRef;
+            this.argRefs = argRefs.clone();
+            hashCode();  // force computation of valueHash
+        }
+        public boolean equals(Object o) {
+            if (o == null || o.getClass() != BootstrapMethodEntry.class) {
+                return false;
+            }
+            BootstrapMethodEntry that = (BootstrapMethodEntry)o;
+            return this.bsmRef.eq(that.bsmRef)
+                && Arrays.equals(this.argRefs, that.argRefs);
+        }
+        public int compareTo(Object o) {
+            int x = superCompareTo(o);
+            if (x == 0) {
+                BootstrapMethodEntry that = (BootstrapMethodEntry)o;
+                if (Utils.SORT_BSS_BSM_MAJOR)
+                    // Primary key is bsmRef.
+                    x = this.bsmRef.compareTo(that.bsmRef);
+                // Primary key is args array length, which is transmitted as UDELTA5.
+                if (x == 0)
+                    x = compareArgArrays(this.argRefs, that.argRefs);
+                if (x == 0)
+                    x = this.bsmRef.compareTo(that.bsmRef);
+            }
+            return x;
+        }
+        public String stringValue() {
+            return stringValueOf(bsmRef, argRefs);
+        }
+        static
+        String stringValueOf(MethodHandleEntry bsmRef, Entry[] argRefs) {
+            StringBuffer sb = new StringBuffer(bsmRef.stringValue());
+            // Arguments are formatted as "<foo;bar;baz>" instead of "[foo,bar,baz]".
+            // This ensures there will be no confusion if "[,]" appear inside of names.
+            char nextSep = '<';
+            boolean didOne = false;
+            for (Entry argRef : argRefs) {
+                sb.append(nextSep).append(argRef.stringValue());
+                nextSep = ';';
+            }
+            if (nextSep == '<')  sb.append(nextSep);
+            sb.append('>');
+            return sb.toString();
+        }
+        static
+        int compareArgArrays(Entry[] a1, Entry[] a2) {
+            int x = a1.length - a2.length;
+            if (x != 0)  return x;
+            for (int i = 0; i < a1.length; i++) {
+                x = a1[i].compareTo(a2[i]);
+                if (x != 0)  break;
+            }
+            return x;
+        }
+    }
+
     // Handy constants:
     protected static final Entry[] noRefs = {};
     protected static final ClassEntry[] noClassRefs = {};
@@ -964,35 +1261,51 @@
     /** Coherent group of constant pool indexes. */
     public static
     class IndexGroup {
-        private Index indexUntyped;
         private Index[] indexByTag = new Index[CONSTANT_Limit];
+        private Index[] indexByTagGroup;
         private int[]   untypedFirstIndexByTag;
-        private int     totalSize;
+        private int     totalSizeQQ;
         private Index[][] indexByTagAndClass;
 
         /** Index of all CP entries of all types, in definition order. */
-        public Index getUntypedIndex() {
-            if (indexUntyped == null) {
+        private Index makeTagGroupIndex(byte tagGroupTag, byte[] tagsInGroup) {
+            if (indexByTagGroup == null)
+                indexByTagGroup = new Index[CONSTANT_GroupLimit - CONSTANT_GroupFirst];
+            int which = tagGroupTag - CONSTANT_GroupFirst;
+            assert(indexByTagGroup[which] == null);
+            int fillp = 0;
+            Entry[] cpMap = null;
+            for (int pass = 1; pass <= 2; pass++) {
                 untypedIndexOf(null);  // warm up untypedFirstIndexByTag
-                Entry[] cpMap = new Entry[totalSize];
-                for (int tag = 0; tag < indexByTag.length; tag++) {
+                for (byte tag : tagsInGroup) {
                     Index ix = indexByTag[tag];
                     if (ix == null)  continue;
                     int ixLen = ix.cpMap.length;
                     if (ixLen == 0)  continue;
-                    int fillp = untypedFirstIndexByTag[tag];
-                    assert(cpMap[fillp] == null);
-                    assert(cpMap[fillp+ixLen-1] == null);
-                    System.arraycopy(ix.cpMap, 0, cpMap, fillp, ixLen);
+                    assert(tagGroupTag == CONSTANT_All
+                            ? fillp == untypedFirstIndexByTag[tag]
+                            : fillp  < untypedFirstIndexByTag[tag]);
+                    if (cpMap != null) {
+                        assert(cpMap[fillp] == null);
+                        assert(cpMap[fillp+ixLen-1] == null);
+                        System.arraycopy(ix.cpMap, 0, cpMap, fillp, ixLen);
+                    }
+                    fillp += ixLen;
                 }
-                indexUntyped = new Index("untyped", cpMap);
+                if (cpMap == null) {
+                    assert(pass == 1);
+                    // get ready for pass 2
+                    cpMap = new Entry[fillp];
+                    fillp = 0;
+                }
             }
-            return indexUntyped;
+            indexByTagGroup[which] = new Index(tagName(tagGroupTag), cpMap);
+            return indexByTagGroup[which];
         }
 
         public int untypedIndexOf(Entry e) {
             if (untypedFirstIndexByTag == null) {
-                untypedFirstIndexByTag = new int[CONSTANT_Limit];
+                untypedFirstIndexByTag = new int[CONSTANT_Limit+1];
                 int fillp = 0;
                 for (int i = 0; i < TAGS_IN_ORDER.length; i++) {
                     byte tag = TAGS_IN_ORDER[i];
@@ -1002,7 +1315,7 @@
                     untypedFirstIndexByTag[tag] = fillp;
                     fillp += ixLen;
                 }
-                totalSize = fillp;
+                untypedFirstIndexByTag[CONSTANT_Limit] = fillp;
             }
             if (e == null)  return -1;
             int tag = e.tag;
@@ -1028,16 +1341,15 @@
             indexByTag[tag] = ix;
             // decache indexes derived from this one:
             untypedFirstIndexByTag = null;
-            indexUntyped = null;
+            indexByTagGroup = null;
             if (indexByTagAndClass != null)
                 indexByTagAndClass[tag] = null;
         }
 
         /** Index of all CP entries of a given tag. */
         public Index getIndexByTag(byte tag) {
-            if (tag == CONSTANT_All) {
-                return getUntypedIndex();
-            }
+            if (tag >= CONSTANT_GroupFirst)
+                return getIndexByTagGroup(tag);
             Index ix = indexByTag[tag];
             if (ix == null) {
                 // Make an empty one by default.
@@ -1047,6 +1359,26 @@
             return ix;
         }
 
+        private Index getIndexByTagGroup(byte tag) {
+            // pool groups:
+            if (indexByTagGroup != null) {
+                Index ix = indexByTagGroup[tag - CONSTANT_GroupFirst];
+                if (ix != null)  return ix;
+            }
+            switch (tag) {
+            case CONSTANT_All:
+                return makeTagGroupIndex(CONSTANT_All, TAGS_IN_ORDER);
+            case CONSTANT_LoadableValue:
+                    return makeTagGroupIndex(CONSTANT_LoadableValue, LOADABLE_VALUE_TAGS);
+            case CONSTANT_AnyMember:
+                return makeTagGroupIndex(CONSTANT_AnyMember, ANY_MEMBER_TAGS);
+            case CONSTANT_FieldSpecific:
+                // This one does not have any fixed index, since it is context-specific.
+                return null;
+            }
+            throw new AssertionError("bad tag group "+tag);
+        }
+
         /** Index of all CP entries of a given tag and class. */
         public Index getMemberIndex(byte tag, ClassEntry classRef) {
             if (indexByTagAndClass == null)
@@ -1107,16 +1439,14 @@
         }
 
         public boolean haveNumbers() {
-            for (byte tag = CONSTANT_Integer; tag <= CONSTANT_Double; tag++) {
-                switch (tag) {
-                case CONSTANT_Integer:
-                case CONSTANT_Float:
-                case CONSTANT_Long:
-                case CONSTANT_Double:
-                    break;
-                default:
-                    assert(false);
-                }
+            for (byte tag : NUMBER_TAGS) {
+                if (getIndexByTag(tag).size() > 0)  return true;
+            }
+            return false;
+        }
+
+        public boolean haveExtraTags() {
+            for (byte tag : EXTRA_TAGS) {
                 if (getIndexByTag(tag).size() > 0)  return true;
             }
             return false;
@@ -1129,8 +1459,13 @@
      *  by their equivalent Utf8s.
      *  Also, discard null from cpRefs.
      */
+    public static void completeReferencesIn(Set<Entry> cpRefs, boolean flattenSigs) {
+         completeReferencesIn(cpRefs, flattenSigs, null);
+    }
+
     public static
-    void completeReferencesIn(Set<Entry> cpRefs, boolean flattenSigs) {
+    void completeReferencesIn(Set<Entry> cpRefs, boolean flattenSigs,
+                              List<BootstrapMethodEntry>bsms) {
         cpRefs.remove(null);
         for (ListIterator<Entry> work =
                  new ArrayList<>(cpRefs).listIterator(cpRefs.size());
@@ -1146,6 +1481,14 @@
                 cpRefs.add(ue);
                 e = ue;   // do not descend into the sig
             }
+            if (bsms != null && e.tag == CONSTANT_BootstrapMethod) {
+                BootstrapMethodEntry bsm = (BootstrapMethodEntry)e;
+                cpRefs.remove(bsm);
+                // move it away to the side table where it belongs
+                if (!bsms.contains(bsm))
+                    bsms.add(bsm);
+                // fall through to recursively add refs for this entry
+            }
             // Recursively add the refs of e to cpRefs:
             for (int i = 0; ; i++) {
                 Entry re = e.getRef(i);
@@ -1174,15 +1517,37 @@
             case CONSTANT_Methodref:            return "Methodref";
             case CONSTANT_InterfaceMethodref:   return "InterfaceMethodref";
             case CONSTANT_NameandType:          return "NameandType";
+            case CONSTANT_MethodHandle:         return "MethodHandle";
+            case CONSTANT_MethodType:           return "MethodType";
+            case CONSTANT_InvokeDynamic:        return "InvokeDynamic";
 
                 // pseudo-tags:
-            case CONSTANT_All:                  return "*All";
-            case CONSTANT_None:                 return "*None";
+            case CONSTANT_All:                  return "**All";
+            case CONSTANT_None:                 return "**None";
+            case CONSTANT_LoadableValue:        return "**LoadableValue";
+            case CONSTANT_AnyMember:            return "**AnyMember";
+            case CONSTANT_FieldSpecific:        return "*FieldSpecific";
             case CONSTANT_Signature:            return "*Signature";
+            case CONSTANT_BootstrapMethod:      return "*BootstrapMethod";
         }
         return "tag#"+tag;
     }
 
+    public static String refKindName(int refKind) {
+        switch (refKind) {
+            case REF_getField:                  return "getField";
+            case REF_getStatic:                 return "getStatic";
+            case REF_putField:                  return "putField";
+            case REF_putStatic:                 return "putStatic";
+            case REF_invokeVirtual:             return "invokeVirtual";
+            case REF_invokeStatic:              return "invokeStatic";
+            case REF_invokeSpecial:             return "invokeSpecial";
+            case REF_newInvokeSpecial:          return "newInvokeSpecial";
+            case REF_invokeInterface:           return "invokeInterface";
+        }
+        return "refKind#"+refKind;
+    }
+
     // archive constant pool definition order
     static final byte TAGS_IN_ORDER[] = {
         CONSTANT_Utf8,
@@ -1190,13 +1555,19 @@
         CONSTANT_Float,
         CONSTANT_Long,
         CONSTANT_Double,
-        CONSTANT_String,
+        CONSTANT_String,            // note that String=8 precedes Class=7
         CONSTANT_Class,
         CONSTANT_Signature,
         CONSTANT_NameandType,       // cp_Descr
         CONSTANT_Fieldref,          // cp_Field
         CONSTANT_Methodref,         // cp_Method
-        CONSTANT_InterfaceMethodref // cp_Imethod
+        CONSTANT_InterfaceMethodref, // cp_Imethod
+
+        // Constants defined in JDK 7 and later:
+        CONSTANT_MethodHandle,
+        CONSTANT_MethodType,
+        CONSTANT_BootstrapMethod,  // pseudo-tag, really stored in a class attribute
+        CONSTANT_InvokeDynamic
     };
     static final byte TAG_ORDER[];
     static {
@@ -1211,4 +1582,45 @@
         System.out.println("};");
         */
     }
+    static final byte[] NUMBER_TAGS = {
+        CONSTANT_Integer, CONSTANT_Float, CONSTANT_Long, CONSTANT_Double
+    };
+    static final byte[] EXTRA_TAGS = {
+        CONSTANT_MethodHandle, CONSTANT_MethodType,
+        CONSTANT_BootstrapMethod, // pseudo-tag
+        CONSTANT_InvokeDynamic
+    };
+    static final byte[] LOADABLE_VALUE_TAGS = { // for CONSTANT_LoadableValue
+        CONSTANT_Integer, CONSTANT_Float, CONSTANT_Long, CONSTANT_Double,
+        CONSTANT_String, CONSTANT_Class,
+        CONSTANT_MethodHandle, CONSTANT_MethodType
+    };
+    static final byte[] ANY_MEMBER_TAGS = { // for CONSTANT_AnyMember
+        CONSTANT_Fieldref, CONSTANT_Methodref, CONSTANT_InterfaceMethodref
+    };
+    static final byte[] FIELD_SPECIFIC_TAGS = { // for CONSTANT_FieldSpecific
+        CONSTANT_Integer, CONSTANT_Float, CONSTANT_Long, CONSTANT_Double,
+        CONSTANT_String
+    };
+    static {
+        assert(
+            verifyTagOrder(TAGS_IN_ORDER) &&
+            verifyTagOrder(NUMBER_TAGS) &&
+            verifyTagOrder(EXTRA_TAGS) &&
+            verifyTagOrder(LOADABLE_VALUE_TAGS) &&
+            verifyTagOrder(ANY_MEMBER_TAGS) &&
+            verifyTagOrder(FIELD_SPECIFIC_TAGS)
+        );
+    }
+    private static boolean verifyTagOrder(byte[] tags) {
+        int prev = -1;
+        for (byte tag : tags) {
+            int next = TAG_ORDER[tag];
+            assert(next > 0) : "tag not found: "+tag;
+            assert(TAGS_IN_ORDER[next-1] == tag) : "tag repeated: "+tag+" => "+next+" => "+TAGS_IN_ORDER[next-1];
+            assert(prev < next) : "tags not in order: "+Arrays.toString(tags)+" at "+tag;
+            prev = next;
+        }
+        return true;
+    }
 }
--- a/jdk/src/share/classes/com/sun/java/util/jar/pack/Constants.java	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/src/share/classes/com/sun/java/util/jar/pack/Constants.java	Wed Jul 05 18:10:27 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -65,6 +65,9 @@
     public final static int JAVA6_PACKAGE_MAJOR_VERSION = 160;
     public final static int JAVA6_PACKAGE_MINOR_VERSION = 1;
 
+    public final static int JAVA7_PACKAGE_MAJOR_VERSION = 170;
+    public final static int JAVA7_PACKAGE_MINOR_VERSION = 1;
+
     public final static int CONSTANT_POOL_INDEX_LIMIT  = 0x10000;
     public final static int CONSTANT_POOL_NARROW_LIMIT = 0x00100;
 
@@ -82,14 +85,36 @@
     public final static byte CONSTANT_Methodref = 10;
     public final static byte CONSTANT_InterfaceMethodref = 11;
     public final static byte CONSTANT_NameandType = 12;
+    public final static byte CONSTANT_unused13 = 13;
+    public final static byte CONSTANT_unused14 = 14;
+    public final static byte CONSTANT_MethodHandle = 15;
+    public final static byte CONSTANT_MethodType = 16;
+    public final static byte CONSTANT_unused17 = 17;  // unused
+    public final static byte CONSTANT_InvokeDynamic = 18;
 
     // pseudo-constants:
     public final static byte CONSTANT_None = 0;
-    public final static byte CONSTANT_Signature = 13;
-    public final static byte CONSTANT_Limit  = 14;
+    public final static byte CONSTANT_Signature = CONSTANT_unused13;
+    public final static byte CONSTANT_BootstrapMethod = CONSTANT_unused17; // used only in InvokeDynamic constants
+    public final static byte CONSTANT_Limit = 19;
+
+    public final static byte CONSTANT_All = 50;  // combined global map
+    public final static byte CONSTANT_LoadableValue = 51; // used for 'KL' and qldc operands
+    public final static byte CONSTANT_AnyMember = 52; // union of refs to field or (interface) method
+    public final static byte CONSTANT_FieldSpecific = 53; // used only for 'KQ' ConstantValue attrs
+    public final static byte CONSTANT_GroupFirst = CONSTANT_All;
+    public final static byte CONSTANT_GroupLimit = CONSTANT_FieldSpecific+1;
 
-    public final static byte CONSTANT_All = 19;  // combined global map
-    public final static byte CONSTANT_Literal = 20; // used only for ldc fields
+    // CONSTANT_MethodHandle reference kinds
+    public final static byte REF_getField = 1;
+    public final static byte REF_getStatic = 2;
+    public final static byte REF_putField = 3;
+    public final static byte REF_putStatic = 4;
+    public final static byte REF_invokeVirtual = 5;
+    public final static byte REF_invokeStatic = 6;
+    public final static byte REF_invokeSpecial = 7;
+    public final static byte REF_newInvokeSpecial = 8;
+    public final static byte REF_invokeInterface = 9;
 
     // pseudo-access bits
     public final static int ACC_IC_LONG_FORM   = (1<<16); //for ic_flags
@@ -133,7 +158,7 @@
     public static final int AO_HAVE_SPECIAL_FORMATS   = 1<<0;
     public static final int AO_HAVE_CP_NUMBERS        = 1<<1;
     public static final int AO_HAVE_ALL_CODE_FLAGS    = 1<<2;
-    public static final int AO_3_UNUSED_MBZ           = 1<<3;
+    public static final int AO_HAVE_CP_EXTRAS         = 1<<3;
     public static final int AO_HAVE_FILE_HEADERS      = 1<<4;
     public static final int AO_DEFLATE_HINT           = 1<<5;
     public static final int AO_HAVE_FILE_MODTIME      = 1<<6;
@@ -143,6 +168,7 @@
     public static final int AO_HAVE_FIELD_FLAGS_HI    = 1<<10;
     public static final int AO_HAVE_METHOD_FLAGS_HI   = 1<<11;
     public static final int AO_HAVE_CODE_FLAGS_HI     = 1<<12;
+    public static final int AO_UNUSED_MBZ          = (-1)<<13;  // option bits reserved for future use
 
     public static final int LG_AO_HAVE_XXX_FLAGS_HI   = 9;
 
@@ -357,7 +383,7 @@
         _invokespecial        = 183, // 0xb7
         _invokestatic         = 184, // 0xb8
         _invokeinterface      = 185, // 0xb9
-        _xxxunusedxxx         = 186, // 0xba
+        _invokedynamic        = 186, // 0xba
         _new                  = 187, // 0xbb
         _newarray             = 188, // 0xbc
         _anewarray            = 189, // 0xbd
@@ -422,15 +448,18 @@
     // Ldc variants gain us only 0.007% improvement in compression ratio,
     // but they simplify the file format greatly.
     public final static int _xldc_op = _invokeinit_limit;
-    public final static int _aldc = _ldc;
+    public final static int _sldc = _ldc;  // previously named _aldc
     public final static int _cldc = _xldc_op+0;
     public final static int _ildc = _xldc_op+1;
     public final static int _fldc = _xldc_op+2;
-    public final static int _aldc_w = _ldc_w;
+    public final static int _sldc_w = _ldc_w;  // previously named _aldc_w
     public final static int _cldc_w = _xldc_op+3;
     public final static int _ildc_w = _xldc_op+4;
     public final static int _fldc_w = _xldc_op+5;
     public final static int _lldc2_w = _ldc2_w;
     public final static int _dldc2_w = _xldc_op+6;
-    public final static int _xldc_limit = _xldc_op+7;
+    // anything other than primitive, string, or class must be handled with qldc:
+    public final static int _qldc   = _xldc_op+7;
+    public final static int _qldc_w = _xldc_op+8;
+    public final static int _xldc_limit = _xldc_op+9;
 }
--- a/jdk/src/share/classes/com/sun/java/util/jar/pack/Instruction.java	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/src/share/classes/com/sun/java/util/jar/pack/Instruction.java	Wed Jul 05 18:10:27 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -451,7 +451,7 @@
 
     public static byte getCPRefOpTag(int bc) {
         if (bc < BC_INDEX[0].length && BC_INDEX[0][bc] > 0)  return BC_TAG[0][bc];
-        if (bc >= _xldc_op && bc < _xldc_limit)  return CONSTANT_Literal;
+        if (bc >= _xldc_op && bc < _xldc_limit)  return CONSTANT_LoadableValue;
         return CONSTANT_None;
     }
 
@@ -500,7 +500,7 @@
         def("bkf", _getstatic, _putfield);              // pack kf (base=Field)
         def("bkm", _invokevirtual, _invokestatic);      // pack kn (base=Method)
         def("bkixx", _invokeinterface);         // pack ki (base=IMethod), omit xx
-        def("", _xxxunusedxxx);
+        def("bkyxx", _invokedynamic);           // pack ky (base=Any), omit xx
         def("bkc", _new);                               // pack kc
         def("bx", _newarray);
         def("bkc", _anewarray);                 // pack kc
@@ -515,7 +515,6 @@
             //System.out.println(i+": l="+BC_LENGTH[0][i]+" i="+BC_INDEX[0][i]);
             //assert(BC_LENGTH[0][i] != -1);
             if (BC_LENGTH[0][i] == -1) {
-                assert(i == _xxxunusedxxx);
                 continue;  // unknown opcode
             }
 
@@ -543,7 +542,7 @@
   "if_icmpne if_icmplt if_icmpge if_icmpgt if_icmple if_acmpeq if_acmpne "+
   "goto jsr ret tableswitch lookupswitch ireturn lreturn freturn dreturn "+
   "areturn return getstatic putstatic getfield putfield invokevirtual "+
-  "invokespecial invokestatic invokeinterface xxxunusedxxx new newarray "+
+  "invokespecial invokestatic invokeinterface invokedynamic new newarray "+
   "anewarray arraylength athrow checkcast instanceof monitorenter "+
   "monitorexit wide multianewarray ifnull ifnonnull goto_w jsr_w ";
         for (int bc = 0; names.length() > 0; bc++) {
@@ -588,6 +587,8 @@
             case _dldc2_w:  iname = "*dldc2_w"; break;
             case _cldc:  iname = "*cldc"; break;
             case _cldc_w:  iname = "*cldc_w"; break;
+            case _qldc:  iname = "*qldc"; break;
+            case _qldc_w:  iname = "*qldc_w"; break;
             case _byte_escape:  iname = "*byte_escape"; break;
             case _ref_escape:  iname = "*ref_escape"; break;
             case _end_marker:  iname = "*end"; break;
@@ -618,15 +619,16 @@
             if (index > 0 && index+1 < length) {
                 switch (fmt.charAt(index+1)) {
                     case 'c': tag = CONSTANT_Class; break;
-                    case 'k': tag = CONSTANT_Literal; break;
+                    case 'k': tag = CONSTANT_LoadableValue; break;
                     case 'f': tag = CONSTANT_Fieldref; break;
                     case 'm': tag = CONSTANT_Methodref; break;
                     case 'i': tag = CONSTANT_InterfaceMethodref; break;
+                    case 'y': tag = CONSTANT_InvokeDynamic; break;
                 }
                 assert(tag != CONSTANT_None);
             } else if (index > 0 && length == 2) {
                 assert(from_bc == _ldc);
-                tag = CONSTANT_Literal;  // _ldc opcode only
+                tag = CONSTANT_LoadableValue;  // _ldc opcode only
             }
             for (int bc = from_bc; bc <= to_bc; bc++) {
                 BC_FORMAT[w][bc] = fmt;
@@ -649,7 +651,7 @@
         Instruction i = at(code, 0);
         while (i != null) {
             int opcode = i.getBC();
-            if (opcode == _xxxunusedxxx || opcode < _nop || opcode > _jsr_w) {
+            if (opcode < _nop || opcode > _jsr_w) {
                 String message = "illegal opcode: " + opcode + " " + i;
                 throw new FormatException(message);
             }
--- a/jdk/src/share/classes/com/sun/java/util/jar/pack/NativeUnpack.java	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/src/share/classes/com/sun/java/util/jar/pack/NativeUnpack.java	Wed Jul 05 18:10:27 2017 +0200
@@ -87,7 +87,12 @@
         // If loading from stand alone build uncomment this.
         // System.loadLibrary("unpack");
         java.security.AccessController.doPrivileged(
-                new sun.security.action.LoadLibraryAction("unpack"));
+            new java.security.PrivilegedAction<Void>() {
+                public Void run() {
+                    System.loadLibrary("unpack");
+                    return null;
+                }
+            });
         initIDs();
     }
 
--- a/jdk/src/share/classes/com/sun/java/util/jar/pack/Package.java	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/src/share/classes/com/sun/java/util/jar/pack/Package.java	Wed Jul 05 18:10:27 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -28,6 +28,7 @@
 import com.sun.java.util.jar.pack.Attribute.Layout;
 import com.sun.java.util.jar.pack.ConstantPool.ClassEntry;
 import com.sun.java.util.jar.pack.ConstantPool.DescriptorEntry;
+import com.sun.java.util.jar.pack.ConstantPool.BootstrapMethodEntry;
 import com.sun.java.util.jar.pack.ConstantPool.Index;
 import com.sun.java.util.jar.pack.ConstantPool.LiteralEntry;
 import com.sun.java.util.jar.pack.ConstantPool.Utf8Entry;
@@ -100,6 +101,8 @@
         classes.clear();
         files.clear();
         BandStructure.nextSeqForDebug = 0;
+        package_minver = -1;  // fill in later
+        package_majver = 0;   // fill in later
     }
 
     int getPackageVersion() {
@@ -108,6 +111,7 @@
 
     // Special empty versions of Code and InnerClasses, used for markers.
     public static final Attribute.Layout attrCodeEmpty;
+    public static final Attribute.Layout attrBootstrapMethodsEmpty;
     public static final Attribute.Layout attrInnerClassesEmpty;
     public static final Attribute.Layout attrSourceFileSpecial;
     public static final Map<Attribute.Layout, Attribute> attrDefs;
@@ -115,6 +119,8 @@
         Map<Layout, Attribute> ad = new HashMap<>(3);
         attrCodeEmpty = Attribute.define(ad, ATTR_CONTEXT_METHOD,
                                          "Code", "").layout();
+        attrBootstrapMethodsEmpty = Attribute.define(ad, ATTR_CONTEXT_CLASS,
+                                                     "BootstrapMethods", "").layout();
         attrInnerClassesEmpty = Attribute.define(ad, ATTR_CONTEXT_CLASS,
                                                  "InnerClasses", "").layout();
         attrSourceFileSpecial = Attribute.define(ad, ATTR_CONTEXT_CLASS,
@@ -153,9 +159,8 @@
             package_minver = JAVA6_PACKAGE_MINOR_VERSION;
         } else {
             // Normal case.  Use the newest archive format, when available
-            // TODO: replace the following with JAVA7* when the need arises
-            package_majver = JAVA6_PACKAGE_MAJOR_VERSION;
-            package_minver = JAVA6_PACKAGE_MINOR_VERSION;
+            package_majver = JAVA7_PACKAGE_MAJOR_VERSION;
+            package_minver = JAVA7_PACKAGE_MINOR_VERSION;
         }
     }
 
@@ -168,13 +173,22 @@
             String expMag = Integer.toHexString(JAVA_PACKAGE_MAGIC);
             throw new IOException("Unexpected package magic number: got "+gotMag+"; expected "+expMag);
         }
-        if ((package_majver != JAVA6_PACKAGE_MAJOR_VERSION  &&
-             package_majver != JAVA5_PACKAGE_MAJOR_VERSION) ||
-             (package_minver != JAVA6_PACKAGE_MINOR_VERSION &&
-             package_minver != JAVA5_PACKAGE_MINOR_VERSION)) {
-
+        int[] majminFound = null;
+        for (int[] majmin : new int[][]{
+                { JAVA7_PACKAGE_MAJOR_VERSION, JAVA7_PACKAGE_MINOR_VERSION },
+                { JAVA6_PACKAGE_MAJOR_VERSION, JAVA6_PACKAGE_MINOR_VERSION },
+                { JAVA5_PACKAGE_MAJOR_VERSION, JAVA5_PACKAGE_MINOR_VERSION }
+            }) {
+            if (package_majver == majmin[0] && package_minver == majmin[1]) {
+                majminFound = majmin;
+                break;
+            }
+        }
+        if (majminFound == null) {
             String gotVer = package_majver+"."+package_minver;
-            String expVer = JAVA6_PACKAGE_MAJOR_VERSION+"."+JAVA6_PACKAGE_MINOR_VERSION+
+            String expVer = JAVA7_PACKAGE_MAJOR_VERSION+"."+JAVA7_PACKAGE_MINOR_VERSION+
+                            " OR "+
+                            JAVA6_PACKAGE_MAJOR_VERSION+"."+JAVA6_PACKAGE_MINOR_VERSION+
                             " OR "+
                             JAVA5_PACKAGE_MAJOR_VERSION+"."+JAVA5_PACKAGE_MINOR_VERSION;
             throw new IOException("Unexpected package minor version: got "+gotVer+"; expected "+expVer);
@@ -213,6 +227,7 @@
         //ArrayList attributes;  // in Attribute.Holder.this.attributes
         // Note that InnerClasses may be collected at the package level.
         ArrayList<InnerClass> innerClasses;
+        ArrayList<BootstrapMethodEntry> bootstrapMethods;
 
         Class(int flags, ClassEntry thisClass, ClassEntry superClass, ClassEntry[] interfaces) {
             this.magic      = JAVA_MAGIC;
@@ -313,6 +328,25 @@
             this.cpMap = cpMap;
         }
 
+        boolean hasBootstrapMethods() {
+            return bootstrapMethods != null && !bootstrapMethods.isEmpty();
+        }
+
+        List<BootstrapMethodEntry> getBootstrapMethods() {
+            return bootstrapMethods;
+        }
+
+        BootstrapMethodEntry[] getBootstrapMethodMap() {
+            return (hasBootstrapMethods())
+                    ? bootstrapMethods.toArray(new BootstrapMethodEntry[bootstrapMethods.size()])
+                    : null;
+        }
+
+        void setBootstrapMethods(Collection<BootstrapMethodEntry> bsms) {
+            assert(bootstrapMethods == null);  // do not do this twice
+            bootstrapMethods = new ArrayList<>(bsms);
+        }
+
         boolean hasInnerClasses() {
             return innerClasses != null;
         }
@@ -1283,7 +1317,8 @@
             byTagU[tag] = null;  // done with it
         }
         for (int i = 0; i < byTagU.length; i++) {
-            assert(byTagU[i] == null);  // all consumed
+            Index ix = byTagU[i];
+            assert(ix == null);  // all consumed
         }
         for (int i = 0; i < ConstantPool.TAGS_IN_ORDER.length; i++) {
             byte tag = ConstantPool.TAGS_IN_ORDER[i];
--- a/jdk/src/share/classes/com/sun/java/util/jar/pack/PackageReader.java	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/src/share/classes/com/sun/java/util/jar/pack/PackageReader.java	Wed Jul 05 18:10:27 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,13 +25,7 @@
 
 package com.sun.java.util.jar.pack;
 
-import com.sun.java.util.jar.pack.ConstantPool.ClassEntry;
-import com.sun.java.util.jar.pack.ConstantPool.DescriptorEntry;
-import com.sun.java.util.jar.pack.ConstantPool.Entry;
-import com.sun.java.util.jar.pack.ConstantPool.Index;
-import com.sun.java.util.jar.pack.ConstantPool.MemberEntry;
-import com.sun.java.util.jar.pack.ConstantPool.SignatureEntry;
-import com.sun.java.util.jar.pack.ConstantPool.Utf8Entry;
+import com.sun.java.util.jar.pack.ConstantPool.*;
 import com.sun.java.util.jar.pack.Package.Class;
 import com.sun.java.util.jar.pack.Package.File;
 import com.sun.java.util.jar.pack.Package.InnerClass;
@@ -46,6 +40,7 @@
 import java.util.Map;
 import java.util.Arrays;
 import java.util.Collection;
+import java.util.Collections;
 import java.util.Comparator;
 import java.util.HashSet;
 import java.util.HashMap;
@@ -266,7 +261,6 @@
         //        #band_headers_size :UNSIGNED5[1]
         //        #attr_definition_count :UNSIGNED5[1]
         //
-        assert(AH_LENGTH == 8+(ConstantPool.TAGS_IN_ORDER.length)+6);
         archive_header_0.expectLength(AH_LENGTH_0);
         archive_header_0.readFrom(in);
 
@@ -282,6 +276,7 @@
         boolean haveSpecial = testBit(archiveOptions, AO_HAVE_SPECIAL_FORMATS);
         boolean haveFiles   = testBit(archiveOptions, AO_HAVE_FILE_HEADERS);
         boolean haveNumbers = testBit(archiveOptions, AO_HAVE_CP_NUMBERS);
+        boolean haveCPExtra = testBit(archiveOptions, AO_HAVE_CP_EXTRAS);
         initAttrIndexLimit();
 
         // now we are ready to use the data:
@@ -300,11 +295,11 @@
         archive_header_S.doneDisbursing();
         archiveSize0 = in.getBytesServed();
 
-        int remainingHeaders = AH_LENGTH - AH_LENGTH_0 - AH_LENGTH_S;
-        if (!haveFiles)    remainingHeaders -= AH_FILE_HEADER_LEN-AH_LENGTH_S;
-        if (!haveSpecial)  remainingHeaders -= AH_SPECIAL_FORMAT_LEN;
-        if (!haveNumbers)  remainingHeaders -= AH_CP_NUMBER_LEN;
-        assert(remainingHeaders >= AH_LENGTH_MIN - AH_LENGTH_0);
+        int remainingHeaders = AH_LENGTH_MIN - AH_LENGTH_0 - AH_LENGTH_S;
+        if (haveFiles)    remainingHeaders += AH_FILE_HEADER_LEN;
+        if (haveSpecial)  remainingHeaders += AH_SPECIAL_FORMAT_LEN;
+        if (haveNumbers)  remainingHeaders += AH_CP_NUMBER_LEN;
+        if (haveCPExtra)  remainingHeaders += AH_CP_EXTRA_LEN;
         archive_header_1.expectLength(remainingHeaders);
         archive_header_1.readFrom(in);
 
@@ -325,7 +320,7 @@
             numAttrDefs = 0;
         }
 
-        readConstantPoolCounts(haveNumbers);
+        readConstantPoolCounts(haveNumbers, haveCPExtra);
 
         numInnerClasses = archive_header_1.getInt();
 
@@ -351,7 +346,7 @@
         band_headers.doneDisbursing();
     }
 
-    void readConstantPoolCounts(boolean haveNumbers) throws IOException {
+    void readConstantPoolCounts(boolean haveNumbers, boolean haveCPExtra) throws IOException {
         // size the constant pools:
         for (int k = 0; k < ConstantPool.TAGS_IN_ORDER.length; k++) {
             //  cp_counts:
@@ -364,6 +359,7 @@
             //        #cp_Field_count :UNSIGNED5[1]
             //        #cp_Method_count :UNSIGNED5[1]
             //        #cp_Imethod_count :UNSIGNED5[1]
+            //        (cp_attr_counts) ** (#have_cp_attr_counts)
             //
             //  cp_number_counts:
             //        #cp_Int_count :UNSIGNED5[1]
@@ -371,6 +367,12 @@
             //        #cp_Long_count :UNSIGNED5[1]
             //        #cp_Double_count :UNSIGNED5[1]
             //
+            //  cp_extra_counts:
+            //        #cp_MethodHandle_count :UNSIGNED5[1]
+            //        #cp_MethodType_count :UNSIGNED5[1]
+            //        #cp_InvokeDynamic_count :UNSIGNED5[1]
+            //        #cp_BootstrapMethod_count :UNSIGNED5[1]
+            //
             byte tag = ConstantPool.TAGS_IN_ORDER[k];
             if (!haveNumbers) {
                 // These four counts are optional.
@@ -382,6 +384,16 @@
                     continue;
                 }
             }
+            if (!haveCPExtra) {
+                // These four counts are optional.
+                switch (tag) {
+                case CONSTANT_MethodHandle:
+                case CONSTANT_MethodType:
+                case CONSTANT_InvokeDynamic:
+                case CONSTANT_BootstrapMethod:
+                    continue;
+                }
+            }
             tagCount[tag] = archive_header_1.getInt();
         }
     }
@@ -401,6 +413,11 @@
         return index;
     }
 
+    void checkLegacy(String bandname) {
+        if (this.pkg.package_majver < JAVA7_PACKAGE_MAJOR_VERSION) {
+            throw new RuntimeException("unexpected band " + bandname);
+        }
+    }
     void readConstantPool() throws IOException {
         //  cp_bands:
         //        cp_Utf8
@@ -533,8 +550,82 @@
             case CONSTANT_InterfaceMethodref:
                 readMemberRefs(tag, cpMap, cp_Imethod_class, cp_Imethod_desc);
                 break;
+            case CONSTANT_MethodHandle:
+                if (cpMap.length > 0) {
+                    checkLegacy(cp_MethodHandle_refkind.name());
+                }
+                cp_MethodHandle_refkind.expectLength(cpMap.length);
+                cp_MethodHandle_refkind.readFrom(in);
+                cp_MethodHandle_member.expectLength(cpMap.length);
+                cp_MethodHandle_member.readFrom(in);
+                cp_MethodHandle_member.setIndex(getCPIndex(CONSTANT_AnyMember));
+                for (int i = 0; i < cpMap.length; i++) {
+                    byte        refKind = (byte)        cp_MethodHandle_refkind.getInt();
+                    MemberEntry memRef  = (MemberEntry) cp_MethodHandle_member.getRef();
+                    cpMap[i] = ConstantPool.getMethodHandleEntry(refKind, memRef);
+                }
+                cp_MethodHandle_refkind.doneDisbursing();
+                cp_MethodHandle_member.doneDisbursing();
+                break;
+            case CONSTANT_MethodType:
+                if (cpMap.length > 0) {
+                    checkLegacy(cp_MethodType.name());
+                }
+                cp_MethodType.expectLength(cpMap.length);
+                cp_MethodType.readFrom(in);
+                cp_MethodType.setIndex(getCPIndex(CONSTANT_Signature));
+                for (int i = 0; i < cpMap.length; i++) {
+                    SignatureEntry typeRef  = (SignatureEntry) cp_MethodType.getRef();
+                    cpMap[i] = ConstantPool.getMethodTypeEntry(typeRef);
+                }
+                cp_MethodType.doneDisbursing();
+                break;
+            case CONSTANT_InvokeDynamic:
+                if (cpMap.length > 0) {
+                    checkLegacy(cp_InvokeDynamic_spec.name());
+                }
+                cp_InvokeDynamic_spec.expectLength(cpMap.length);
+                cp_InvokeDynamic_spec.readFrom(in);
+                cp_InvokeDynamic_spec.setIndex(getCPIndex(CONSTANT_BootstrapMethod));
+                cp_InvokeDynamic_desc.expectLength(cpMap.length);
+                cp_InvokeDynamic_desc.readFrom(in);
+                cp_InvokeDynamic_desc.setIndex(getCPIndex(CONSTANT_NameandType));
+                for (int i = 0; i < cpMap.length; i++) {
+                    BootstrapMethodEntry bss   = (BootstrapMethodEntry) cp_InvokeDynamic_spec.getRef();
+                    DescriptorEntry      descr = (DescriptorEntry)      cp_InvokeDynamic_desc.getRef();
+                    cpMap[i] = ConstantPool.getInvokeDynamicEntry(bss, descr);
+                }
+                cp_InvokeDynamic_spec.doneDisbursing();
+                cp_InvokeDynamic_desc.doneDisbursing();
+                break;
+            case CONSTANT_BootstrapMethod:
+                if (cpMap.length > 0) {
+                    checkLegacy(cp_BootstrapMethod_ref.name());
+                }
+                cp_BootstrapMethod_ref.expectLength(cpMap.length);
+                cp_BootstrapMethod_ref.readFrom(in);
+                cp_BootstrapMethod_ref.setIndex(getCPIndex(CONSTANT_MethodHandle));
+                cp_BootstrapMethod_arg_count.expectLength(cpMap.length);
+                cp_BootstrapMethod_arg_count.readFrom(in);
+                int totalArgCount = cp_BootstrapMethod_arg_count.getIntTotal();
+                cp_BootstrapMethod_arg.expectLength(totalArgCount);
+                cp_BootstrapMethod_arg.readFrom(in);
+                cp_BootstrapMethod_arg.setIndex(getCPIndex(CONSTANT_LoadableValue));
+                for (int i = 0; i < cpMap.length; i++) {
+                    MethodHandleEntry bsm = (MethodHandleEntry) cp_BootstrapMethod_ref.getRef();
+                    int argc = cp_BootstrapMethod_arg_count.getInt();
+                    Entry[] argRefs = new Entry[argc];
+                    for (int j = 0; j < argc; j++) {
+                        argRefs[j] = cp_BootstrapMethod_arg.getRef();
+                    }
+                    cpMap[i] = ConstantPool.getBootstrapMethodEntry(bsm, argRefs);
+                }
+                cp_BootstrapMethod_ref.doneDisbursing();
+                cp_BootstrapMethod_arg_count.doneDisbursing();
+                cp_BootstrapMethod_arg.doneDisbursing();
+                break;
             default:
-                assert(false);
+                throw new AssertionError("unexpected CP tag in package");
             }
 
             Index index = initCPIndex(tag, cpMap);
@@ -548,6 +639,21 @@
 
         cp_bands.doneDisbursing();
 
+        if (optDumpBands || verbose > 1) {
+            for (byte tag = CONSTANT_GroupFirst; tag < CONSTANT_GroupLimit; tag++) {
+                Index index = pkg.cp.getIndexByTag(tag);
+                if (index == null || index.isEmpty())  continue;
+                Entry[] cpMap = index.cpMap;
+                if (verbose > 1)
+                    Utils.log.info("Index group "+ConstantPool.tagName(tag)+" contains "+cpMap.length+" entries.");
+                if (optDumpBands) {
+                    try (PrintStream ps = new PrintStream(getDumpStream(index.debugName, tag, ".gidx", index))) {
+                        printArrayTo(ps, cpMap, 0, cpMap.length, true);
+                    }
+                }
+            }
+        }
+
         setBandIndexes();
     }
 
@@ -1056,8 +1162,16 @@
         // look for constant pool entries:
         cls.visitRefs(VRM_CLASSIC, cpRefs);
 
+        ArrayList<BootstrapMethodEntry> bsms = new ArrayList<>();
+        /*
+         * BootstrapMethod(BSMs) are added here before InnerClasses(ICs),
+         * so as to ensure the order. Noting that the BSMs  may be
+         * removed if they are not found in the CP, after the ICs expansion.
+         */
+        cls.addAttribute(Package.attrBootstrapMethodsEmpty.canonicalInstance());
+
         // flesh out the local constant pool
-        ConstantPool.completeReferencesIn(cpRefs, true);
+        ConstantPool.completeReferencesIn(cpRefs, true, bsms);
 
         // Now that we know all our local class references,
         // compute the InnerClasses attribute.
@@ -1074,14 +1188,23 @@
             }
 
             // flesh out the local constant pool, again
-            ConstantPool.completeReferencesIn(cpRefs, true);
+            ConstantPool.completeReferencesIn(cpRefs, true, bsms);
+        }
+
+        // remove the attr previously set, otherwise add the bsm and
+        // references as required
+        if (bsms.isEmpty()) {
+            cls.attributes.remove(Package.attrBootstrapMethodsEmpty.canonicalInstance());
+        } else {
+            cpRefs.add(Package.getRefString("BootstrapMethods"));
+            Collections.sort(bsms);
+            cls.setBootstrapMethods(bsms);
         }
 
         // construct a local constant pool
         int numDoubles = 0;
         for (Entry e : cpRefs) {
             if (e.isDoubleWord())  numDoubles++;
-            assert(e.tag != CONSTANT_Signature) : (e);
         }
         Entry[] cpMap = new Entry[1+numDoubles+cpRefs.size()];
         int fillp = 1;
@@ -1154,7 +1277,8 @@
         int totalNM = class_method_count.getIntTotal();
         field_descr.expectLength(totalNF);
         method_descr.expectLength(totalNM);
-        if (verbose > 1)  Utils.log.fine("expecting #fields="+totalNF+" and #methods="+totalNM+" in #classes="+numClasses);
+        if (verbose > 1)  Utils.log.fine("expecting #fields="+totalNF+
+                " and #methods="+totalNM+" in #classes="+numClasses);
 
         List<Class.Field> fields = new ArrayList<>(totalNF);
         field_descr.readFrom(in);
@@ -1393,7 +1517,8 @@
         MultiBand xxx_attr_bands = attrBands[ctype];
         long flagMask = attrFlagMask[ctype];
         if (verbose > 1) {
-            Utils.log.fine("scanning flags and attrs for "+Attribute.contextName(ctype)+"["+holders.size()+"]");
+            Utils.log.fine("scanning flags and attrs for "+
+                    Attribute.contextName(ctype)+"["+holders.size()+"]");
         }
 
         // Fetch the attribute layout definitions which govern the bands
@@ -1751,8 +1876,10 @@
             bc_local, bc_label,
             bc_intref, bc_floatref,
             bc_longref, bc_doubleref, bc_stringref,
+            bc_loadablevalueref,
             bc_classref, bc_fieldref,
             bc_methodref, bc_imethodref,
+            bc_indyref,
             bc_thisfield, bc_superfield,
             bc_thismethod, bc_supermethod,
             bc_initref,
@@ -2099,7 +2226,8 @@
                         case _ildc:
                         case _cldc:
                         case _fldc:
-                        case _aldc:
+                        case _sldc:
+                        case _qldc:
                             origBC = _ldc;
                             size = 1;
                             ldcRefSet.add(ref);
@@ -2107,7 +2235,8 @@
                         case _ildc_w:
                         case _cldc_w:
                         case _fldc_w:
-                        case _aldc_w:
+                        case _sldc_w:
+                        case _qldc_w:
                             origBC = _ldc_w;
                             break;
                         case _lldc2_w:
@@ -2136,6 +2265,9 @@
                             int argSize = ((MemberEntry)ref).descRef.typeRef.computeSize(true);
                             buf[pc++] = (byte)( 1 + argSize );
                             buf[pc++] = 0;
+                        } else if (origBC == _invokedynamic) {
+                            buf[pc++] = 0;
+                            buf[pc++] = 0;
                         }
                         assert(Instruction.opLength(origBC) == (pc - curPC));
                         continue;
--- a/jdk/src/share/classes/com/sun/java/util/jar/pack/PackageWriter.java	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/src/share/classes/com/sun/java/util/jar/pack/PackageWriter.java	Wed Jul 05 18:10:27 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,15 +25,7 @@
 
 package com.sun.java.util.jar.pack;
 
-import com.sun.java.util.jar.pack.ConstantPool.ClassEntry;
-import com.sun.java.util.jar.pack.ConstantPool.DescriptorEntry;
-import com.sun.java.util.jar.pack.ConstantPool.Entry;
-import com.sun.java.util.jar.pack.ConstantPool.Index;
-import com.sun.java.util.jar.pack.ConstantPool.IndexGroup;
-import com.sun.java.util.jar.pack.ConstantPool.MemberEntry;
-import com.sun.java.util.jar.pack.ConstantPool.NumberEntry;
-import com.sun.java.util.jar.pack.ConstantPool.SignatureEntry;
-import com.sun.java.util.jar.pack.ConstantPool.StringEntry;
+import com.sun.java.util.jar.pack.ConstantPool.*;
 import com.sun.java.util.jar.pack.Package.Class;
 import com.sun.java.util.jar.pack.Package.File;
 import com.sun.java.util.jar.pack.Package.InnerClass;
@@ -281,7 +273,7 @@
 
     void writeArchiveHeader() throws IOException {
         // for debug only:  number of words optimized away
-        int headerDiscountForDebug = 0;
+        int headerSizeForDebug = AH_LENGTH_MIN;
 
         // AO_HAVE_SPECIAL_FORMATS is set if non-default
         // coding techniques are used, or if there are
@@ -293,8 +285,8 @@
             if (haveSpecial)
                 archiveOptions |= AO_HAVE_SPECIAL_FORMATS;
         }
-        if (!haveSpecial)
-            headerDiscountForDebug += AH_SPECIAL_FORMAT_LEN;
+        if (haveSpecial)
+            headerSizeForDebug += AH_SPECIAL_FORMAT_LEN;
 
         // AO_HAVE_FILE_HEADERS is set if there is any
         // file or segment envelope information present.
@@ -305,8 +297,8 @@
             if (haveFiles)
                 archiveOptions |= AO_HAVE_FILE_HEADERS;
         }
-        if (!haveFiles)
-            headerDiscountForDebug += AH_FILE_HEADER_LEN;
+        if (haveFiles)
+            headerSizeForDebug += AH_FILE_HEADER_LEN;
 
         // AO_HAVE_CP_NUMBERS is set if there are any numbers
         // in the global constant pool.  (Numbers are in 15% of classes.)
@@ -316,8 +308,19 @@
             if (haveNumbers)
                 archiveOptions |= AO_HAVE_CP_NUMBERS;
         }
-        if (!haveNumbers)
-            headerDiscountForDebug += AH_CP_NUMBER_LEN;
+        if (haveNumbers)
+            headerSizeForDebug += AH_CP_NUMBER_LEN;
+
+        // AO_HAVE_CP_EXTRAS is set if there are constant pool entries
+        // beyond the Java 6 version of the class file format.
+        boolean haveCPExtra = testBit(archiveOptions, AO_HAVE_CP_EXTRAS);
+        if (!haveCPExtra) {
+            haveCPExtra |= pkg.cp.haveExtraTags();
+            if (haveCPExtra)
+                archiveOptions |= AO_HAVE_CP_EXTRAS;
+        }
+        if (haveCPExtra)
+            headerSizeForDebug += AH_CP_EXTRA_LEN;
 
         assert(pkg.package_majver > 0);  // caller must specify!
         archive_header_0.putInt(pkg.package_minver);
@@ -355,18 +358,18 @@
             assert(attrDefsWritten.length == 0);
         }
 
-        writeConstantPoolCounts(haveNumbers);
+        writeConstantPoolCounts(haveNumbers, haveCPExtra);
 
         archive_header_1.putInt(pkg.getAllInnerClasses().size());
         archive_header_1.putInt(pkg.default_class_minver);
         archive_header_1.putInt(pkg.default_class_majver);
         archive_header_1.putInt(pkg.classes.size());
 
-        // Sanity:  Make sure we came out to 26 (less optional fields):
+        // Sanity:  Make sure we came out to 29 (less optional fields):
         assert(archive_header_0.length() +
                archive_header_S.length() +
                archive_header_1.length()
-               == AH_LENGTH - headerDiscountForDebug);
+               == headerSizeForDebug);
 
         // Figure out all the sizes now, first cut:
         archiveSize0 = 0;
@@ -394,9 +397,8 @@
         assert(all_bands.outputSize() == archiveSize0+archiveSize1);
     }
 
-    void writeConstantPoolCounts(boolean haveNumbers) throws IOException {
-        for (int k = 0; k < ConstantPool.TAGS_IN_ORDER.length; k++) {
-            byte tag = ConstantPool.TAGS_IN_ORDER[k];
+    void writeConstantPoolCounts(boolean haveNumbers, boolean haveCPExtra) throws IOException {
+        for (byte tag : ConstantPool.TAGS_IN_ORDER) {
             int count = pkg.cp.getIndexByTag(tag).size();
             switch (tag) {
             case CONSTANT_Utf8:
@@ -416,6 +418,17 @@
                     continue;
                 }
                 break;
+
+            case CONSTANT_MethodHandle:
+            case CONSTANT_MethodType:
+            case CONSTANT_InvokeDynamic:
+            case CONSTANT_BootstrapMethod:
+                // Omit counts for newer entities if possible.
+                if (!haveCPExtra) {
+                    assert(count == 0);
+                    continue;
+                }
+                break;
             }
             archive_header_1.putInt(count);
         }
@@ -449,8 +462,7 @@
 
         if (verbose > 0)  Utils.log.info("Writing CP");
 
-        for (int k = 0; k < ConstantPool.TAGS_IN_ORDER.length; k++) {
-            byte  tag   = ConstantPool.TAGS_IN_ORDER[k];
+        for (byte tag : ConstantPool.TAGS_IN_ORDER) {
             Index index = cp.getIndexByTag(tag);
 
             Entry[] cpMap = index.cpMap;
@@ -530,8 +542,52 @@
             case CONSTANT_InterfaceMethodref:
                 writeMemberRefs(tag, cpMap, cp_Imethod_class, cp_Imethod_desc);
                 break;
+            case CONSTANT_MethodHandle:
+                for (int i = 0; i < cpMap.length; i++) {
+                    MethodHandleEntry e = (MethodHandleEntry) cpMap[i];
+                    cp_MethodHandle_refkind.putInt(e.refKind);
+                    cp_MethodHandle_member.putRef(e.memRef);
+                }
+                break;
+            case CONSTANT_MethodType:
+                for (int i = 0; i < cpMap.length; i++) {
+                    MethodTypeEntry e = (MethodTypeEntry) cpMap[i];
+                    cp_MethodType.putRef(e.typeRef);
+                }
+                break;
+            case CONSTANT_InvokeDynamic:
+                for (int i = 0; i < cpMap.length; i++) {
+                    InvokeDynamicEntry e = (InvokeDynamicEntry) cpMap[i];
+                    cp_InvokeDynamic_spec.putRef(e.bssRef);
+                    cp_InvokeDynamic_desc.putRef(e.descRef);
+                }
+                break;
+            case CONSTANT_BootstrapMethod:
+                for (int i = 0; i < cpMap.length; i++) {
+                    BootstrapMethodEntry e = (BootstrapMethodEntry) cpMap[i];
+                    cp_BootstrapMethod_ref.putRef(e.bsmRef);
+                    cp_BootstrapMethod_arg_count.putInt(e.argRefs.length);
+                    for (Entry argRef : e.argRefs) {
+                        cp_BootstrapMethod_arg.putRef(argRef);
+                    }
+                }
+                break;
             default:
-                assert(false);
+                throw new AssertionError("unexpected CP tag in package");
+            }
+        }
+        if (optDumpBands || verbose > 1) {
+            for (byte tag = CONSTANT_GroupFirst; tag < CONSTANT_GroupLimit; tag++) {
+                Index index = cp.getIndexByTag(tag);
+                if (index == null || index.isEmpty())  continue;
+                Entry[] cpMap = index.cpMap;
+                if (verbose > 1)
+                    Utils.log.info("Index group "+ConstantPool.tagName(tag)+" contains "+cpMap.length+" entries.");
+                if (optDumpBands) {
+                    try (PrintStream ps = new PrintStream(getDumpStream(index.debugName, tag, ".gidx", index))) {
+                        printArrayTo(ps, cpMap, 0, cpMap.length, true);
+                    }
+                }
             }
         }
     }
@@ -988,6 +1044,8 @@
         for (Class cls : pkg.classes) {
             // Replace "obvious" SourceFile attrs by null.
             cls.minimizeSourceFile();
+            // BootstrapMethods should never have been inserted.
+            assert(cls.getAttribute(Package.attrBootstrapMethodsEmpty) == null);
         }
     }
 
@@ -1325,9 +1383,7 @@
             // %%% Add a stress mode which issues _ref/_byte_escape.
             if (verbose > 3)  Utils.log.fine(i.toString());
 
-            if (i.isNonstandard()
-                && (!p200.getBoolean(Utils.COM_PREFIX+"invokedynamic")
-                    || i.getBC() != _xxxunusedxxx)) {
+            if (i.isNonstandard()) {
                 // Crash and burn with a complaint if there are funny
                 // bytecodes in this class file.
                 String complaint = code.getMethod()
@@ -1427,24 +1483,6 @@
                 continue;
             }
 
-            switch (bc) {
-            case _xxxunusedxxx:  // %%% pretend this is invokedynamic
-                {
-                    i.setNonstandardLength(3);
-                    int refx = i.getShortAt(1);
-                    Entry ref = (refx == 0)? null: curCPMap[refx];
-                    // transmit the opcode, carefully:
-                    bc_codes.putByte(_byte_escape);
-                    bc_escsize.putInt(1);     // one byte of opcode
-                    bc_escbyte.putByte(bc);   // the opcode
-                    // transmit the CP reference, carefully:
-                    bc_codes.putByte(_ref_escape);
-                    bc_escrefsize.putInt(2);  // two bytes of ref
-                    bc_escref.putRef(ref);    // the ref
-                    continue;
-                }
-            }
-
             int branch = i.getBranchLabel();
             if (branch >= 0) {
                 bc_codes.putByte(bc);
@@ -1458,7 +1496,7 @@
                 CPRefBand bc_which;
                 int vbc = bc;
                 switch (i.getCPTag()) {
-                case CONSTANT_Literal:
+                case CONSTANT_LoadableValue:
                     switch (ref.tag) {
                     case CONSTANT_Integer:
                         bc_which = bc_intref;
@@ -1489,8 +1527,8 @@
                     case CONSTANT_String:
                         bc_which = bc_stringref;
                         switch (bc) {
-                        case _ldc:    vbc = _aldc; break;
-                        case _ldc_w:  vbc = _aldc_w; break;
+                        case _ldc:    vbc = _sldc; break;
+                        case _ldc_w:  vbc = _sldc_w; break;
                         default:      assert(false);
                         }
                         break;
@@ -1503,8 +1541,16 @@
                         }
                         break;
                     default:
-                        bc_which = null;
-                        assert(false);
+                        // CONSTANT_MethodHandle, etc.
+                        if (getPackageMajver() < JAVA7_PACKAGE_MAJOR_VERSION) {
+                            throw new IOException("bad package major version for Java 7 ldc");
+                        }
+                        bc_which = bc_loadablevalueref;
+                        switch (bc) {
+                        case _ldc:    vbc = _qldc; break;
+                        case _ldc_w:  vbc = _qldc_w; break;
+                        default:      assert(false);
+                        }
                     }
                     break;
                 case CONSTANT_Class:
@@ -1517,6 +1563,8 @@
                     bc_which = bc_methodref; break;
                 case CONSTANT_InterfaceMethodref:
                     bc_which = bc_imethodref; break;
+                case CONSTANT_InvokeDynamic:
+                    bc_which = bc_indyref; break;
                 default:
                     bc_which = null;
                     assert(false);
@@ -1532,6 +1580,12 @@
                     assert(i.getLength() == 5);
                     // Make sure the discarded bytes are sane:
                     assert(i.getConstant() == (1+((MemberEntry)ref).descRef.typeRef.computeSize(true)) << 8);
+                } else if (bc == _invokedynamic) {
+                    if (getPackageMajver() < JAVA7_PACKAGE_MAJOR_VERSION) {
+                        throw new IOException("bad package major version for Java 7 invokedynamic");
+                    }
+                    assert(i.getLength() == 5);
+                    assert(i.getConstant() == 0);  // last 2 bytes MBZ
                 } else {
                     // Make sure there is nothing else to write.
                     assert(i.getLength() == ((bc == _ldc)?2:3));
--- a/jdk/src/share/classes/com/sun/java/util/jar/pack/TLGlobals.java	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/src/share/classes/com/sun/java/util/jar/pack/TLGlobals.java	Wed Jul 05 18:10:27 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -28,6 +28,10 @@
 import com.sun.java.util.jar.pack.ConstantPool.DescriptorEntry;
 import com.sun.java.util.jar.pack.ConstantPool.LiteralEntry;
 import com.sun.java.util.jar.pack.ConstantPool.MemberEntry;
+import com.sun.java.util.jar.pack.ConstantPool.MethodHandleEntry;
+import com.sun.java.util.jar.pack.ConstantPool.MethodTypeEntry;
+import com.sun.java.util.jar.pack.ConstantPool.InvokeDynamicEntry;
+import com.sun.java.util.jar.pack.ConstantPool.BootstrapMethodEntry;
 import com.sun.java.util.jar.pack.ConstantPool.SignatureEntry;
 import com.sun.java.util.jar.pack.ConstantPool.Utf8Entry;
 import java.util.HashMap;
@@ -56,6 +60,10 @@
     private final Map<String, SignatureEntry> signatureEntries;
     private final Map<String, DescriptorEntry> descriptorEntries;
     private final Map<String, MemberEntry> memberEntries;
+    private final Map<String, MethodHandleEntry> methodHandleEntries;
+    private final Map<String, MethodTypeEntry> methodTypeEntries;
+    private final Map<String, InvokeDynamicEntry> invokeDynamicEntries;
+    private final Map<String, BootstrapMethodEntry> bootstrapMethodEntries;
 
     TLGlobals() {
         utf8Entries = new HashMap<>();
@@ -64,6 +72,10 @@
         signatureEntries = new HashMap<>();
         descriptorEntries = new HashMap<>();
         memberEntries = new HashMap<>();
+        methodHandleEntries = new HashMap<>();
+        methodTypeEntries = new HashMap<>();
+        invokeDynamicEntries = new HashMap<>();
+        bootstrapMethodEntries = new HashMap<>();
         props = new PropMap();
     }
 
@@ -94,4 +106,20 @@
     Map<String, MemberEntry> getMemberEntries() {
         return memberEntries;
     }
+
+    Map<String, MethodHandleEntry> getMethodHandleEntries() {
+        return methodHandleEntries;
+    }
+
+    Map<String, MethodTypeEntry> getMethodTypeEntries() {
+        return methodTypeEntries;
+    }
+
+    Map<String, InvokeDynamicEntry> getInvokeDynamicEntries() {
+        return invokeDynamicEntries;
+    }
+
+    Map<String, BootstrapMethodEntry> getBootstrapMethodEntries() {
+        return bootstrapMethodEntries;
+    }
 }
--- a/jdk/src/share/classes/com/sun/java/util/jar/pack/Utils.java	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/src/share/classes/com/sun/java/util/jar/pack/Utils.java	Wed Jul 05 18:10:27 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -60,7 +60,7 @@
      * If >3, print tons of comments (e.g., processing of references).
      * (installer only)
      */
-    static final String DEBUG_VERBOSE = Utils.COM_PREFIX+"verbose";
+    static final String DEBUG_VERBOSE = COM_PREFIX+"verbose";
 
     /*
      * Disables use of native code, prefers the Java-coded implementation.
@@ -134,35 +134,11 @@
     // to the engine code, especially the native code.
     static final ThreadLocal<TLGlobals> currentInstance = new ThreadLocal<>();
 
-    // convenience methods to access the TL globals
+    // convenience method to access the TL globals
     static TLGlobals getTLGlobals() {
         return currentInstance.get();
     }
 
-    static Map<String, Utf8Entry> getUtf8Entries() {
-        return getTLGlobals().getUtf8Entries();
-    }
-
-    static Map<String, ClassEntry> getClassEntries() {
-        return getTLGlobals().getClassEntries();
-    }
-
-    static Map<Object, LiteralEntry> getLiteralEntries() {
-        return getTLGlobals().getLiteralEntries();
-    }
-
-    static Map<String, DescriptorEntry> getDescriptorEntries() {
-         return getTLGlobals().getDescriptorEntries();
-    }
-
-    static Map<String, SignatureEntry> getSignatureEntries() {
-        return getTLGlobals().getSignatureEntries();
-    }
-
-    static Map<String, MemberEntry> getMemberEntries() {
-        return getTLGlobals().getMemberEntries();
-    }
-
     static PropMap currentPropMap() {
         Object obj = currentInstance.get();
         if (obj instanceof PackerImpl)
@@ -173,8 +149,19 @@
     }
 
     static final boolean nolog
-        = Boolean.getBoolean(Utils.COM_PREFIX+"nolog");
+        = Boolean.getBoolean(COM_PREFIX+"nolog");
+
+    static final boolean SORT_MEMBERS_DESCR_MAJOR
+        = Boolean.getBoolean(COM_PREFIX+"sort.members.descr.major");
 
+    static final boolean SORT_HANDLES_KIND_MAJOR
+        = Boolean.getBoolean(COM_PREFIX+"sort.handles.kind.major");
+
+    static final boolean SORT_INDY_BSS_MAJOR
+        = Boolean.getBoolean(COM_PREFIX+"sort.indy.bss.major");
+
+    static final boolean SORT_BSS_BSM_MAJOR
+        = Boolean.getBoolean(COM_PREFIX+"sort.bss.bsm.major");
 
     static class Pack200Logger {
         private final String name;
--- a/jdk/src/share/classes/java/awt/SplashScreen.java	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/src/share/classes/java/awt/SplashScreen.java	Wed Jul 05 18:10:27 2017 +0200
@@ -119,7 +119,12 @@
             // SplashScreen class is now a singleton
             if (!wasClosed && theInstance == null) {
                 java.security.AccessController.doPrivileged(
-                        new sun.security.action.LoadLibraryAction("splashscreen"));
+                    new java.security.PrivilegedAction<Void>() {
+                        public Void run() {
+                            System.loadLibrary("splashscreen");
+                            return null;
+                        }
+                    });
                 long ptr = _getInstance();
                 if (ptr != 0 && _isVisible(ptr)) {
                     theInstance = new SplashScreen(ptr);
--- a/jdk/src/share/classes/java/awt/Toolkit.java	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/src/share/classes/java/awt/Toolkit.java	Wed Jul 05 18:10:27 2017 +0200
@@ -1646,7 +1646,12 @@
     static void loadLibraries() {
         if (!loaded) {
             java.security.AccessController.doPrivileged(
-                          new sun.security.action.LoadLibraryAction("awt"));
+                new java.security.PrivilegedAction<Void>() {
+                    public Void run() {
+                        System.loadLibrary("awt");
+                        return null;
+                    }
+                });
             loaded = true;
         }
     }
--- a/jdk/src/share/classes/java/awt/event/NativeLibLoader.java	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/src/share/classes/java/awt/event/NativeLibLoader.java	Wed Jul 05 18:10:27 2017 +0200
@@ -54,6 +54,11 @@
      */
     static void loadLibraries() {
         java.security.AccessController.doPrivileged(
-                new sun.security.action.LoadLibraryAction("awt"));
+            new java.security.PrivilegedAction<Void>() {
+                public Void run() {
+                    System.loadLibrary("awt");
+                    return null;
+                }
+            });
     }
 }
--- a/jdk/src/share/classes/java/awt/image/ColorModel.java	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/src/share/classes/java/awt/image/ColorModel.java	Wed Jul 05 18:10:27 2017 +0200
@@ -204,7 +204,12 @@
     static void loadLibraries() {
         if (!loaded) {
             java.security.AccessController.doPrivileged(
-                  new sun.security.action.LoadLibraryAction("awt"));
+                new java.security.PrivilegedAction<Void>() {
+                    public Void run() {
+                        System.loadLibrary("awt");
+                        return null;
+                    }
+                });
             loaded = true;
         }
     }
--- a/jdk/src/share/classes/java/net/AbstractPlainDatagramSocketImpl.java	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/src/share/classes/java/net/AbstractPlainDatagramSocketImpl.java	Wed Jul 05 18:10:27 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -60,14 +60,19 @@
     /**
      * flag set if the native connect() call not to be used
      */
-    private final static boolean connectDisabled = os.startsWith("Mac OS");
+    private final static boolean connectDisabled = os.contains("OS X");
 
     /**
      * Load net library into runtime.
      */
     static {
         java.security.AccessController.doPrivileged(
-                  new sun.security.action.LoadLibraryAction("net"));
+            new java.security.PrivilegedAction<Void>() {
+                public Void run() {
+                    System.loadLibrary("net");
+                    return null;
+                }
+            });
     }
 
     /**
--- a/jdk/src/share/classes/java/net/AbstractPlainSocketImpl.java	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/src/share/classes/java/net/AbstractPlainSocketImpl.java	Wed Jul 05 18:10:27 2017 +0200
@@ -78,7 +78,12 @@
      */
     static {
         java.security.AccessController.doPrivileged(
-                  new sun.security.action.LoadLibraryAction("net"));
+            new java.security.PrivilegedAction<Void>() {
+                public Void run() {
+                    System.loadLibrary("net");
+                    return null;
+                }
+            });
     }
 
     /**
--- a/jdk/src/share/classes/java/net/DatagramPacket.java	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/src/share/classes/java/net/DatagramPacket.java	Wed Jul 05 18:10:27 2017 +0200
@@ -47,7 +47,12 @@
      */
     static {
         java.security.AccessController.doPrivileged(
-                  new sun.security.action.LoadLibraryAction("net"));
+            new java.security.PrivilegedAction<Void>() {
+                public Void run() {
+                    System.loadLibrary("net");
+                    return null;
+                }
+            });
         init();
     }
 
--- a/jdk/src/share/classes/java/net/InetAddress.java	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/src/share/classes/java/net/InetAddress.java	Wed Jul 05 18:10:27 2017 +0200
@@ -234,7 +234,13 @@
     static {
         preferIPv6Address = java.security.AccessController.doPrivileged(
             new GetBooleanAction("java.net.preferIPv6Addresses")).booleanValue();
-        AccessController.doPrivileged(new LoadLibraryAction("net"));
+        AccessController.doPrivileged(
+            new java.security.PrivilegedAction<Void>() {
+                public Void run() {
+                    System.loadLibrary("net");
+                    return null;
+                }
+            });
         init();
     }
 
--- a/jdk/src/share/classes/java/net/NetworkInterface.java	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/src/share/classes/java/net/NetworkInterface.java	Wed Jul 05 18:10:27 2017 +0200
@@ -53,7 +53,14 @@
     private static final int defaultIndex; /* index of defaultInterface */
 
     static {
-        AccessController.doPrivileged(new LoadLibraryAction("net"));
+        AccessController.doPrivileged(
+            new java.security.PrivilegedAction<Void>() {
+                public Void run() {
+                    System.loadLibrary("net");
+                    return null;
+                }
+            });
+
         init();
         defaultInterface = DefaultInterface.getDefault();
         if (defaultInterface != null) {
--- a/jdk/src/share/classes/java/nio/Bits.java	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/src/share/classes/java/nio/Bits.java	Wed Jul 05 18:10:27 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -609,7 +609,7 @@
         String arch = AccessController.doPrivileged(
             new sun.security.action.GetPropertyAction("os.arch"));
         unaligned = arch.equals("i386") || arch.equals("x86")
-            || arch.equals("amd64");
+            || arch.equals("amd64") || arch.equals("x86_64");
         unalignedKnown = true;
         return unaligned;
     }
--- a/jdk/src/share/classes/java/nio/file/Path.java	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/src/share/classes/java/nio/file/Path.java	Wed Jul 05 18:10:27 2017 +0200
@@ -54,7 +54,7 @@
  * resolveSibling} methods to combine paths. The {@link #relativize relativize}
  * method that can be used to construct a relative path between two paths.
  * Paths can be {@link #compareTo compared}, and tested against each other using
- * the {@link #startsWith startsWith} and {@link #endsWith endWith} methods.
+ * the {@link #startsWith startsWith} and {@link #endsWith endsWith} methods.
  *
  * <p> This interface extends {@link Watchable} interface so that a directory
  * located by a path can be {@link #register registered} with a {@link
--- a/jdk/src/share/classes/java/text/DateFormatSymbols.java	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/src/share/classes/java/text/DateFormatSymbols.java	Wed Jul 05 18:10:27 2017 +0200
@@ -647,6 +647,8 @@
     private static final ConcurrentMap<Locale, SoftReference<DateFormatSymbols>> cachedInstances
         = new ConcurrentHashMap<Locale, SoftReference<DateFormatSymbols>>(3);
 
+    private transient int lastZoneIndex = 0;
+
     private void initializeData(Locale desiredLocale) {
         locale = desiredLocale;
 
@@ -692,12 +694,24 @@
      * the given time zone ID can't be located in the DateFormatSymbols object.
      * @see java.util.SimpleTimeZone
      */
-    final int getZoneIndex(String ID)
-    {
+    final int getZoneIndex(String ID) {
         String[][] zoneStrings = getZoneStringsWrapper();
-        for (int index=0; index<zoneStrings.length; index++)
-        {
-            if (ID.equals(zoneStrings[index][0])) return index;
+
+        /*
+         * getZoneIndex has been re-written for performance reasons. instead of
+         * traversing the zoneStrings array every time, we cache the last used zone
+         * index
+         */
+        if (lastZoneIndex < zoneStrings.length && ID.equals(zoneStrings[lastZoneIndex][0])) {
+            return lastZoneIndex;
+        }
+
+        /* slow path, search entire list */
+        for (int index = 0; index < zoneStrings.length; index++) {
+            if (ID.equals(zoneStrings[index][0])) {
+                lastZoneIndex = index;
+                return index;
+            }
         }
 
         return -1;
--- a/jdk/src/share/classes/java/util/prefs/Preferences.java	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/src/share/classes/java/util/prefs/Preferences.java	Wed Jul 05 18:10:27 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -293,7 +293,7 @@
         String platformFactory;
         if (osName.startsWith("Windows")) {
             platformFactory = "java.util.prefs.WindowsPreferencesFactory";
-        } else if (osName.startsWith("Mac OS X")) {
+        } else if (osName.contains("OS X")) {
             platformFactory = "java.util.prefs.MacOSXPreferencesFactory";
         } else {
             platformFactory = "java.util.prefs.FileSystemPreferencesFactory";
--- a/jdk/src/share/classes/javax/net/ssl/SSLContext.java	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/src/share/classes/javax/net/ssl/SSLContext.java	Wed Jul 05 18:10:27 2017 +0200
@@ -145,7 +145,7 @@
      * @return the new <code>SSLContext</code> object.
      *
      * @exception NoSuchAlgorithmException if no Provider supports a
-     *          TrustManagerFactorySpi implementation for the
+     *          SSLContextSpi implementation for the
      *          specified protocol.
      * @exception NullPointerException if protocol is null.
      *
@@ -222,11 +222,11 @@
      *
      * @return the new <code>SSLContext</code> object.
      *
-     * @throws NoSuchAlgorithmException if a KeyManagerFactorySpi
+     * @throws NoSuchAlgorithmException if a SSLContextSpi
      *          implementation for the specified protocol is not available
      *          from the specified Provider object.
      *
-     * @throws IllegalArgumentException if the provider name is null.
+     * @throws IllegalArgumentException if the provider is null.
      * @throws NullPointerException if protocol is null.
      *
      * @see java.security.Provider
--- a/jdk/src/share/classes/javax/swing/JComponent.java	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/src/share/classes/javax/swing/JComponent.java	Wed Jul 05 18:10:27 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -2638,17 +2638,16 @@
      *    attribute: visualUpdate true
      */
     public void setVisible(boolean aFlag) {
-        if(aFlag != isVisible()) {
+        if (aFlag != isVisible()) {
             super.setVisible(aFlag);
-            Container parent = getParent();
-            if(parent != null) {
-                Rectangle r = getBounds();
-                parent.repaint(r.x,r.y,r.width,r.height);
+            if (aFlag) {
+                Container parent = getParent();
+                if (parent != null) {
+                    Rectangle r = getBounds();
+                    parent.repaint(r.x, r.y, r.width, r.height);
+                }
+                revalidate();
             }
-            // Some (all should) LayoutManagers do not consider components
-            // that are not visible. As such we need to revalidate when the
-            // visible bit changes.
-            revalidate();
         }
     }
 
@@ -5568,4 +5567,21 @@
         ",preferredSize=" + preferredSizeString;
     }
 
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void hide() {
+        boolean showing = isShowing();
+        super.hide();
+        if (showing) {
+            Container parent = getParent();
+            if (parent != null) {
+                Rectangle r = getBounds();
+                parent.repaint(r.x, r.y, r.width, r.height);
+            }
+            revalidate();
+        }
+    }
+
 }
--- a/jdk/src/share/classes/javax/swing/JDesktopPane.java	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/src/share/classes/javax/swing/JDesktopPane.java	Wed Jul 05 18:10:27 2017 +0200
@@ -27,7 +27,8 @@
 
 import java.util.List;
 import java.util.ArrayList;
-import java.util.Vector;
+import java.util.Collection;
+import java.util.Iterator;
 import javax.swing.plaf.*;
 import javax.accessibility.*;
 
@@ -42,7 +43,6 @@
 import java.beans.PropertyVetoException;
 import java.util.Set;
 import java.util.TreeSet;
-
 /**
  * A container used to create a multiple-document interface or a virtual desktop.
  * You create <code>JInternalFrame</code> objects and add them to the
@@ -261,25 +261,26 @@
      * @return an array of <code>JInternalFrame</code> objects
      */
     public JInternalFrame[] getAllFrames() {
-        int i, count;
-        JInternalFrame[] results;
-        Vector<JInternalFrame> vResults = new Vector<JInternalFrame>(10);
+        return getAllFrames(this).toArray(new JInternalFrame[0]);
+    }
 
-        count = getComponentCount();
-        for(i = 0; i < count; i++) {
-            Component next = getComponent(i);
-            if(next instanceof JInternalFrame)
-                vResults.addElement((JInternalFrame) next);
-            else if(next instanceof JInternalFrame.JDesktopIcon)  {
-                JInternalFrame tmp = ((JInternalFrame.JDesktopIcon)next).getInternalFrame();
-                if(tmp != null)
-                    vResults.addElement(tmp);
+    private static Collection<JInternalFrame> getAllFrames(Container parent) {
+        int i, count;
+        Collection<JInternalFrame> results = new ArrayList<JInternalFrame>();
+        count = parent.getComponentCount();
+        for (i = 0; i < count; i++) {
+            Component next = parent.getComponent(i);
+            if (next instanceof JInternalFrame) {
+                results.add((JInternalFrame) next);
+            } else if (next instanceof JInternalFrame.JDesktopIcon) {
+                JInternalFrame tmp = ((JInternalFrame.JDesktopIcon) next).getInternalFrame();
+                if (tmp != null) {
+                    results.add(tmp);
+                }
+            } else if (next instanceof Container) {
+                results.addAll(getAllFrames((Container) next));
             }
         }
-
-        results = new JInternalFrame[vResults.size()];
-        vResults.copyInto(results);
-
         return results;
     }
 
@@ -322,27 +323,14 @@
      * @see JLayeredPane
      */
     public JInternalFrame[] getAllFramesInLayer(int layer) {
-        int i, count;
-        JInternalFrame[] results;
-        Vector<JInternalFrame> vResults = new Vector<JInternalFrame>(10);
-
-        count = getComponentCount();
-        for(i = 0; i < count; i++) {
-            Component next = getComponent(i);
-            if(next instanceof JInternalFrame) {
-                if(((JInternalFrame)next).getLayer() == layer)
-                    vResults.addElement((JInternalFrame) next);
-            } else if(next instanceof JInternalFrame.JDesktopIcon)  {
-                JInternalFrame tmp = ((JInternalFrame.JDesktopIcon)next).getInternalFrame();
-                if(tmp != null && tmp.getLayer() == layer)
-                    vResults.addElement(tmp);
+        Collection<JInternalFrame> allFrames = getAllFrames(this);
+        Iterator<JInternalFrame> iterator = allFrames.iterator();
+        while (iterator.hasNext()) {
+            if (iterator.next().getLayer() != layer) {
+                iterator.remove();
             }
         }
-
-        results = new JInternalFrame[vResults.size()];
-        vResults.copyInto(results);
-
-        return results;
+        return allFrames.toArray(new JInternalFrame[0]);
     }
 
     private List<JInternalFrame> getFrames() {
--- a/jdk/src/share/classes/javax/swing/JPopupMenu.java	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/src/share/classes/javax/swing/JPopupMenu.java	Wed Jul 05 18:10:27 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -41,6 +41,8 @@
 import javax.swing.plaf.ComponentUI;
 import javax.swing.plaf.basic.BasicComboPopup;
 import javax.swing.event.*;
+
+import sun.awt.SunToolkit;
 import sun.security.util.SecurityConstants;
 
 import java.applet.Applet;
@@ -347,6 +349,7 @@
         long popupBottomY = (long)popupLocation.y + (long)popupSize.height;
         int scrWidth = scrBounds.width;
         int scrHeight = scrBounds.height;
+
         if (!canPopupOverlapTaskBar()) {
             // Insets include the task bar. Take them into account.
             Insets scrInsets = toolkit.getScreenInsets(gc);
@@ -407,25 +410,19 @@
     }
 
     /**
-     * Checks that there are enough security permissions
-     * to make popup "always on top", which allows to show it above the task bar.
+     * Returns whether popup is allowed to be shown above the task bar.
      */
     static boolean canPopupOverlapTaskBar() {
         boolean result = true;
-        try {
-            SecurityManager sm = System.getSecurityManager();
-            if (sm != null) {
-                sm.checkPermission(
-                    SecurityConstants.AWT.SET_WINDOW_ALWAYS_ON_TOP_PERMISSION);
-            }
-        } catch (SecurityException se) {
-            // There is no permission to show popups over the task bar
-            result = false;
+
+        Toolkit tk = Toolkit.getDefaultToolkit();
+        if (tk instanceof SunToolkit) {
+            result = ((SunToolkit)tk).canPopupOverlapTaskBar();
         }
+
         return result;
     }
 
-
     /**
      * Factory method which creates the <code>JMenuItem</code> for
      * <code>Actions</code> added to the <code>JPopupMenu</code>.
--- a/jdk/src/share/classes/javax/swing/JTable.java	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/src/share/classes/javax/swing/JTable.java	Wed Jul 05 18:10:27 2017 +0200
@@ -5470,7 +5470,7 @@
                 if (constructor.getDeclaringClass() == String.class) {
                     value = s;
                 }
-                super.stopCellEditing();
+                return super.stopCellEditing();
             }
 
             try {
--- a/jdk/src/share/classes/sun/awt/NativeLibLoader.java	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/src/share/classes/sun/awt/NativeLibLoader.java	Wed Jul 05 18:10:27 2017 +0200
@@ -54,6 +54,11 @@
      */
     static void loadLibraries() {
         java.security.AccessController.doPrivileged(
-            new sun.security.action.LoadLibraryAction("awt"));
+            new java.security.PrivilegedAction<Void>() {
+                public Void run() {
+                    System.loadLibrary("awt");
+                    return null;
+                }
+            });
     }
 }
--- a/jdk/src/share/classes/sun/awt/OSInfo.java	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/src/share/classes/sun/awt/OSInfo.java	Wed Jul 05 18:10:27 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -101,7 +101,7 @@
                 return SOLARIS;
             }
 
-            if (osName.startsWith("Mac OS X")) {
+            if (osName.contains("OS X")) {
                 return MACOSX;
             }
 
--- a/jdk/src/share/classes/sun/awt/SunToolkit.java	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/src/share/classes/sun/awt/SunToolkit.java	Wed Jul 05 18:10:27 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -42,6 +42,8 @@
 import java.util.concurrent.locks.Condition;
 import java.util.concurrent.locks.Lock;
 import java.util.concurrent.locks.ReentrantLock;
+
+import sun.security.util.SecurityConstants;
 import sun.util.logging.PlatformLogger;
 import sun.misc.SoftCache;
 import sun.font.FontDesignMetrics;
@@ -1136,6 +1138,26 @@
     }
 
     /**
+     * Returns whether popup is allowed to be shown above the task bar.
+     * This is a default implementation of this method, which checks
+     * corresponding security permission.
+     */
+    public boolean canPopupOverlapTaskBar() {
+        boolean result = true;
+        try {
+            SecurityManager sm = System.getSecurityManager();
+            if (sm != null) {
+                sm.checkPermission(
+                        SecurityConstants.AWT.SET_WINDOW_ALWAYS_ON_TOP_PERMISSION);
+            }
+        } catch (SecurityException se) {
+            // There is no permission to show popups over the task bar
+            result = false;
+        }
+        return result;
+    }
+
+    /**
      * Returns a new input method window, with behavior as specified in
      * {@link java.awt.im.spi.InputMethodContext#createInputMethodWindow}.
      * If the inputContext is not null, the window should return it from its
--- a/jdk/src/share/classes/sun/awt/image/JPEGImageDecoder.java	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/src/share/classes/sun/awt/image/JPEGImageDecoder.java	Wed Jul 05 18:10:27 2017 +0200
@@ -54,7 +54,12 @@
 
     static {
         java.security.AccessController.doPrivileged(
-                  new sun.security.action.LoadLibraryAction("jpeg"));
+            new java.security.PrivilegedAction<Void>() {
+                public Void run() {
+                    System.loadLibrary("jpeg");
+                    return null;
+                }
+            });
         initIDs(InputStreamClass);
         RGBcolormodel = new DirectColorModel(24, 0xff0000, 0xff00, 0xff);
         ARGBcolormodel = ColorModel.getRGBdefault();
--- a/jdk/src/share/classes/sun/awt/image/NativeLibLoader.java	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/src/share/classes/sun/awt/image/NativeLibLoader.java	Wed Jul 05 18:10:27 2017 +0200
@@ -53,7 +53,12 @@
      * that the name of the library is "awt".  -br.
      */
     static void loadLibraries() {
-        java.security.AccessController.doPrivileged
-                (new sun.security.action.LoadLibraryAction("awt"));
+        java.security.AccessController.doPrivileged(
+            new java.security.PrivilegedAction<Void>() {
+                public Void run() {
+                    System.loadLibrary("awt");
+                    return null;
+                }
+            });
     }
 }
--- a/jdk/src/share/classes/sun/font/FontUtilities.java	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/src/share/classes/sun/font/FontUtilities.java	Wed Jul 05 18:10:27 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -78,7 +78,7 @@
 
                 isLinux = osName.startsWith("Linux");
 
-                isMacOSX = osName.startsWith("Mac OS X"); // TODO: MacOSX
+                isMacOSX = osName.contains("OS X"); // TODO: MacOSX
 
                 String t2kStr = System.getProperty("sun.java2d.font.scaler");
                 if (t2kStr != null) {
--- a/jdk/src/share/classes/sun/java2d/Disposer.java	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/src/share/classes/sun/java2d/Disposer.java	Wed Jul 05 18:10:27 2017 +0200
@@ -57,7 +57,12 @@
 
     static {
         java.security.AccessController.doPrivileged(
-            new sun.security.action.LoadLibraryAction("awt"));
+            new java.security.PrivilegedAction<Void>() {
+                public Void run() {
+                    System.loadLibrary("awt");
+                    return null;
+                }
+            });
         initIDs();
         String type = (String) java.security.AccessController.doPrivileged(
                 new sun.security.action.GetPropertyAction("sun.java2d.reftype"));
--- a/jdk/src/share/classes/sun/launcher/LauncherHelper.java	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/src/share/classes/sun/launcher/LauncherHelper.java	Wed Jul 05 18:10:27 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -381,7 +381,7 @@
         PrintStream ostream =  (printToStderr) ? System.err : System.out;
         ostream.println(getLocalizedMessage("java.launcher.X.usage",
                 File.pathSeparator));
-        if (System.getProperty("os.name").startsWith("Mac OS")) {
+        if (System.getProperty("os.name").contains("OS X")) {
             ostream.println(getLocalizedMessage("java.launcher.X.macosx.usage",
                         File.pathSeparator));
         }
--- a/jdk/src/share/classes/sun/management/ManagementFactoryHelper.java	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/src/share/classes/sun/management/ManagementFactoryHelper.java	Wed Jul 05 18:10:27 2017 +0200
@@ -37,7 +37,6 @@
 import java.security.AccessController;
 import java.security.PrivilegedActionException;
 import java.security.PrivilegedExceptionAction;
-import sun.security.action.LoadLibraryAction;
 
 import sun.util.logging.LoggingSupport;
 
@@ -422,7 +421,13 @@
     }
 
     static {
-        AccessController.doPrivileged(new LoadLibraryAction("management"));
+        AccessController.doPrivileged(
+            new java.security.PrivilegedAction<Void>() {
+                public Void run() {
+                    System.loadLibrary("management");
+                    return null;
+                }
+            });
         jvm = new VMManagementImpl();
     }
 
--- a/jdk/src/share/classes/sun/net/sdp/SdpSupport.java	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/src/share/classes/sun/net/sdp/SdpSupport.java	Wed Jul 05 18:10:27 2017 +0200
@@ -76,6 +76,11 @@
 
     static {
         AccessController.doPrivileged(
-            new sun.security.action.LoadLibraryAction("net"));
+            new java.security.PrivilegedAction<Void>() {
+                public Void run() {
+                    System.loadLibrary("net");
+                    return null;
+                }
+            });
     }
 }
--- a/jdk/src/share/classes/sun/net/spi/DefaultProxySelector.java	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/src/share/classes/sun/net/spi/DefaultProxySelector.java	Wed Jul 05 18:10:27 2017 +0200
@@ -95,7 +95,12 @@
                 }});
         if (b != null && b.booleanValue()) {
             java.security.AccessController.doPrivileged(
-                      new sun.security.action.LoadLibraryAction("net"));
+                new java.security.PrivilegedAction<Void>() {
+                    public Void run() {
+                        System.loadLibrary("net");
+                        return null;
+                    }
+                });
             hasSystemProxies = init();
         }
     }
--- a/jdk/src/share/classes/sun/nio/ch/DatagramChannelImpl.java	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/src/share/classes/sun/nio/ch/DatagramChannelImpl.java	Wed Jul 05 18:10:27 2017 +0200
@@ -744,7 +744,8 @@
                     if (sm != null)
                         sm.checkConnect(isa.getAddress().getHostAddress(),
                                         isa.getPort());
-                    disconnect0(fd);
+                    boolean isIPv6 = (family == StandardProtocolFamily.INET6);
+                    disconnect0(fd, isIPv6);
                     remoteAddress = null;
                     state = ST_UNCONNECTED;
 
@@ -1079,7 +1080,7 @@
 
     private static native void initIDs();
 
-    private static native void disconnect0(FileDescriptor fd)
+    private static native void disconnect0(FileDescriptor fd, boolean isIPv6)
         throws IOException;
 
     private native int receive0(FileDescriptor fd, long address, int len,
--- a/jdk/src/share/classes/sun/nio/ch/Util.java	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/src/share/classes/sun/nio/ch/Util.java	Wed Jul 05 18:10:27 2017 +0200
@@ -472,10 +472,15 @@
             if (loaded)
                 return;
             loaded = true;
-            java.security.AccessController
-                .doPrivileged(new sun.security.action.LoadLibraryAction("net"));
-            java.security.AccessController
-                .doPrivileged(new sun.security.action.LoadLibraryAction("nio"));
+            java.security.AccessController.doPrivileged(
+                new java.security.PrivilegedAction<Void>() {
+                    public Void run() {
+                        System.loadLibrary("net");
+                        System.loadLibrary("nio");
+                        return null;
+                    }
+                });
+
             // IOUtil must be initialized; Its native methods are called from
             // other places in native nio code so they must be set up.
             IOUtil.initIDs();
--- a/jdk/src/share/classes/sun/nio/cs/ext/ExtendedCharsets.java	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/src/share/classes/sun/nio/cs/ext/ExtendedCharsets.java	Wed Jul 05 18:10:27 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -1280,7 +1280,7 @@
         String osName = AccessController.doPrivileged(
             new GetPropertyAction("os.name"));
         if ("SunOS".equals(osName) || "Linux".equals(osName)
-               || osName.startsWith("Mac OS")) {
+               || osName.contains("OS X")) {
             charset("x-COMPOUND_TEXT", "COMPOUND_TEXT",
                     new String[] {
                         "COMPOUND_TEXT",        // JDK historical
--- a/jdk/src/share/classes/sun/print/PSPrinterJob.java	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/src/share/classes/sun/print/PSPrinterJob.java	Wed Jul 05 18:10:27 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -1567,7 +1567,7 @@
         }
 
        String osname = System.getProperty("os.name");
-       if (osname.equals("Linux") || osname.startsWith("Mac OS X")) {
+       if (osname.equals("Linux") || osname.contains("OS X")) {
             execCmd = new String[ncomps];
             execCmd[n++] = "/usr/bin/lpr";
             if ((pFlags & PRINTER) != 0) {
--- a/jdk/src/share/classes/sun/print/ServiceDialog.java	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/src/share/classes/sun/print/ServiceDialog.java	Wed Jul 05 18:10:27 2017 +0200
@@ -72,6 +72,7 @@
 import sun.print.SunPageSelection;
 import java.awt.event.KeyEvent;
 import java.net.URISyntaxException;
+import java.lang.reflect.Field;
 
 
 /**
@@ -479,20 +480,45 @@
      */
     public static String getMsg(String key) {
         try {
-            return messageRB.getString(key);
+            return removeMnemonics(messageRB.getString(key));
         } catch (java.util.MissingResourceException e) {
             throw new Error("Fatal: Resource for ServiceUI is broken; " +
                             "there is no " + key + " key in resource");
         }
     }
 
+    private static String removeMnemonics(String s) {
+        int i = s.indexOf('&');
+        int len = s.length();
+        if (i < 0 || i == (len - 1)) {
+            return s;
+        }
+        int j = s.indexOf('&', i+1);
+        if (j == i+1) {
+            if (j+1 == len) {
+                return s.substring(0, i+1);  // string ends with &&
+            } else {
+                return s.substring(0, i+1) + removeMnemonics(s.substring(j+1));
+            }
+        }
+        // ok first & not double &&
+        if (i == 0) {
+            return removeMnemonics(s.substring(1));
+        } else {
+            return (s.substring(0, i) + removeMnemonics(s.substring(i+1)));
+        }
+    }
+
+
     /**
      * Returns mnemonic character from resource
      */
     private static char getMnemonic(String key) {
-        String str = getMsg(key + ".mnemonic");
-        if ((str != null) && (str.length() > 0)) {
-            return str.charAt(0);
+        String str = messageRB.getString(key).replace("&&", "");
+        int index = str.indexOf('&');
+        if (0 <= index && index < str.length() - 1) {
+            char c = str.charAt(index + 1);
+            return Character.toUpperCase(c);
         } else {
             return (char)0;
         }
@@ -501,12 +527,23 @@
     /**
      * Returns the mnemonic as a KeyEvent.VK constant from the resource.
      */
+    static Class _keyEventClazz = null;
     private static int getVKMnemonic(String key) {
-        String str = getMsg(key + ".vkMnemonic");
-        if ((str != null) && (str.length() > 0)) {
-            try {
-                return Integer.parseInt(str);
-            } catch (NumberFormatException nfe) {}
+        String s = String.valueOf(getMnemonic(key));
+        if ( s == null || s.length() != 1) {
+            return 0;
+        }
+        String vkString = "VK_" + s.toUpperCase();
+
+        try {
+            if (_keyEventClazz == null) {
+                _keyEventClazz= Class.forName("java.awt.event.KeyEvent",
+                                 true, (ServiceDialog.class).getClassLoader());
+            }
+            Field field = _keyEventClazz.getDeclaredField(vkString);
+            int value = field.getInt(null);
+            return value;
+        } catch (Exception e) {
         }
         return 0;
     }
--- a/jdk/src/share/classes/sun/print/resources/serviceui.properties	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/src/share/classes/sun/print/resources/serviceui.properties	Wed Jul 05 18:10:27 2017 +0200
@@ -14,15 +14,11 @@
 button.cancel=Cancel
 button.ok=OK
 button.print=Print
-button.properties=Properties...
-button.properties.mnemonic=R
+button.properties=P&roperties...
 #
-checkbox.collate=Collate
-checkbox.collate.mnemonic=C
-checkbox.jobsheets=Banner Page
-checkbox.jobsheets.mnemonic=B
-checkbox.printtofile=Print To File
-checkbox.printtofile.mnemonic=F
+checkbox.collate=&Collate
+checkbox.jobsheets=&Banner Page
+checkbox.printtofile=Print To &File
 #
 dialog.printtitle=Print
 dialog.pstitle=Page Setup
@@ -33,70 +29,42 @@
 dialog.writeerror=Cannot write to file:
 #
 label.info=Info:
-label.jobname=Job Name:
-label.jobname.mnemonic=J
-label.numcopies=Number of copies:
-label.numcopies.mnemonic=O
-label.priority=Priority:
-label.priority.mnemonic=R
-label.psname=Name:
-label.psname.mnemonic=N
+label.jobname=&Job Name:
+label.numcopies=Number &of copies:
+label.priority=P&riority:
+label.psname=&Name:
 label.pstype=Type:
 label.rangeto=To
-label.size=Size:
-label.size.mnemonic=Z
-label.source=Source:
-label.source.mnemonic=C
+label.size=Si&ze:
+label.source=Sour&ce:
 label.status=Status:
-label.username=User Name:
-label.username.mnemonic=U
+label.username=&User Name:
 label.millimetres=(mm)
 label.inches=(in)
-label.topmargin=top
-label.topmargin.mnemonic=T
-label.bottommargin=bottom
-label.bottommargin.mnemonic=B
-label.leftmargin=left
-label.leftmargin.mnemonic=F
-label.rightmargin=right
-label.rightmargin.mnemonic=R
+label.topmargin=&top
+label.bottommargin=&bottom
+label.leftmargin=le&ft
+label.rightmargin=&right
 #
-radiobutton.color=Color
-radiobutton.color.mnemonic=C
-radiobutton.draftq=Draft
-radiobutton.draftq.mnemonic=F
-radiobutton.duplex=Duplex
-radiobutton.duplex.mnemonic=D
-radiobutton.highq=High
-radiobutton.highq.mnemonic=H
-radiobutton.landscape=Landscape
-radiobutton.landscape.mnemonic=L
-radiobutton.monochrome=Monochrome
-radiobutton.monochrome.mnemonic=M
-radiobutton.normalq=Normal
-radiobutton.normalq.mnemonic=N
-radiobutton.oneside=One Side
-radiobutton.oneside.mnemonic=O
-radiobutton.portrait=Portrait
-radiobutton.portrait.mnemonic=P
-radiobutton.rangeall=All
-radiobutton.rangeall.mnemonic=L
-radiobutton.rangepages=Pages
-radiobutton.rangepages.mnemonic=E
-radiobutton.revlandscape=Reverse Landscape
-radiobutton.revlandscape.mnemonic=N
-radiobutton.revportrait=Reverse Portrait
-radiobutton.revportrait.mnemonic=I
-radiobutton.tumble=Tumble
-radiobutton.tumble.mnemonic=T
+radiobutton.color=&Color
+radiobutton.draftq=Dra&ft
+radiobutton.duplex=&Duplex
+radiobutton.highq=&High
+radiobutton.landscape=&Landscape
+radiobutton.monochrome=&Monochrome
+radiobutton.normalq=&Normal
+radiobutton.oneside=&One Side
+radiobutton.portrait=&Portrait
+radiobutton.rangeall=A&ll
+radiobutton.rangepages=Pag&es
+radiobutton.revlandscape=Reverse La&ndscape
+radiobutton.revportrait=Reverse Portra&it
+radiobutton.tumble=&Tumble
 # The vkMnemonics correspond with the constants defined in KeyEvent, eg
 # 65 = KeyEvent.VK_A
-tab.appearance=Appearance
-tab.appearance.vkMnemonic=65
-tab.general=General
-tab.general.vkMnemonic=71
-tab.pagesetup=Page Setup
-tab.pagesetup.vkMnemonic=83
+tab.appearance=&Appearance
+tab.general=&General
+tab.pagesetup=Page &Setup
 #
 error.pagerange=Invalid page range; please re-enter values (e.g. 1-3,5,7-10)
 error.destination=Invalid filename; please try again
--- a/jdk/src/share/classes/sun/print/resources/serviceui_de.properties	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/src/share/classes/sun/print/resources/serviceui_de.properties	Wed Jul 05 18:10:27 2017 +0200
@@ -14,15 +14,11 @@
 button.cancel=Abbrechen
 button.ok=OK
 button.print=Drucken
-button.properties=Eigenschaften...
-button.properties.mnemonic=I
+button.properties=E&igenschaften...
 #
-checkbox.collate=Sortieren
-checkbox.collate.mnemonic=R
-checkbox.jobsheets=Bannerseite
-checkbox.jobsheets.mnemonic=B
-checkbox.printtofile=Ausgabe in Datei
-checkbox.printtofile.mnemonic=U
+checkbox.collate=So&rtieren
+checkbox.jobsheets=&Bannerseite
+checkbox.printtofile=A&usgabe in Datei
 #
 dialog.printtitle=Drucken
 dialog.pstitle=Seite einrichten
@@ -33,70 +29,42 @@
 dialog.writeerror=Schreiben in Datei nicht m\u00F6glich:
 #
 label.info=Info:
-label.jobname=Job-Name:
-label.jobname.mnemonic=J
-label.numcopies=Anzahl Kopien:
-label.numcopies.mnemonic=K
-label.priority=Priorit\u00E4t:
-label.priority.mnemonic=R
-label.psname=Name:
-label.psname.mnemonic=N
+label.jobname=&Job-Name:
+label.numcopies=Anzahl &Kopien:
+label.priority=P&riorit\u00E4t:
+label.psname=&Name:
 label.pstype=Typ:
 label.rangeto=Bis
-label.size=Gr\u00F6\u00DFe:
-label.size.mnemonic=E
-label.source=Quelle:
-label.source.mnemonic=U
+label.size=Gr\u00F6\u00DF&e:
+label.source=Q&uelle:
 label.status=Status:
-label.username=Benutzername:
-label.username.mnemonic=U
+label.username=Ben&utzername:
 label.millimetres=(mm)
 label.inches=(Zoll)
-label.topmargin=oben
-label.topmargin.mnemonic=O
-label.bottommargin=unten
-label.bottommargin.mnemonic=N
-label.leftmargin=links
-label.leftmargin.mnemonic=L
-label.rightmargin=rechts
-label.rightmargin.mnemonic=R
+label.topmargin=&oben
+label.bottommargin=u&nten
+label.leftmargin=&links
+label.rightmargin=&rechts
 #
-radiobutton.color=Farbe
-radiobutton.color.mnemonic=F
-radiobutton.draftq=Entwurf
-radiobutton.draftq.mnemonic=W
-radiobutton.duplex=Duplex
-radiobutton.duplex.mnemonic=P
-radiobutton.highq=Hoch
-radiobutton.highq.mnemonic=H
-radiobutton.landscape=Querformat
-radiobutton.landscape.mnemonic=Q
-radiobutton.monochrome=Monochrom
-radiobutton.monochrome.mnemonic=M
-radiobutton.normalq=Normal
-radiobutton.normalq.mnemonic=N
-radiobutton.oneside=Einseitig
-radiobutton.oneside.mnemonic=E
-radiobutton.portrait=Hochformat
-radiobutton.portrait.mnemonic=H
-radiobutton.rangeall=Alle
-radiobutton.rangeall.mnemonic=L
-radiobutton.rangepages=Seiten
-radiobutton.rangepages.mnemonic=E
-radiobutton.revlandscape=Umgekehrtes Querformat
-radiobutton.revlandscape.mnemonic=M
-radiobutton.revportrait=Umgekehrtes Hochformat
-radiobutton.revportrait.mnemonic=K
-radiobutton.tumble=Kalenderdruck
-radiobutton.tumble.mnemonic=K
+radiobutton.color=&Farbe
+radiobutton.draftq=Ent&wurf
+radiobutton.duplex=Du&plex
+radiobutton.highq=&Hoch
+radiobutton.landscape=&Querformat
+radiobutton.monochrome=&Monochrom
+radiobutton.normalq=&Normal
+radiobutton.oneside=&Einseitig
+radiobutton.portrait=&Hochformat
+radiobutton.rangeall=A&lle
+radiobutton.rangepages=S&eiten
+radiobutton.revlandscape=U&mgekehrtes Querformat
+radiobutton.revportrait=Umge&kehrtes Hochformat
+radiobutton.tumble=&Kalenderdruck
 # The vkMnemonics correspond with the constants defined in KeyEvent, eg
 # 65 = KeyEvent.VK_A
-tab.appearance=Darstellung
-tab.appearance.vkMnemonic=68
-tab.general=Allgemein
-tab.general.vkMnemonic=65
-tab.pagesetup=Seite einrichten
-tab.pagesetup.vkMnemonic=83
+tab.appearance=&Darstellung
+tab.general=&Allgemein
+tab.pagesetup=&Seite einrichten
 #
 error.pagerange=Ung\u00FCltiger Seitenbereich. Geben Sie die Werte erneut ein (Beispiel: 1-3,5,7-10)
 error.destination=Ung\u00FCltiger Dateiname. Wiederholen Sie den Vorgang
--- a/jdk/src/share/classes/sun/print/resources/serviceui_es.properties	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/src/share/classes/sun/print/resources/serviceui_es.properties	Wed Jul 05 18:10:27 2017 +0200
@@ -14,15 +14,11 @@
 button.cancel=Cancelar
 button.ok=Aceptar
 button.print=Imprimir
-button.properties=Propiedades...
-button.properties.mnemonic=R
+button.properties=P&ropiedades...
 #
-checkbox.collate=Intercalar
-checkbox.collate.mnemonic=C
-checkbox.jobsheets=P\u00E1gina de R\u00F3tulo
-checkbox.jobsheets.mnemonic=E
-checkbox.printtofile=Imprimir en Archivo
-checkbox.printtofile.mnemonic=M
+checkbox.collate=Inter&calar
+checkbox.jobsheets=P\u00E1gina d&e R\u00F3tulo
+checkbox.printtofile=I&mprimir en Archivo
 #
 dialog.printtitle=Imprimir
 dialog.pstitle=Preparar P\u00E1gina
@@ -33,70 +29,42 @@
 dialog.writeerror=No se puede escribir en el archivo:
 #
 label.info=Informaci\u00F3n:
-label.jobname=Nombre del Trabajo:
-label.jobname.mnemonic=T
-label.numcopies=N\u00FAmero de Copias:
-label.numcopies.mnemonic=O
-label.priority=Prioridad:
-label.priority.mnemonic=I
-label.psname=Nombre:
-label.psname.mnemonic=N
+label.jobname=Nombre del &Trabajo:
+label.numcopies=N\u00FAmer&o de Copias:
+label.priority=Pr&ioridad:
+label.psname=&Nombre:
 label.pstype=Tipo:
 label.rangeto=A
-label.size=Tama\u00F1o:
-label.size.mnemonic=T
+label.size=&Tama\u00F1o:
 label.source=Origen:
-label.source.mnemonic=O
 label.status=Estado:
-label.username=Usuario:
-label.username.mnemonic=S
+label.username=U&suario:
 label.millimetres=(mm)
 label.inches=(pulg.)
 label.topmargin=superior
-label.topmargin.mnemonic=S
-label.bottommargin=inferior
-label.bottommargin.mnemonic=F
-label.leftmargin=izquierdo
-label.leftmargin.mnemonic=Q
-label.rightmargin=derecho
-label.rightmargin.mnemonic=E
+label.bottommargin=in&ferior
+label.leftmargin=iz&quierdo
+label.rightmargin=d&erecho
 #
-radiobutton.color=Color
-radiobutton.color.mnemonic=C
-radiobutton.draftq=Borrador
-radiobutton.draftq.mnemonic=R
-radiobutton.duplex=D\u00FAplex
-radiobutton.duplex.mnemonic=D
-radiobutton.highq=Alta
-radiobutton.highq.mnemonic=L
-radiobutton.landscape=Horizontal
-radiobutton.landscape.mnemonic=Z
-radiobutton.monochrome=Monocromo
-radiobutton.monochrome.mnemonic=M
-radiobutton.normalq=Normal
-radiobutton.normalq.mnemonic=N
-radiobutton.oneside=Una Cara
-radiobutton.oneside.mnemonic=U
-radiobutton.portrait=Vertical
-radiobutton.portrait.mnemonic=V
-radiobutton.rangeall=Todo
-radiobutton.rangeall.mnemonic=T
-radiobutton.rangepages=P\u00E1ginas
-radiobutton.rangepages.mnemonic=G
-radiobutton.revlandscape=Horizontal Inverso
-radiobutton.revlandscape.mnemonic=H
-radiobutton.revportrait=Vertical Inverso
-radiobutton.revportrait.mnemonic=R
-radiobutton.tumble=Cambio de Cara
-radiobutton.tumble.mnemonic=B
+radiobutton.color=&Color
+radiobutton.draftq=Bo&rrador
+radiobutton.duplex=&D\u00FAplex
+radiobutton.highq=A&lta
+radiobutton.landscape=Hori&zontal
+radiobutton.monochrome=&Monocromo
+radiobutton.normalq=&Normal
+radiobutton.oneside=&Una Cara
+radiobutton.portrait=&Vertical
+radiobutton.rangeall=&Todo
+radiobutton.rangepages=P\u00E1&ginas
+radiobutton.revlandscape=&Horizontal Inverso
+radiobutton.revportrait=Ve&rtical Inverso
+radiobutton.tumble=Cam&bio de Cara
 # The vkMnemonics correspond with the constants defined in KeyEvent, eg
 # 65 = KeyEvent.VK_A
-tab.appearance=Apariencia
-tab.appearance.vkMnemonic=65
-tab.general=General
-tab.general.vkMnemonic=71
-tab.pagesetup=Preparar P\u00E1gina
-tab.pagesetup.vkMnemonic=80
+tab.appearance=&Apariencia
+tab.general=&General
+tab.pagesetup=&Preparar P\u00E1gina
 #
 error.pagerange=Rango de p\u00E1ginas no v\u00E1lido; vuelva a introducir los valores (por ejemplo, 1-3, 5, 7-10)
 error.destination=Nombre de archivo no v\u00E1lido; int\u00E9ntelo de nuevo
--- a/jdk/src/share/classes/sun/print/resources/serviceui_fr.properties	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/src/share/classes/sun/print/resources/serviceui_fr.properties	Wed Jul 05 18:10:27 2017 +0200
@@ -14,15 +14,11 @@
 button.cancel=Annuler
 button.ok=OK
 button.print=Imprimer
-button.properties=Propri\u00E9t\u00E9s...
-button.properties.mnemonic=R
+button.properties=P&ropri\u00E9t\u00E9s...
 #
-checkbox.collate=Collationner
-checkbox.collate.mnemonic=C
-checkbox.jobsheets=Page de banni\u00E8re
-checkbox.jobsheets.mnemonic=B
-checkbox.printtofile=Imprimer dans un fichier
-checkbox.printtofile.mnemonic=F
+checkbox.collate=&Collationner
+checkbox.jobsheets=Page de &banni\u00E8re
+checkbox.printtofile=Imprimer dans un &fichier
 #
 dialog.printtitle=Imprimer
 dialog.pstitle=Mise en page
@@ -33,70 +29,42 @@
 dialog.writeerror=Impossible d'\u00E9crire dans le fichier :
 #
 label.info=Infos :
-label.jobname=Nom du travail :
-label.jobname.mnemonic=T
-label.numcopies=Nombre de copies :
-label.numcopies.mnemonic=O
-label.priority=Priorit\u00E9 :
-label.priority.mnemonic=R
-label.psname=Nom :
-label.psname.mnemonic=N
+label.jobname=Nom du &travail :
+label.numcopies=N&ombre de copies :
+label.priority=P&riorit\u00E9 :
+label.psname=&Nom :
 label.pstype=Type :
 label.rangeto=A
-label.size=Taille :
-label.size.mnemonic=L
-label.source=Source :
-label.source.mnemonic=C
+label.size=Tai&lle :
+label.source=Sour&ce :
 label.status=Statut :
-label.username=Nom utilisateur :
-label.username.mnemonic=O
+label.username=N&om utilisateur :
 label.millimetres=(mm)
 label.inches=(po)
-label.topmargin=haut
-label.topmargin.mnemonic=H
-label.bottommargin=bas
-label.bottommargin.mnemonic=B
-label.leftmargin=gauche
-label.leftmargin.mnemonic=G
-label.rightmargin=droite
-label.rightmargin.mnemonic=D
+label.topmargin=&haut
+label.bottommargin=&bas
+label.leftmargin=&gauche
+label.rightmargin=&droite
 #
-radiobutton.color=Couleur
-radiobutton.color.mnemonic=C
-radiobutton.draftq=Brouillon
-radiobutton.draftq.mnemonic=L
-radiobutton.duplex=Duplex
-radiobutton.duplex.mnemonic=D
-radiobutton.highq=Max.
-radiobutton.highq.mnemonic=X
-radiobutton.landscape=Paysage
-radiobutton.landscape.mnemonic=Y
-radiobutton.monochrome=Monochrome
-radiobutton.monochrome.mnemonic=M
-radiobutton.normalq=Normal
-radiobutton.normalq.mnemonic=N
-radiobutton.oneside=Un c\u00F4t\u00E9
-radiobutton.oneside.mnemonic=U
-radiobutton.portrait=Portrait
-radiobutton.portrait.mnemonic=P
-radiobutton.rangeall=Tout
-radiobutton.rangeall.mnemonic=T
-radiobutton.rangepages=Pages
-radiobutton.rangepages.mnemonic=E
-radiobutton.revlandscape=Paysage invers\u00E9
-radiobutton.revlandscape.mnemonic=N
-radiobutton.revportrait=Portrait invers\u00E9
-radiobutton.revportrait.mnemonic=I
-radiobutton.tumble=T\u00EAte-b\u00EAche
-radiobutton.tumble.mnemonic=T
+radiobutton.color=&Couleur
+radiobutton.draftq=Broui&llon
+radiobutton.duplex=&Duplex
+radiobutton.highq=Ma&x.
+radiobutton.landscape=Pa&ysage
+radiobutton.monochrome=&Monochrome
+radiobutton.normalq=&Normal
+radiobutton.oneside=&Un c\u00F4t\u00E9
+radiobutton.portrait=&Portrait
+radiobutton.rangeall=&Tout
+radiobutton.rangepages=Pag&es
+radiobutton.revlandscape=Paysage i&nvers\u00E9
+radiobutton.revportrait=Portra&it invers\u00E9
+radiobutton.tumble=&T\u00EAte-b\u00EAche
 # The vkMnemonics correspond with the constants defined in KeyEvent, eg
 # 65 = KeyEvent.VK_A
-tab.appearance=Apparence
-tab.appearance.vkMnemonic=65
-tab.general=G\u00E9n\u00E9ral
-tab.general.vkMnemonic=71
-tab.pagesetup=Mise en page
-tab.pagesetup.vkMnemonic=83
+tab.appearance=&Apparence
+tab.general=&G\u00E9n\u00E9ral
+tab.pagesetup=Mi&se en page
 #
 error.pagerange=Plage de pages non valide. Sp\u00E9cifiez les valeurs de nouveau (ex. : 1-3,5,7-10)
 error.destination=Nom de fichier non valide ; recommencez
--- a/jdk/src/share/classes/sun/print/resources/serviceui_it.properties	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/src/share/classes/sun/print/resources/serviceui_it.properties	Wed Jul 05 18:10:27 2017 +0200
@@ -14,15 +14,11 @@
 button.cancel=Annulla
 button.ok=OK
 button.print=Stampa
-button.properties=Propriet\u00E0...
-button.properties.mnemonic=R
+button.properties=P&ropriet\u00E0...
 #
-checkbox.collate=Fascicola
-checkbox.collate.mnemonic=L
-checkbox.jobsheets=Pagina banner
-checkbox.jobsheets.mnemonic=P
-checkbox.printtofile=Stampa su file
-checkbox.printtofile.mnemonic=F
+checkbox.collate=Fascico&la
+checkbox.jobsheets=&Pagina banner
+checkbox.printtofile=Stampa su &file
 #
 dialog.printtitle=Stampa
 dialog.pstitle=Imposta pagina
@@ -33,70 +29,42 @@
 dialog.writeerror=Impossibile scrivere nel file:
 #
 label.info=Informazioni:
-label.jobname=Nome job:
-label.jobname.mnemonic=J
-label.numcopies=Numero di copie:
-label.numcopies.mnemonic=O
-label.priority=Priorit\u00E0:
-label.priority.mnemonic=I
-label.psname=Nome:
-label.psname.mnemonic=N
+label.jobname=Nome &job:
+label.numcopies=Numer&o di copie:
+label.priority=Pr&iorit\u00E0:
+label.psname=&Nome:
 label.pstype=Tipo:
 label.rangeto=A
-label.size=Dimensioni:
-label.size.mnemonic=M
-label.source=Origine:
-label.source.mnemonic=R
+label.size=Di&mensioni:
+label.source=O&rigine:
 label.status=Stato:
-label.username=Nome utente:
-label.username.mnemonic=U
+label.username=Nome &utente:
 label.millimetres=(mm)
 label.inches=(poll.)
-label.topmargin=superiore
-label.topmargin.mnemonic=P
-label.bottommargin=inferiore
-label.bottommargin.mnemonic=F
-label.leftmargin=sinistro
-label.leftmargin.mnemonic=T
-label.rightmargin=destro
-label.rightmargin.mnemonic=D
+label.topmargin=su&periore
+label.bottommargin=in&feriore
+label.leftmargin=sinis&tro
+label.rightmargin=&destro
 #
-radiobutton.color=Colore
-radiobutton.color.mnemonic=C
-radiobutton.draftq=Bozza
-radiobutton.draftq.mnemonic=B
-radiobutton.duplex=Fronte retro
-radiobutton.duplex.mnemonic=R
-radiobutton.highq=Alta
-radiobutton.highq.mnemonic=L
-radiobutton.landscape=Orizzontale
-radiobutton.landscape.mnemonic=L
-radiobutton.monochrome=Monocromatico
-radiobutton.monochrome.mnemonic=M
-radiobutton.normalq=Normale
-radiobutton.normalq.mnemonic=N
-radiobutton.oneside=Un lato
-radiobutton.oneside.mnemonic=O
-radiobutton.portrait=Verticale
-radiobutton.portrait.mnemonic=V
-radiobutton.rangeall=Tutto
-radiobutton.rangeall.mnemonic=U
-radiobutton.rangepages=Pagine
-radiobutton.rangepages.mnemonic=E
-radiobutton.revlandscape=Orizzontale capovolto
-radiobutton.revlandscape.mnemonic=N
-radiobutton.revportrait=Verticale capovolto
-radiobutton.revportrait.mnemonic=I
-radiobutton.tumble=Lato corto
-radiobutton.tumble.mnemonic=T
+radiobutton.color=&Colore
+radiobutton.draftq=&Bozza
+radiobutton.duplex=F&ronte retro
+radiobutton.highq=A&lta
+radiobutton.landscape=Orizzonta&le
+radiobutton.monochrome=&Monocromatico
+radiobutton.normalq=&Normale
+radiobutton.oneside=Un lat&o
+radiobutton.portrait=&Verticale
+radiobutton.rangeall=T&utto
+radiobutton.rangepages=Pagin&e
+radiobutton.revlandscape=Orizzo&ntale capovolto
+radiobutton.revportrait=Vert&icale capovolto
+radiobutton.tumble=La&to corto
 # The vkMnemonics correspond with the constants defined in KeyEvent, eg
 # 65 = KeyEvent.VK_A
-tab.appearance=Aspetto
-tab.appearance.vkMnemonic=65
-tab.general=Generale
-tab.general.vkMnemonic=71
-tab.pagesetup=Imposta pagina
-tab.pagesetup.vkMnemonic=83
+tab.appearance=&Aspetto
+tab.general=&Generale
+tab.pagesetup=Impo&sta pagina
 #
 error.pagerange=Intervallo pagine non valido; immettere nuovamente i valori (ad es. 1-3,5,7-10)
 error.destination=Nome file non valido; riprovare
--- a/jdk/src/share/classes/sun/print/resources/serviceui_ja.properties	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/src/share/classes/sun/print/resources/serviceui_ja.properties	Wed Jul 05 18:10:27 2017 +0200
@@ -14,15 +14,11 @@
 button.cancel=\u53D6\u6D88
 button.ok=OK
 button.print=\u5370\u5237
-button.properties=\u30D7\u30ED\u30D1\u30C6\u30A3(R)...
-button.properties.mnemonic=R
+button.properties=\u30D7\u30ED\u30D1\u30C6\u30A3(&R)...
 #
-checkbox.collate=\u4E01\u5408\u3044(C)
-checkbox.collate.mnemonic=C
-checkbox.jobsheets=\u30D0\u30CA\u30FC\u30FB\u30DA\u30FC\u30B8(B)
-checkbox.jobsheets.mnemonic=B
-checkbox.printtofile=\u30D5\u30A1\u30A4\u30EB\u306B\u51FA\u529B(F)
-checkbox.printtofile.mnemonic=F
+checkbox.collate=\u4E01\u5408\u3044(&C)
+checkbox.jobsheets=\u30D0\u30CA\u30FC\u30FB\u30DA\u30FC\u30B8(&B)
+checkbox.printtofile=\u30D5\u30A1\u30A4\u30EB\u306B\u51FA\u529B(&F)
 #
 dialog.printtitle=\u5370\u5237
 dialog.pstitle=\u30DA\u30FC\u30B8\u8A2D\u5B9A
@@ -33,70 +29,42 @@
 dialog.writeerror=\u30D5\u30A1\u30A4\u30EB\u306B\u66F8\u304D\u8FBC\u3081\u307E\u305B\u3093:
 #
 label.info=\u60C5\u5831:
-label.jobname=\u30B8\u30E7\u30D6\u540D(J):
-label.jobname.mnemonic=J
-label.numcopies=\u5370\u5237\u90E8\u6570(O):
-label.numcopies.mnemonic=O
-label.priority=\u512A\u5148\u5EA6(R):
-label.priority.mnemonic=R
-label.psname=\u540D\u524D(N):
-label.psname.mnemonic=N
+label.jobname=\u30B8\u30E7\u30D6\u540D(&J):
+label.numcopies=\u5370\u5237\u90E8\u6570(&O):
+label.priority=\u512A\u5148\u5EA6(&R):
+label.psname=\u540D\u524D(&N):
 label.pstype=\u30BF\u30A4\u30D7:
 label.rangeto=\u5370\u5237\u7BC4\u56F2
-label.size=\u30B5\u30A4\u30BA(Z):
-label.size.mnemonic=Z
-label.source=\u30BD\u30FC\u30B9(C):
-label.source.mnemonic=C
+label.size=\u30B5\u30A4\u30BA(&Z):
+label.source=\u30BD\u30FC\u30B9(&C):
 label.status=\u72B6\u614B:
-label.username=\u30E6\u30FC\u30B6\u30FC\u540D(U):
-label.username.mnemonic=U
+label.username=\u30E6\u30FC\u30B6\u30FC\u540D(&U):
 label.millimetres=(mm)
 label.inches=(in)
-label.topmargin=\u4E0A(T)
-label.topmargin.mnemonic=T
-label.bottommargin=\u4E0B(B)
-label.bottommargin.mnemonic=B
-label.leftmargin=\u5DE6(F)
-label.leftmargin.mnemonic=F
-label.rightmargin=\u53F3(R)
-label.rightmargin.mnemonic=R
+label.topmargin=\u4E0A(&T)
+label.bottommargin=\u4E0B(&B)
+label.leftmargin=\u5DE6(&F)
+label.rightmargin=\u53F3(&R)
 #
-radiobutton.color=\u30AB\u30E9\u30FC(C)
-radiobutton.color.mnemonic=C
-radiobutton.draftq=\u30C9\u30E9\u30D5\u30C8(F)
-radiobutton.draftq.mnemonic=F
-radiobutton.duplex=\u4E21\u9762(D)
-radiobutton.duplex.mnemonic=D
-radiobutton.highq=\u9AD8(H)
-radiobutton.highq.mnemonic=H
-radiobutton.landscape=\u6A2A(L)
-radiobutton.landscape.mnemonic=L
-radiobutton.monochrome=\u30E2\u30CE\u30AF\u30ED(M)
-radiobutton.monochrome.mnemonic=M
-radiobutton.normalq=\u6A19\u6E96(N)
-radiobutton.normalq.mnemonic=N
-radiobutton.oneside=\u7247\u9762(O)
-radiobutton.oneside.mnemonic=O
-radiobutton.portrait=\u7E26(P)
-radiobutton.portrait.mnemonic=P
-radiobutton.rangeall=\u3059\u3079\u3066(L)
-radiobutton.rangeall.mnemonic=L
-radiobutton.rangepages=\u30DA\u30FC\u30B8(E)
-radiobutton.rangepages.mnemonic=E
-radiobutton.revlandscape=\u30E9\u30F3\u30C9\u30B9\u30B1\u30FC\u30D7(\u53CD\u8EE2)(N)
-radiobutton.revlandscape.mnemonic=N
-radiobutton.revportrait=\u30DD\u30FC\u30C8\u30EC\u30A4\u30C8(\u53CD\u8EE2)(I)
-radiobutton.revportrait.mnemonic=I
-radiobutton.tumble=\u53CD\u8EE2(T)
-radiobutton.tumble.mnemonic=T
+radiobutton.color=\u30AB\u30E9\u30FC(&C)
+radiobutton.draftq=\u30C9\u30E9\u30D5\u30C8(&F)
+radiobutton.duplex=\u4E21\u9762(&D)
+radiobutton.highq=\u9AD8(&H)
+radiobutton.landscape=\u6A2A(&L)
+radiobutton.monochrome=\u30E2\u30CE\u30AF\u30ED(&M)
+radiobutton.normalq=\u6A19\u6E96(&N)
+radiobutton.oneside=\u7247\u9762(&O)
+radiobutton.portrait=\u7E26(&P)
+radiobutton.rangeall=\u3059\u3079\u3066(&L)
+radiobutton.rangepages=\u30DA\u30FC\u30B8(&E)
+radiobutton.revlandscape=\u30E9\u30F3\u30C9\u30B9\u30B1\u30FC\u30D7(\u53CD\u8EE2)(&N)
+radiobutton.revportrait=\u30DD\u30FC\u30C8\u30EC\u30A4\u30C8(\u53CD\u8EE2)(&I)
+radiobutton.tumble=\u53CD\u8EE2(&T)
 # The vkMnemonics correspond with the constants defined in KeyEvent, eg
 # 65 = KeyEvent.VK_A
-tab.appearance=\u5916\u89B3(A)
-tab.appearance.vkMnemonic=65
-tab.general=\u4E00\u822C(G)
-tab.general.vkMnemonic=71
-tab.pagesetup=\u30DA\u30FC\u30B8\u8A2D\u5B9A(S)
-tab.pagesetup.vkMnemonic=83
+tab.appearance=\u5916\u89B3(&A)
+tab.general=\u4E00\u822C(&G)
+tab.pagesetup=\u30DA\u30FC\u30B8\u8A2D\u5B9A(&S)
 #
 error.pagerange=\u7121\u52B9\u306A\u30DA\u30FC\u30B8\u7BC4\u56F2\u3002\u5024\u3092\u518D\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044(\u4F8B\u30011-3,5,7-10)
 error.destination=\u7121\u52B9\u306A\u30D5\u30A1\u30A4\u30EB\u540D\u3002\u30D5\u30A1\u30A4\u30EB\u540D\u3092\u518D\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044
--- a/jdk/src/share/classes/sun/print/resources/serviceui_ko.properties	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/src/share/classes/sun/print/resources/serviceui_ko.properties	Wed Jul 05 18:10:27 2017 +0200
@@ -14,15 +14,11 @@
 button.cancel=\uCDE8\uC18C
 button.ok=\uD655\uC778
 button.print=\uC778\uC1C4
-button.properties=\uC18D\uC131(R)...
-button.properties.mnemonic=R
+button.properties=\uC18D\uC131(&R)...
 #
-checkbox.collate=\uD55C \uBD80\uC529 \uC778\uC1C4(C)
-checkbox.collate.mnemonic=C
-checkbox.jobsheets=\uBC30\uB108 \uD398\uC774\uC9C0(B)
-checkbox.jobsheets.mnemonic=B
-checkbox.printtofile=\uD30C\uC77C\uB85C \uC778\uC1C4(F)
-checkbox.printtofile.mnemonic=F
+checkbox.collate=\uD55C \uBD80\uC529 \uC778\uC1C4(&C)
+checkbox.jobsheets=\uBC30\uB108 \uD398\uC774\uC9C0(&B)
+checkbox.printtofile=\uD30C\uC77C\uB85C \uC778\uC1C4(&F)
 #
 dialog.printtitle=\uC778\uC1C4
 dialog.pstitle=\uD398\uC774\uC9C0 \uC124\uC815
@@ -33,70 +29,42 @@
 dialog.writeerror=\uD30C\uC77C\uC5D0 \uC4F8 \uC218 \uC5C6\uC74C:
 #
 label.info=\uC815\uBCF4:
-label.jobname=\uC791\uC5C5 \uC774\uB984(J):
-label.jobname.mnemonic=J
-label.numcopies=\uB9E4\uC218(O):
-label.numcopies.mnemonic=O
-label.priority=\uC6B0\uC120\uC21C\uC704(R):
-label.priority.mnemonic=R
-label.psname=\uC774\uB984(N):
-label.psname.mnemonic=N
+label.jobname=\uC791\uC5C5 \uC774\uB984(&J):
+label.numcopies=\uB9E4\uC218(&O):
+label.priority=\uC6B0\uC120\uC21C\uC704(&R):
+label.psname=\uC774\uB984(&N):
 label.pstype=\uC720\uD615:
 label.rangeto=\uC885\uB8CC
-label.size=\uD06C\uAE30(Z):
-label.size.mnemonic=Z
-label.source=\uC18C\uC2A4(C):
-label.source.mnemonic=C
+label.size=\uD06C\uAE30(&Z):
+label.source=\uC18C\uC2A4(&C):
 label.status=\uC0C1\uD0DC:
-label.username=\uC0AC\uC6A9\uC790 \uC774\uB984(U):
-label.username.mnemonic=U
+label.username=\uC0AC\uC6A9\uC790 \uC774\uB984(&U):
 label.millimetres=(mm)
 label.inches=(\uC778\uCE58)
-label.topmargin=\uC704\uCABD(T)
-label.topmargin.mnemonic=T
-label.bottommargin=\uC544\uB798\uCABD(B)
-label.bottommargin.mnemonic=B
-label.leftmargin=\uC67C\uCABD(F)
-label.leftmargin.mnemonic=F
-label.rightmargin=\uC624\uB978\uCABD(R)
-label.rightmargin.mnemonic=R
+label.topmargin=\uC704\uCABD(&T)
+label.bottommargin=\uC544\uB798\uCABD(&B)
+label.leftmargin=\uC67C\uCABD(&F)
+label.rightmargin=\uC624\uB978\uCABD(&R)
 #
-radiobutton.color=\uC0C9\uC0C1(C)
-radiobutton.color.mnemonic=C
-radiobutton.draftq=\uCD08\uC548(F)
-radiobutton.draftq.mnemonic=F
-radiobutton.duplex=\uC591\uBA74(D)
-radiobutton.duplex.mnemonic=D
-radiobutton.highq=\uB192\uC74C(H)
-radiobutton.highq.mnemonic=H
-radiobutton.landscape=\uAC00\uB85C(L)
-radiobutton.landscape.mnemonic=L
-radiobutton.monochrome=\uB2E8\uC0C9(M)
-radiobutton.monochrome.mnemonic=M
-radiobutton.normalq=\uBCF4\uD1B5(N)
-radiobutton.normalq.mnemonic=N
-radiobutton.oneside=\uB2E8\uBA74(O)
-radiobutton.oneside.mnemonic=O
-radiobutton.portrait=\uC138\uB85C(P)
-radiobutton.portrait.mnemonic=P
-radiobutton.rangeall=\uC804\uCCB4(L)
-radiobutton.rangeall.mnemonic=L
-radiobutton.rangepages=\uD398\uC774\uC9C0(E)
-radiobutton.rangepages.mnemonic=E
-radiobutton.revlandscape=\uAC00\uB85C \uBC18\uC804(N)
-radiobutton.revlandscape.mnemonic=N
-radiobutton.revportrait=\uC138\uB85C \uBC18\uC804(I)
-radiobutton.revportrait.mnemonic=I
-radiobutton.tumble=\uD68C\uC804\uC2DD(T)
-radiobutton.tumble.mnemonic=T
+radiobutton.color=\uC0C9\uC0C1(&C)
+radiobutton.draftq=\uCD08\uC548(&F)
+radiobutton.duplex=\uC591\uBA74(&D)
+radiobutton.highq=\uB192\uC74C(&H)
+radiobutton.landscape=\uAC00\uB85C(&L)
+radiobutton.monochrome=\uB2E8\uC0C9(&M)
+radiobutton.normalq=\uBCF4\uD1B5(&N)
+radiobutton.oneside=\uB2E8\uBA74(&O)
+radiobutton.portrait=\uC138\uB85C(&P)
+radiobutton.rangeall=\uC804\uCCB4(&L)
+radiobutton.rangepages=\uD398\uC774\uC9C0(&E)
+radiobutton.revlandscape=\uAC00\uB85C \uBC18\uC804(&N)
+radiobutton.revportrait=\uC138\uB85C \uBC18\uC804(&I)
+radiobutton.tumble=\uD68C\uC804\uC2DD(&T)
 # The vkMnemonics correspond with the constants defined in KeyEvent, eg
 # 65 = KeyEvent.VK_A
-tab.appearance=\uBAA8\uC591(A)
-tab.appearance.vkMnemonic=65
-tab.general=\uC77C\uBC18 \uC0AC\uD56D(G)
-tab.general.vkMnemonic=71
-tab.pagesetup=\uD398\uC774\uC9C0 \uC124\uC815(S)
-tab.pagesetup.vkMnemonic=83
+tab.appearance=\uBAA8\uC591(&A)
+tab.general=\uC77C\uBC18 \uC0AC\uD56D(&G)
+tab.pagesetup=\uD398\uC774\uC9C0 \uC124\uC815(&S)
 #
 error.pagerange=\uBD80\uC801\uD569\uD55C \uD398\uC774\uC9C0 \uBC94\uC704: \uAC12\uC744 \uB2E4\uC2DC \uC785\uB825\uD558\uC2ED\uC2DC\uC624(\uC608: 1-3,5,7-10).
 error.destination=\uBD80\uC801\uD569\uD55C \uD30C\uC77C \uC774\uB984: \uB2E4\uC2DC \uC2DC\uB3C4\uD558\uC2ED\uC2DC\uC624.
--- a/jdk/src/share/classes/sun/print/resources/serviceui_pt_BR.properties	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/src/share/classes/sun/print/resources/serviceui_pt_BR.properties	Wed Jul 05 18:10:27 2017 +0200
@@ -14,15 +14,11 @@
 button.cancel=Cancelar
 button.ok=OK
 button.print=Imprimir
-button.properties=Propriedades...
-button.properties.mnemonic=D
+button.properties=Proprie&dades...
 #
-checkbox.collate=Agrupar
-checkbox.collate.mnemonic=R
-checkbox.jobsheets=P\u00E1gina com Banner
-checkbox.jobsheets.mnemonic=B
-checkbox.printtofile=Imprimir em Arquivo
-checkbox.printtofile.mnemonic=I
+checkbox.collate=Ag&rupar
+checkbox.jobsheets=P\u00E1gina com &Banner
+checkbox.printtofile=&Imprimir em Arquivo
 #
 dialog.printtitle=Imprimir
 dialog.pstitle=Configura\u00E7\u00E3o da P\u00E1gina
@@ -33,70 +29,42 @@
 dialog.writeerror=N\u00E3o \u00E9 poss\u00EDvel gravar no arquivo:
 #
 label.info=Informa\u00E7\u00F5es:
-label.jobname=Nome do Job:
-label.jobname.mnemonic=J
-label.numcopies=N\u00FAmero de c\u00F3pias:
-label.numcopies.mnemonic=O
-label.priority=Prioridade:
-label.priority.mnemonic=P
-label.psname=Nome:
-label.psname.mnemonic=N
+label.jobname=Nome do &Job:
+label.numcopies=N\u00FAmer&o de c\u00F3pias:
+label.priority=&Prioridade:
+label.psname=&Nome:
 label.pstype=Tipo:
 label.rangeto=At\u00E9
-label.size=Tamanho:
-label.size.mnemonic=M
-label.source=Origem:
-label.source.mnemonic=O
+label.size=Ta&manho:
+label.source=&Origem:
 label.status=Status:
-label.username=Nome do Usu\u00E1rio:
-label.username.mnemonic=U
+label.username=Nome do &Usu\u00E1rio:
 label.millimetres=(mm)
 label.inches=(pol)
-label.topmargin=superior
-label.topmargin.mnemonic=S
-label.bottommargin=inferior
-label.bottommargin.mnemonic=I
-label.leftmargin=esquerda:
-label.leftmargin.mnemonic=Q
-label.rightmargin=direita
-label.rightmargin.mnemonic=D
+label.topmargin=&superior
+label.bottommargin=&inferior
+label.leftmargin=es&querda:
+label.rightmargin=&direita
 #
-radiobutton.color=Cor
-radiobutton.color.mnemonic=O
-radiobutton.draftq=Rascunho
-radiobutton.draftq.mnemonic=R
-radiobutton.duplex=Duplex
-radiobutton.duplex.mnemonic=D
-radiobutton.highq=Alta
-radiobutton.highq.mnemonic=T
-radiobutton.landscape=Paisagem
-radiobutton.landscape.mnemonic=P
-radiobutton.monochrome=Monocrom\u00E1tico
-radiobutton.monochrome.mnemonic=M
-radiobutton.normalq=Normal
-radiobutton.normalq.mnemonic=N
-radiobutton.oneside=Um Lado
-radiobutton.oneside.mnemonic=L
-radiobutton.portrait=Retrato
-radiobutton.portrait.mnemonic=R
-radiobutton.rangeall=Tudo
-radiobutton.rangeall.mnemonic=U
-radiobutton.rangepages=P\u00E1ginas
-radiobutton.rangepages.mnemonic=P
-radiobutton.revlandscape=Paisagem Invertida
-radiobutton.revlandscape.mnemonic=N
-radiobutton.revportrait=Retrato Invertido
-radiobutton.revportrait.mnemonic=E
-radiobutton.tumble=Virar
-radiobutton.tumble.mnemonic=V
+radiobutton.color=C&or
+radiobutton.draftq=&Rascunho
+radiobutton.duplex=&Duplex
+radiobutton.highq=Al&ta
+radiobutton.landscape=&Paisagem
+radiobutton.monochrome=&Monocrom\u00E1tico
+radiobutton.normalq=&Normal
+radiobutton.oneside=Um &Lado
+radiobutton.portrait=&Retrato
+radiobutton.rangeall=T&udo
+radiobutton.rangepages=&P\u00E1ginas
+radiobutton.revlandscape=Paisagem I&nvertida
+radiobutton.revportrait=R&etrato Invertido
+radiobutton.tumble=&Virar
 # The vkMnemonics correspond with the constants defined in KeyEvent, eg
 # 65 = KeyEvent.VK_A
-tab.appearance=Apar\u00EAncia
-tab.appearance.vkMnemonic=65
-tab.general=Geral
-tab.general.vkMnemonic=71
-tab.pagesetup=Configura\u00E7\u00E3o de P\u00E1gina
-tab.pagesetup.vkMnemonic=67
+tab.appearance=&Apar\u00EAncia
+tab.general=&Geral
+tab.pagesetup=&Configura\u00E7\u00E3o de P\u00E1gina
 #
 error.pagerange=Faixa de p\u00E1ginas inv\u00E1lida; insira novamente os valores (por exemplo, 1-3,5,7-10)
 error.destination=Nome de arquivo inv\u00E1lido; tente novamente
--- a/jdk/src/share/classes/sun/print/resources/serviceui_sv.properties	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/src/share/classes/sun/print/resources/serviceui_sv.properties	Wed Jul 05 18:10:27 2017 +0200
@@ -14,15 +14,11 @@
 button.cancel=Avbryt
 button.ok=OK
 button.print=Skriv ut
-button.properties=Egenskaper...
-button.properties.mnemonic=R
+button.properties=Egenskape&r...
 #
-checkbox.collate=Sortera
-checkbox.collate.mnemonic=T
-checkbox.jobsheets=F\u00F6rs\u00E4ttsblad
-checkbox.jobsheets.mnemonic=R
-checkbox.printtofile=Skriv ut till fil
-checkbox.printtofile.mnemonic=K
+checkbox.collate=Sor&tera
+checkbox.jobsheets=F\u00F6&rs\u00E4ttsblad
+checkbox.printtofile=S&kriv ut till fil
 #
 dialog.printtitle=Skriv ut
 dialog.pstitle=Utskriftsformat
@@ -33,70 +29,42 @@
 dialog.writeerror=Kan inte skriva till filen:
 #
 label.info=Information:
-label.jobname=Utskrift:
-label.jobname.mnemonic=U
-label.numcopies=Antal exemplar:
-label.numcopies.mnemonic=E
-label.priority=Prioritet:
-label.priority.mnemonic=R
-label.psname=Namn:
-label.psname.mnemonic=N
+label.jobname=&Utskrift:
+label.numcopies=Antal &exemplar:
+label.priority=P&rioritet:
+label.psname=&Namn:
 label.pstype=Typ:
 label.rangeto=Till
-label.size=Storlek:
-label.size.mnemonic=O
-label.source=K\u00E4lla:
-label.source.mnemonic=K
+label.size=St&orlek:
+label.source=&K\u00E4lla:
 label.status=Status:
-label.username=Anv\u00E4ndarnamn:
-label.username.mnemonic=N
+label.username=A&nv\u00E4ndarnamn:
 label.millimetres=(mm)
 label.inches=(tum)
-label.topmargin=\u00F6verkant
-label.topmargin.mnemonic=R
-label.bottommargin=nederkant
-label.bottommargin.mnemonic=N
-label.leftmargin=v\u00E4nster
-label.leftmargin.mnemonic=V
-label.rightmargin=h\u00F6ger
-label.rightmargin.mnemonic=H
+label.topmargin=\u00F6ve&rkant
+label.bottommargin=&nederkant
+label.leftmargin=&v\u00E4nster
+label.rightmargin=&h\u00F6ger
 #
-radiobutton.color=F\u00E4rg
-radiobutton.color.mnemonic=G
-radiobutton.draftq=Utkast
-radiobutton.draftq.mnemonic=K
-radiobutton.duplex=Dubbelsidig
-radiobutton.duplex.mnemonic=D
-radiobutton.highq=H\u00F6g
-radiobutton.highq.mnemonic=H
-radiobutton.landscape=Liggande
-radiobutton.landscape.mnemonic=L
-radiobutton.monochrome=Monokrom
-radiobutton.monochrome.mnemonic=M
-radiobutton.normalq=Normal
-radiobutton.normalq.mnemonic=O
-radiobutton.oneside=Ensidig
-radiobutton.oneside.mnemonic=E
-radiobutton.portrait=St\u00E5ende
-radiobutton.portrait.mnemonic=D
-radiobutton.rangeall=Alla
-radiobutton.rangeall.mnemonic=L
-radiobutton.rangepages=Sidor
-radiobutton.rangepages.mnemonic=D
-radiobutton.revlandscape=Omv\u00E4nt liggande
-radiobutton.revlandscape.mnemonic=G
-radiobutton.revportrait=Omv\u00E4nt st\u00E5ende
-radiobutton.revportrait.mnemonic=M
-radiobutton.tumble=V\u00E4nd
-radiobutton.tumble.mnemonic=V
+radiobutton.color=F\u00E4r&g
+radiobutton.draftq=Ut&kast
+radiobutton.duplex=&Dubbelsidig
+radiobutton.highq=&H\u00F6g
+radiobutton.landscape=&Liggande
+radiobutton.monochrome=&Monokrom
+radiobutton.normalq=N&ormal
+radiobutton.oneside=&Ensidig
+radiobutton.portrait=St\u00E5en&de
+radiobutton.rangeall=A&lla
+radiobutton.rangepages=Si&dor
+radiobutton.revlandscape=Omv\u00E4nt li&ggande
+radiobutton.revportrait=O&mv\u00E4nt st\u00E5ende
+radiobutton.tumble=&V\u00E4nd
 # The vkMnemonics correspond with the constants defined in KeyEvent, eg
 # 65 = KeyEvent.VK_A
-tab.appearance=Format
-tab.appearance.vkMnemonic=70
-tab.general=Allm\u00E4nt
-tab.general.vkMnemonic=65
-tab.pagesetup=Utskriftsformat
-tab.pagesetup.vkMnemonic=83
+tab.appearance=&Format
+tab.general=&Allm\u00E4nt
+tab.pagesetup=Ut&skriftsformat
 #
 error.pagerange=Ogiltigt sidintervall. Skriv in v\u00E4rdena igen (t ex 1-3,5,7-10)
 error.destination=Ogiltigt filnamn. F\u00F6rs\u00F6k igen.
--- a/jdk/src/share/classes/sun/print/resources/serviceui_zh_CN.properties	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/src/share/classes/sun/print/resources/serviceui_zh_CN.properties	Wed Jul 05 18:10:27 2017 +0200
@@ -14,15 +14,11 @@
 button.cancel=\u53D6\u6D88
 button.ok=\u786E\u5B9A
 button.print=\u6253\u5370
-button.properties=\u5C5E\u6027(R)...
-button.properties.mnemonic=R
+button.properties=\u5C5E\u6027(&R)...
 #
-checkbox.collate=\u9010\u4EFD\u6253\u5370(C)
-checkbox.collate.mnemonic=C
-checkbox.jobsheets=\u6807\u5E1C\u9875(B)
-checkbox.jobsheets.mnemonic=B
-checkbox.printtofile=\u6253\u5370\u5230\u6587\u4EF6(F)
-checkbox.printtofile.mnemonic=F
+checkbox.collate=\u9010\u4EFD\u6253\u5370(&C)
+checkbox.jobsheets=\u6807\u5E1C\u9875(&B)
+checkbox.printtofile=\u6253\u5370\u5230\u6587\u4EF6(&F)
 #
 dialog.printtitle=\u6253\u5370
 dialog.pstitle=\u9875\u9762\u8BBE\u7F6E
@@ -33,70 +29,42 @@
 dialog.writeerror=\u65E0\u6CD5\u5199\u5165\u6587\u4EF6:
 #
 label.info=\u4FE1\u606F:
-label.jobname=\u4F5C\u4E1A\u540D(J):
-label.jobname.mnemonic=J
-label.numcopies=\u6253\u5370\u4EFD\u6570(O):
-label.numcopies.mnemonic=O
-label.priority=\u4F18\u5148\u7EA7(R):
-label.priority.mnemonic=R
-label.psname=\u540D\u79F0(N):
-label.psname.mnemonic=N
+label.jobname=\u4F5C\u4E1A\u540D(&J):
+label.numcopies=\u6253\u5370\u4EFD\u6570(&O):
+label.priority=\u4F18\u5148\u7EA7(&R):
+label.psname=\u540D\u79F0(&N):
 label.pstype=\u7C7B\u578B:
 label.rangeto=\u81F3
-label.size=\u5927\u5C0F(Z):
-label.size.mnemonic=Z
-label.source=\u6765\u6E90(C):
-label.source.mnemonic=C
+label.size=\u5927\u5C0F(&Z):
+label.source=\u6765\u6E90(&C):
 label.status=\u72B6\u6001:
-label.username=\u7528\u6237\u540D(U):
-label.username.mnemonic=U
+label.username=\u7528\u6237\u540D(&U):
 label.millimetres=(\u6BEB\u7C73)
 label.inches=(\u82F1\u5BF8)
-label.topmargin=\u4E0A\u8FB9\u8DDD(T)
-label.topmargin.mnemonic=T
-label.bottommargin=\u4E0B\u8FB9\u8DDD(B)
-label.bottommargin.mnemonic=B
-label.leftmargin=\u5DE6\u8FB9\u8DDD(F)
-label.leftmargin.mnemonic=F
-label.rightmargin=\u53F3\u8FB9\u8DDD(R)
-label.rightmargin.mnemonic=R
+label.topmargin=\u4E0A\u8FB9\u8DDD(&T)
+label.bottommargin=\u4E0B\u8FB9\u8DDD(&B)
+label.leftmargin=\u5DE6\u8FB9\u8DDD(&F)
+label.rightmargin=\u53F3\u8FB9\u8DDD(&R)
 #
-radiobutton.color=\u989C\u8272(C)
-radiobutton.color.mnemonic=C
-radiobutton.draftq=\u8349\u56FE(F)
-radiobutton.draftq.mnemonic=F
-radiobutton.duplex=\u53CC\u9762\u6253\u5370(D)
-radiobutton.duplex.mnemonic=D
-radiobutton.highq=\u9AD8(H)
-radiobutton.highq.mnemonic=H
-radiobutton.landscape=\u6A2A\u5411(L)
-radiobutton.landscape.mnemonic=L
-radiobutton.monochrome=\u5355\u8272(M)
-radiobutton.monochrome.mnemonic=M
-radiobutton.normalq=\u6B63\u5E38(N)
-radiobutton.normalq.mnemonic=N
-radiobutton.oneside=\u5355\u9762(O)
-radiobutton.oneside.mnemonic=O
-radiobutton.portrait=\u7EB5\u5411(P)
-radiobutton.portrait.mnemonic=P
-radiobutton.rangeall=\u5168\u90E8(L)
-radiobutton.rangeall.mnemonic=L
-radiobutton.rangepages=\u9875\u7801\u8303\u56F4(E)
-radiobutton.rangepages.mnemonic=E
-radiobutton.revlandscape=\u6A2A\u5411\u53CD\u9762\u6253\u5370(N)
-radiobutton.revlandscape.mnemonic=N
-radiobutton.revportrait=\u7EB5\u5411\u53CD\u9762\u6253\u5370(I)
-radiobutton.revportrait.mnemonic=I
-radiobutton.tumble=\u7FFB\u8F6C(T)
-radiobutton.tumble.mnemonic=T
+radiobutton.color=\u989C\u8272(&C)
+radiobutton.draftq=\u8349\u56FE(&F)
+radiobutton.duplex=\u53CC\u9762\u6253\u5370(&D)
+radiobutton.highq=\u9AD8(&H)
+radiobutton.landscape=\u6A2A\u5411(&L)
+radiobutton.monochrome=\u5355\u8272(&M)
+radiobutton.normalq=\u6B63\u5E38(&N)
+radiobutton.oneside=\u5355\u9762(&O)
+radiobutton.portrait=\u7EB5\u5411(&P)
+radiobutton.rangeall=\u5168\u90E8(&L)
+radiobutton.rangepages=\u9875\u7801\u8303\u56F4(&E)
+radiobutton.revlandscape=\u6A2A\u5411\u53CD\u9762\u6253\u5370(&N)
+radiobutton.revportrait=\u7EB5\u5411\u53CD\u9762\u6253\u5370(&I)
+radiobutton.tumble=\u7FFB\u8F6C(&T)
 # The vkMnemonics correspond with the constants defined in KeyEvent, eg
 # 65 = KeyEvent.VK_A
-tab.appearance=\u5916\u89C2(A)
-tab.appearance.vkMnemonic=65
-tab.general=\u4E00\u822C\u4FE1\u606F(G)
-tab.general.vkMnemonic=71
-tab.pagesetup=\u9875\u9762\u8BBE\u7F6E(S)
-tab.pagesetup.vkMnemonic=83
+tab.appearance=\u5916\u89C2(&A)
+tab.general=\u4E00\u822C\u4FE1\u606F(&G)
+tab.pagesetup=\u9875\u9762\u8BBE\u7F6E(&S)
 #
 error.pagerange=\u65E0\u6548\u7684\u9875\u9762\u8303\u56F4; \u8BF7\u91CD\u65B0\u8F93\u5165\u6570\u503C (\u4F8B\u5982 1-3,5,7-10)
 error.destination=\u65E0\u6548\u7684\u6587\u4EF6\u540D; \u8BF7\u91CD\u8BD5
--- a/jdk/src/share/classes/sun/print/resources/serviceui_zh_TW.properties	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/src/share/classes/sun/print/resources/serviceui_zh_TW.properties	Wed Jul 05 18:10:27 2017 +0200
@@ -14,15 +14,11 @@
 button.cancel=\u53D6\u6D88
 button.ok=\u78BA\u5B9A
 button.print=\u5217\u5370
-button.properties=\u7279\u6027(R)...
-button.properties.mnemonic=R
+button.properties=\u7279\u6027(&R)...
 #
-checkbox.collate=\u7406\u5E8F(C)
-checkbox.collate.mnemonic=C
-checkbox.jobsheets=\u6A19\u984C\u9801(B)
-checkbox.jobsheets.mnemonic=B
-checkbox.printtofile=\u5217\u5370\u81F3\u6A94\u6848(F)
-checkbox.printtofile.mnemonic=F
+checkbox.collate=\u7406\u5E8F(&C)
+checkbox.jobsheets=\u6A19\u984C\u9801(&B)
+checkbox.printtofile=\u5217\u5370\u81F3\u6A94\u6848(&F)
 #
 dialog.printtitle=\u5217\u5370
 dialog.pstitle=\u9801\u9762\u8A2D\u5B9A
@@ -33,70 +29,42 @@
 dialog.writeerror=\u7121\u6CD5\u5BEB\u5165\u81F3\u6A94\u6848:
 #
 label.info=\u8CC7\u8A0A:
-label.jobname=\u5DE5\u4F5C\u540D\u7A31(J):
-label.jobname.mnemonic=J
-label.numcopies=\u5217\u5370\u4EFD\u6578(O):
-label.numcopies.mnemonic=O
-label.priority=\u512A\u5148\u6B0A(R):
-label.priority.mnemonic=R
-label.psname=\u540D\u7A31(N):
-label.psname.mnemonic=N
+label.jobname=\u5DE5\u4F5C\u540D\u7A31(&J):
+label.numcopies=\u5217\u5370\u4EFD\u6578(&O):
+label.priority=\u512A\u5148\u6B0A(&R):
+label.psname=\u540D\u7A31(&N):
 label.pstype=\u985E\u578B:
 label.rangeto=\u81F3
-label.size=\u5927\u5C0F(Z):
-label.size.mnemonic=Z
-label.source=\u4F86\u6E90(C):
-label.source.mnemonic=C
+label.size=\u5927\u5C0F(&Z):
+label.source=\u4F86\u6E90(&C):
 label.status=\u72C0\u614B:
-label.username=\u4F7F\u7528\u8005\u540D\u7A31(U):
-label.username.mnemonic=U
+label.username=\u4F7F\u7528\u8005\u540D\u7A31(&U):
 label.millimetres=(mm)
 label.inches=(in)
-label.topmargin=\u9802\u7AEF\u908A\u8DDD(T)
-label.topmargin.mnemonic=T
-label.bottommargin=\u5E95\u90E8\u908A\u8DDD(B)
-label.bottommargin.mnemonic=B
-label.leftmargin=\u5DE6\u908A\u8DDD(F)
-label.leftmargin.mnemonic=F
-label.rightmargin=\u53F3\u908A\u8DDD(R)
-label.rightmargin.mnemonic=R
+label.topmargin=\u9802\u7AEF\u908A\u8DDD(&T)
+label.bottommargin=\u5E95\u90E8\u908A\u8DDD(&B)
+label.leftmargin=\u5DE6\u908A\u8DDD(&F)
+label.rightmargin=\u53F3\u908A\u8DDD(&R)
 #
-radiobutton.color=\u984F\u8272(C)
-radiobutton.color.mnemonic=C
-radiobutton.draftq=\u8349\u7A3F(F)
-radiobutton.draftq.mnemonic=F
-radiobutton.duplex=\u96D9\u9762\u5217\u5370(D)
-radiobutton.duplex.mnemonic=D
-radiobutton.highq=\u9AD8(H)
-radiobutton.highq.mnemonic=H
-radiobutton.landscape=\u6A6B\u5411(L)
-radiobutton.landscape.mnemonic=L
-radiobutton.monochrome=\u55AE\u8272(M)
-radiobutton.monochrome.mnemonic=M
-radiobutton.normalq=\u6B63\u5E38(N)
-radiobutton.normalq.mnemonic=N
-radiobutton.oneside=\u55AE\u9762(O)
-radiobutton.oneside.mnemonic=O
-radiobutton.portrait=\u76F4\u5411(P)
-radiobutton.portrait.mnemonic=P
-radiobutton.rangeall=\u5168\u90E8(L)
-radiobutton.rangeall.mnemonic=L
-radiobutton.rangepages=\u9801\u9762(E)
-radiobutton.rangepages.mnemonic=E
-radiobutton.revlandscape=\u53CD\u5411\u6A6B\u5370(N)
-radiobutton.revlandscape.mnemonic=N
-radiobutton.revportrait=\u53CD\u5411\u76F4\u5370(I)
-radiobutton.revportrait.mnemonic=I
-radiobutton.tumble=\u7FFB\u8F49(T)
-radiobutton.tumble.mnemonic=T
+radiobutton.color=\u984F\u8272(&C)
+radiobutton.draftq=\u8349\u7A3F(&F)
+radiobutton.duplex=\u96D9\u9762\u5217\u5370(&D)
+radiobutton.highq=\u9AD8(&H)
+radiobutton.landscape=\u6A6B\u5411(&L)
+radiobutton.monochrome=\u55AE\u8272(&M)
+radiobutton.normalq=\u6B63\u5E38(&N)
+radiobutton.oneside=\u55AE\u9762(&O)
+radiobutton.portrait=\u76F4\u5411(&P)
+radiobutton.rangeall=\u5168\u90E8(&L)
+radiobutton.rangepages=\u9801\u9762(&E)
+radiobutton.revlandscape=\u53CD\u5411\u6A6B\u5370(&N)
+radiobutton.revportrait=\u53CD\u5411\u76F4\u5370(&I)
+radiobutton.tumble=\u7FFB\u8F49(&T)
 # The vkMnemonics correspond with the constants defined in KeyEvent, eg
 # 65 = KeyEvent.VK_A
-tab.appearance=\u5916\u89C0(A)
-tab.appearance.vkMnemonic=65
-tab.general=\u4E00\u822C(G)
-tab.general.vkMnemonic=71
-tab.pagesetup=\u9801\u9762\u8A2D\u5B9A(S)
-tab.pagesetup.vkMnemonic=83
+tab.appearance=\u5916\u89C0(&A)
+tab.general=\u4E00\u822C(&G)
+tab.pagesetup=\u9801\u9762\u8A2D\u5B9A(&S)
 #
 error.pagerange=\u7121\u6548\u7684\u9801\u9762\u7BC4\u570D; \u8ACB\u91CD\u65B0\u8F38\u5165\u6578\u503C (\u4F8B\u5982 1-3,5,7-10)
 error.destination=\u7121\u6548\u7684\u6A94\u540D; \u8ACB\u518D\u8A66\u4E00\u6B21
--- a/jdk/src/share/classes/sun/security/action/LoadLibraryAction.java	Wed Jul 05 18:09:43 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,70 +0,0 @@
-/*
- * Copyright (c) 1998, 2006, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.security.action;
-
-/**
- * A convenience class for loading a system library as a privileged action.
- *
- * <p>An instance of this class can be used as the argument of
- * <code>AccessController.doPrivileged</code>.
- *
- * <p>The following code attempts to load the system library named
- * <code>"lib"</code> as a privileged action: <p>
- *
- * <pre>
- * java.security.AccessController.doPrivileged(new LoadLibraryAction("lib"));
- * </pre>
- *
- * @author Roland Schemers
- * @see java.security.PrivilegedAction
- * @see java.security.AccessController
- * @since 1.2
- */
-
-public class LoadLibraryAction implements java.security.PrivilegedAction<Void> {
-    private String theLib;
-
-    /**
-     * Constructor that takes the name of the system library that needs to be
-     * loaded.
-     *
-     * <p>The manner in which a library name is mapped to the
-     * actual system library is system dependent.
-     *
-     * @param theLib the name of the library.
-     */
-    public LoadLibraryAction(String theLib) {
-        this.theLib = theLib;
-    }
-
-    /**
-     * Loads the system library whose name was specified in the constructor.
-     */
-    public Void run() {
-        System.loadLibrary(theLib);
-        return null;
-    }
-}
--- a/jdk/src/share/classes/sun/security/jgss/wrapper/SunNativeProvider.java	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/src/share/classes/sun/security/jgss/wrapper/SunNativeProvider.java	Wed Jul 05 18:10:27 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -90,7 +90,7 @@
                                     "libgssapi_krb5.so",
                                     "libgssapi_krb5.so.2",
                                 };
-                            } else if (osname.startsWith("Mac OS X")) {
+                            } else if (osname.contains("OS X")) {
                                 gssLibs = new String[]{
                                     "/usr/lib/sasl2/libgssapiv2.2.so",
                                 };
--- a/jdk/src/share/classes/sun/security/krb5/Config.java	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/src/share/classes/sun/security/krb5/Config.java	Wed Jul 05 18:10:27 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -737,7 +737,7 @@
                     }
                 } else if (osname.startsWith("SunOS")) {
                     name =  "/etc/krb5/krb5.conf";
-                } else if (osname.startsWith("Mac")) {
+                } else if (osname.contains("OS X")) {
                     if (isMacosLionOrBetter()) return "";
                     name = findMacosConfigFile();
                 } else {
--- a/jdk/src/share/classes/sun/security/krb5/Credentials.java	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/src/share/classes/sun/security/krb5/Credentials.java	Wed Jul 05 18:10:27 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -289,7 +289,7 @@
             String os = java.security.AccessController.doPrivileged(
                         new sun.security.action.GetPropertyAction("os.name"));
             if (os.toUpperCase(Locale.ENGLISH).startsWith("WINDOWS") ||
-                    os.toUpperCase(Locale.ENGLISH).startsWith("MAC")) {
+                    os.toUpperCase(Locale.ENGLISH).contains("OS X")) {
                 Credentials creds = acquireDefaultCreds();
                 if (creds == null) {
                     if (DEBUG) {
@@ -478,7 +478,7 @@
         java.security.AccessController.doPrivileged(
                 new java.security.PrivilegedAction<Void> () {
                         public Void run() {
-                                if (System.getProperty("os.name").startsWith("Mac")) {
+                                if (System.getProperty("os.name").contains("OS X")) {
                                     System.loadLibrary("osxkrb5");
                                 } else {
                                     System.loadLibrary("w2k_lsa_auth");
--- a/jdk/src/share/classes/sun/security/krb5/SCDynamicStoreConfig.java	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/src/share/classes/sun/security/krb5/SCDynamicStoreConfig.java	Wed Jul 05 18:10:27 2017 +0200
@@ -36,7 +36,13 @@
     private static native Hashtable<String, Object> getKerberosConfig();
 
     static {
-        java.security.AccessController.doPrivileged(new sun.security.action.LoadLibraryAction("osx"));
+        java.security.AccessController.doPrivileged(
+            new java.security.PrivilegedAction<Void>() {
+                public Void run() {
+                    System.loadLibrary("osx");
+                    return null;
+                }
+            });
         installNotificationCallback();
     }
 
--- a/jdk/src/share/classes/sun/security/provider/ByteArrayAccess.java	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/src/share/classes/sun/security/provider/ByteArrayAccess.java	Wed Jul 05 18:10:27 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -95,7 +95,8 @@
     private static boolean unaligned() {
         String arch = java.security.AccessController.doPrivileged
             (new sun.security.action.GetPropertyAction("os.arch", ""));
-        return arch.equals("i386") || arch.equals("x86") || arch.equals("amd64");
+        return arch.equals("i386") || arch.equals("x86") || arch.equals("amd64")
+            || arch.equals("x86_64");
     }
 
     /**
--- a/jdk/src/share/classes/sun/security/smartcardio/PCSC.java	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/src/share/classes/sun/security/smartcardio/PCSC.java	Wed Jul 05 18:10:27 2017 +0200
@@ -27,8 +27,6 @@
 
 import java.security.AccessController;
 
-import sun.security.action.LoadLibraryAction;
-
 /**
  * Access to native PC/SC functions and definition of PC/SC constants.
  * Initialization and platform specific PC/SC constants are handled in
--- a/jdk/src/share/classes/sun/security/util/DisabledAlgorithmConstraints.java	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/src/share/classes/sun/security/util/DisabledAlgorithmConstraints.java	Wed Jul 05 18:10:27 2017 +0200
@@ -59,10 +59,10 @@
     public final static String PROPERTY_TLS_DISABLED_ALGS =
             "jdk.tls.disabledAlgorithms";
 
-    private static Map<String, String[]> disabledAlgorithmsMap =
-            Collections.synchronizedMap(new HashMap<String, String[]>());
-    private static Map<String, KeySizeConstraints> keySizeConstraintsMap =
-        Collections.synchronizedMap(new HashMap<String, KeySizeConstraints>());
+    private final static Map<String, String[]> disabledAlgorithmsMap =
+                                                            new HashMap<>();
+    private final static Map<String, KeySizeConstraints> keySizeConstraintsMap =
+                                                            new HashMap<>();
 
     private String[] disabledAlgorithms;
     private KeySizeConstraints keySizeConstraints;
@@ -74,6 +74,8 @@
      *        algorithm constraints
      */
     public DisabledAlgorithmConstraints(String propertyName) {
+        // Both disabledAlgorithmsMap and keySizeConstraintsMap are
+        // synchronized with the lock of disabledAlgorithmsMap.
         synchronized (disabledAlgorithmsMap) {
             if(!disabledAlgorithmsMap.containsKey(propertyName)) {
                 loadDisabledAlgorithmsMap(propertyName);
--- a/jdk/src/share/classes/sun/tracing/dtrace/JVM.java	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/src/share/classes/sun/tracing/dtrace/JVM.java	Wed Jul 05 18:10:27 2017 +0200
@@ -35,8 +35,13 @@
 class JVM {
 
     static {
-      java.security.AccessController.doPrivileged(
-              new sun.security.action.LoadLibraryAction("jsdt"));
+        java.security.AccessController.doPrivileged(
+            new java.security.PrivilegedAction<Void>() {
+                public Void run() {
+                    System.loadLibrary("jsdt");
+                    return null;
+                }
+            });
     }
 
     static long activate(String moduleName, DTraceProvider[] providers) {
--- a/jdk/src/share/classes/sun/util/logging/PlatformLogger.java	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/src/share/classes/sun/util/logging/PlatformLogger.java	Wed Jul 05 18:10:27 2017 +0200
@@ -516,6 +516,9 @@
         }
 
         void doLog(int level, String msg, Object... params) {
+            if (!isLoggable(level)) {
+                return;
+            }
             // only pass String objects to the j.u.l.Logger which may
             // be created by untrusted code
             int len = (params != null) ? params.length : 0;
--- a/jdk/src/share/native/com/sun/java/util/jar/pack/bands.cpp	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/src/share/native/com/sun/java/util/jar/pack/bands.cpp	Wed Jul 05 18:10:27 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -188,9 +188,13 @@
 entry* band::getRefCommon(cpindex* ix_, bool nullOKwithCaller) {
   CHECK_0;
   assert(ix_->ixTag == ixTag
-         || (ixTag == CONSTANT_Literal
-             && ix_->ixTag >= CONSTANT_Integer
-             && ix_->ixTag <= CONSTANT_String));
+         || ((ixTag == CONSTANT_All ||
+              ixTag == CONSTANT_LoadableValue ||
+              ixTag == CONSTANT_AnyMember)
+         || (ixTag == CONSTANT_FieldSpecific &&
+              ix_->ixTag >= CONSTANT_Integer  &&
+              ix_->ixTag <= CONSTANT_String))
+         );
   int n = vs[0].getInt() - nullOK;
   // Note: band-local nullOK means null encodes as 0.
   // But nullOKwithCaller means caller is willing to tolerate a null.
@@ -270,22 +274,15 @@
 #define NO_INDEX            0
 
 struct band_init {
-#ifndef PRODUCT
   int         bn;
   const char* name;
-#endif
   int   defc;
   int   index;
 };
 
-#ifdef PRODUCT
-#define BAND_INIT(name, cspec, ix) \
-  { cspec, ix }
-#else
 #define BAND_INIT(name, cspec, ix) \
   { e_##name,  #name, /*debug only*/ \
     cspec, ix }
-#endif
 
 const band_init all_band_inits[] = {
 //BAND_INIT(archive_magic, BYTE1_spec, 0),
@@ -314,6 +311,14 @@
   BAND_INIT(cp_Method_desc, UDELTA5_spec, INDEX(CONSTANT_NameandType)),
   BAND_INIT(cp_Imethod_class, DELTA5_spec, INDEX(CONSTANT_Class)),
   BAND_INIT(cp_Imethod_desc, UDELTA5_spec, INDEX(CONSTANT_NameandType)),
+  BAND_INIT(cp_MethodHandle_refkind, DELTA5_spec, 0),
+  BAND_INIT(cp_MethodHandle_member, UDELTA5_spec, INDEX(CONSTANT_AnyMember)),
+  BAND_INIT(cp_MethodType, UDELTA5_spec, INDEX(CONSTANT_Signature)),
+  BAND_INIT(cp_BootstrapMethod_ref, DELTA5_spec, INDEX(CONSTANT_MethodHandle)),
+  BAND_INIT(cp_BootstrapMethod_arg_count, UDELTA5_spec, 0),
+  BAND_INIT(cp_BootstrapMethod_arg, DELTA5_spec, INDEX(CONSTANT_LoadableValue)),
+  BAND_INIT(cp_InvokeDynamic_spec, DELTA5_spec, INDEX(CONSTANT_BootstrapMethod)),
+  BAND_INIT(cp_InvokeDynamic_desc, UDELTA5_spec, INDEX(CONSTANT_NameandType)),
   BAND_INIT(attr_definition_headers, BYTE1_spec, 0),
   BAND_INIT(attr_definition_name, UNSIGNED5_spec, INDEX(CONSTANT_Utf8)),
   BAND_INIT(attr_definition_layout, UNSIGNED5_spec, INDEX(CONSTANT_Utf8)),
@@ -333,7 +338,7 @@
   BAND_INIT(field_attr_count, UNSIGNED5_spec, 0),
   BAND_INIT(field_attr_indexes, UNSIGNED5_spec, 0),
   BAND_INIT(field_attr_calls, UNSIGNED5_spec, 0),
-  BAND_INIT(field_ConstantValue_KQ, UNSIGNED5_spec, INDEX(CONSTANT_Literal)),
+  BAND_INIT(field_ConstantValue_KQ, UNSIGNED5_spec, INDEX(CONSTANT_FieldSpecific)),
   BAND_INIT(field_Signature_RS, UNSIGNED5_spec, INDEX(CONSTANT_Signature)),
   BAND_INIT(field_metadata_bands, -1, -1),
   BAND_INIT(field_attr_bands, -1, -1),
@@ -415,10 +420,12 @@
   BAND_INIT(bc_longref, DELTA5_spec, INDEX(CONSTANT_Long)),
   BAND_INIT(bc_doubleref, DELTA5_spec, INDEX(CONSTANT_Double)),
   BAND_INIT(bc_stringref, DELTA5_spec, INDEX(CONSTANT_String)),
+  BAND_INIT(bc_loadablevalueref, DELTA5_spec, INDEX(CONSTANT_LoadableValue)),
   BAND_INIT(bc_classref, UNSIGNED5_spec, NULL_OR_INDEX(CONSTANT_Class)),
   BAND_INIT(bc_fieldref, DELTA5_spec, INDEX(CONSTANT_Fieldref)),
   BAND_INIT(bc_methodref, UNSIGNED5_spec, INDEX(CONSTANT_Methodref)),
   BAND_INIT(bc_imethodref, DELTA5_spec, INDEX(CONSTANT_InterfaceMethodref)),
+  BAND_INIT(bc_indyref, DELTA5_spec, INDEX(CONSTANT_InvokeDynamic)),
   BAND_INIT(bc_thisfield, UNSIGNED5_spec, SUB_INDEX(CONSTANT_Fieldref)),
   BAND_INIT(bc_superfield, UNSIGNED5_spec, SUB_INDEX(CONSTANT_Fieldref)),
   BAND_INIT(bc_thismethod, UNSIGNED5_spec, SUB_INDEX(CONSTANT_Methodref)),
@@ -471,7 +478,7 @@
   for (int i = 0; i < BAND_LIMIT; i++) {
     band* scan = &tmp_all_bands[i];
     uint tag = scan->ixTag;  // Cf. #define INDEX(tag) above
-    if (tag != 0 && tag != CONSTANT_Literal && (tag & SUBINDEX_BIT) == 0) {
+    if (tag != 0 && tag != CONSTANT_FieldSpecific && (tag & SUBINDEX_BIT) == 0) {
       scan->setIndex(u->cp.getIndex(tag));
     }
   }
--- a/jdk/src/share/native/com/sun/java/util/jar/pack/bands.h	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/src/share/native/com/sun/java/util/jar/pack/bands.h	Wed Jul 05 18:10:27 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2005, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -29,9 +29,7 @@
 struct unpacker;
 
 struct band {
-#ifndef PRODUCT
   const char*   name;
-#endif
   int           bn;             // band_number of this band
   coding*       defc;           // default coding method
   cpindex*      ix;             // CP entry mapping, if CPRefBand
@@ -162,6 +160,14 @@
     e_cp_Method_desc,
     e_cp_Imethod_class,
     e_cp_Imethod_desc,
+    e_cp_MethodHandle_refkind,
+    e_cp_MethodHandle_member,
+    e_cp_MethodType,
+    e_cp_BootstrapMethod_ref,
+    e_cp_BootstrapMethod_arg_count,
+    e_cp_BootstrapMethod_arg,
+    e_cp_InvokeDynamic_spec,
+    e_cp_InvokeDynamic_desc,
 
     // bands which define transmission of attributes
     e_attr_definition_headers,
@@ -284,11 +290,13 @@
     e_bc_longref,
     e_bc_doubleref,
     e_bc_stringref,
+    e_bc_loadablevalueref,
     e_bc_classref,
 
     e_bc_fieldref,
     e_bc_methodref,
     e_bc_imethodref,
+    e_bc_indyref,
 
     // _self_linker_op family
     e_bc_thisfield,
@@ -343,6 +351,14 @@
 #define cp_Method_desc all_bands[e_cp_Method_desc]
 #define cp_Imethod_class all_bands[e_cp_Imethod_class]
 #define cp_Imethod_desc all_bands[e_cp_Imethod_desc]
+#define cp_MethodHandle_refkind all_bands[e_cp_MethodHandle_refkind]
+#define cp_MethodHandle_member all_bands[e_cp_MethodHandle_member]
+#define cp_MethodType all_bands[e_cp_MethodType]
+#define cp_BootstrapMethod_ref all_bands[e_cp_BootstrapMethod_ref]
+#define cp_BootstrapMethod_arg_count all_bands[e_cp_BootstrapMethod_arg_count]
+#define cp_BootstrapMethod_arg all_bands[e_cp_BootstrapMethod_arg]
+#define cp_InvokeDynamic_spec  all_bands[e_cp_InvokeDynamic_spec]
+#define cp_InvokeDynamic_desc all_bands[e_cp_InvokeDynamic_desc]
 #define attr_definition_headers all_bands[e_attr_definition_headers]
 #define attr_definition_name all_bands[e_attr_definition_name]
 #define attr_definition_layout all_bands[e_attr_definition_layout]
@@ -437,10 +453,12 @@
 #define bc_longref all_bands[e_bc_longref]
 #define bc_doubleref all_bands[e_bc_doubleref]
 #define bc_stringref all_bands[e_bc_stringref]
+#define bc_loadablevalueref all_bands[e_bc_loadablevalueref]
 #define bc_classref all_bands[e_bc_classref]
 #define bc_fieldref all_bands[e_bc_fieldref]
 #define bc_methodref all_bands[e_bc_methodref]
 #define bc_imethodref all_bands[e_bc_imethodref]
+#define bc_indyref all_bands[e_bc_indyref]
 #define bc_thisfield all_bands[e_bc_thisfield]
 #define bc_superfield all_bands[e_bc_superfield]
 #define bc_thismethod all_bands[e_bc_thismethod]
--- a/jdk/src/share/native/com/sun/java/util/jar/pack/constants.h	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/src/share/native/com/sun/java/util/jar/pack/constants.h	Wed Jul 05 18:10:27 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2005, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -49,61 +49,82 @@
 #define JAVA6_PACKAGE_MAJOR_VERSION 160
 #define JAVA6_PACKAGE_MINOR_VERSION 1
 
+#define JAVA7_PACKAGE_MAJOR_VERSION 170
+#define JAVA7_PACKAGE_MINOR_VERSION 1
 
 // magic number for gzip streams (for processing pack200-gzip data)
 #define GZIP_MAGIC      0x1F8B0800
 #define GZIP_MAGIC_MASK 0xFFFFFF00  // last byte is variable "flg" field
 
 enum {
-    CONSTANT_None,
-    CONSTANT_Utf8,
-    CONSTANT_unused2,           /* unused, was Unicode */
-    CONSTANT_Integer,
-    CONSTANT_Float,
-    CONSTANT_Long,
-    CONSTANT_Double,
-    CONSTANT_Class,
-    CONSTANT_String,
-    CONSTANT_Fieldref,
-    CONSTANT_Methodref,
-    CONSTANT_InterfaceMethodref,
-    CONSTANT_NameandType,
+    CONSTANT_None               = 0,
+    CONSTANT_Utf8               = 1,
+    CONSTANT_unused             = 2,     /* unused, was Unicode */
+    CONSTANT_Integer            = 3,
+    CONSTANT_Float              = 4,
+    CONSTANT_Long               = 5,
+    CONSTANT_Double             = 6,
+    CONSTANT_Class              = 7,
+    CONSTANT_String             = 8,
+    CONSTANT_Fieldref           = 9,
+    CONSTANT_Methodref          = 10,
+    CONSTANT_InterfaceMethodref = 11,
+    CONSTANT_NameandType        = 12,
+    CONSTANT_unused13           = 13,
+    CONSTANT_unused14           = 14,
+    CONSTANT_MethodHandle       = 15,
+    CONSTANT_MethodType         = 16,
+    CONSTANT_unused17           = 17,
+    CONSTANT_InvokeDynamic      = 18,
+    CONSTANT_Limit              = 19,
+    CONSTANT_Signature          = CONSTANT_unused13,
+    CONSTANT_BootstrapMethod    = CONSTANT_unused17, // used only for InvokeDynamic
+    CONSTANT_All                = 50,                // combined global map
+    CONSTANT_LoadableValue      = 51,                // used for 'KL' and qldc operands
+    CONSTANT_AnyMember          = 52,                // union of refs to field or (interface) method
+    CONSTANT_FieldSpecific      = 53,                // used only for 'KQ' ConstantValue attrs
+    CONSTANT_GroupFirst         = CONSTANT_All,      // start group marker
+    CONSTANT_GroupLimit         = 54,                // end group marker
 
-    CONSTANT_Signature = 13,
-    CONSTANT_All       = 14,
-    CONSTANT_Limit     = 15,
-    CONSTANT_NONE      = 0,
-
-    CONSTANT_Literal   = 20,   //pseudo-tag for debugging
-    CONSTANT_Member    = 21,   //pseudo-tag for debugging
+    // CONSTANT_MethodHandle reference kinds
+    REF_getField         = 1,
+    REF_getStatic        = 2,
+    REF_putField         = 3,
+    REF_putStatic        = 4,
+    REF_invokeVirtual    = 5,
+    REF_invokeStatic     = 6,
+    REF_invokeSpecial    = 7,
+    REF_newInvokeSpecial = 8,
+    REF_invokeInterface  = 9,
 
     SUBINDEX_BIT = 64,  // combined with CONSTANT_xxx for ixTag
 
     ACC_STATIC       = 0x0008,
     ACC_IC_LONG_FORM = (1<<16), //for ic_flags
 
-    CLASS_ATTR_SourceFile = 17,
-    CLASS_ATTR_EnclosingMethod = 18,
-    CLASS_ATTR_InnerClasses = 23,
-    CLASS_ATTR_ClassFile_version = 24,
-    FIELD_ATTR_ConstantValue = 17,
-    METHOD_ATTR_Code = 17,
-    METHOD_ATTR_Exceptions = 18,
-    METHOD_ATTR_RuntimeVisibleParameterAnnotations = 23,
+    CLASS_ATTR_SourceFile                            = 17,
+    CLASS_ATTR_EnclosingMethod                       = 18,
+    CLASS_ATTR_InnerClasses                          = 23,
+    CLASS_ATTR_ClassFile_version                     = 24,
+    CLASS_ATTR_BootstrapMethods                      = 25,
+    FIELD_ATTR_ConstantValue                         = 17,
+    METHOD_ATTR_Code                                 = 17,
+    METHOD_ATTR_Exceptions                           = 18,
+    METHOD_ATTR_RuntimeVisibleParameterAnnotations   = 23,
     METHOD_ATTR_RuntimeInvisibleParameterAnnotations = 24,
-    METHOD_ATTR_AnnotationDefault = 25,
-    CODE_ATTR_StackMapTable = 0,
-    CODE_ATTR_LineNumberTable = 1,
-    CODE_ATTR_LocalVariableTable = 2,
+    METHOD_ATTR_AnnotationDefault                    = 25,
+    CODE_ATTR_StackMapTable          = 0,
+    CODE_ATTR_LineNumberTable        = 1,
+    CODE_ATTR_LocalVariableTable     = 2,
     CODE_ATTR_LocalVariableTypeTable = 3,
     //X_ATTR_Synthetic = 12,  // ACC_SYNTHETIC; not predefined
-    X_ATTR_Signature = 19,
-    X_ATTR_Deprecated = 20,
-    X_ATTR_RuntimeVisibleAnnotations = 21,
+    X_ATTR_Signature                   = 19,
+    X_ATTR_Deprecated                  = 20,
+    X_ATTR_RuntimeVisibleAnnotations   = 21,
     X_ATTR_RuntimeInvisibleAnnotations = 22,
-    X_ATTR_OVERFLOW = 16,
-    X_ATTR_LIMIT_NO_FLAGS_HI = 32,
-    X_ATTR_LIMIT_FLAGS_HI = 63,
+    X_ATTR_OVERFLOW                    = 16,
+    X_ATTR_LIMIT_NO_FLAGS_HI           = 32,
+    X_ATTR_LIMIT_FLAGS_HI              = 63,
 
 #define O_ATTR_DO(F) \
         F(X_ATTR_OVERFLOW,01) \
@@ -121,6 +142,7 @@
         F(CLASS_ATTR_InnerClasses,InnerClasses) \
         F(CLASS_ATTR_EnclosingMethod,EnclosingMethod) \
         F(CLASS_ATTR_ClassFile_version,02) \
+        F(CLASS_ATTR_BootstrapMethods,BootstrapMethods) \
           /*(end)*/
 #define FIELD_ATTR_DO(F) \
         F(FIELD_ATTR_ConstantValue,ConstantValue) \
@@ -175,7 +197,7 @@
     AO_HAVE_SPECIAL_FORMATS   = 1<<0,
     AO_HAVE_CP_NUMBERS        = 1<<1,
     AO_HAVE_ALL_CODE_FLAGS    = 1<<2,
-    AO_3_UNUSED_MBZ           = 1<<3,
+    AO_HAVE_CP_EXTRAS         = 1<<3,
     AO_HAVE_FILE_HEADERS      = 1<<4,
     AO_DEFLATE_HINT           = 1<<5,
     AO_HAVE_FILE_MODTIME      = 1<<6,
@@ -185,11 +207,13 @@
     AO_HAVE_FIELD_FLAGS_HI    = 1<<10,
     AO_HAVE_METHOD_FLAGS_HI   = 1<<11,
     AO_HAVE_CODE_FLAGS_HI     = 1<<12,
+    AO_UNUSED_MBZ             = (-1)<<13, // options bits reserved for future use.
+
 #define ARCHIVE_BIT_DO(F) \
          F(AO_HAVE_SPECIAL_FORMATS) \
          F(AO_HAVE_CP_NUMBERS) \
          F(AO_HAVE_ALL_CODE_FLAGS) \
-         /*F(AO_3_UNUSED_MBZ)*/ \
+         F(AO_HAVE_CP_EXTRAS) \
          F(AO_HAVE_FILE_HEADERS) \
          F(AO_DEFLATE_HINT) \
          F(AO_HAVE_FILE_MODTIME) \
@@ -215,14 +239,14 @@
     NO_MODTIME = 0,  // null modtime value
 
     // meta-coding
-    _meta_default = 0,
+    _meta_default   = 0,
     _meta_canon_min = 1,
     _meta_canon_max = 115,
-    _meta_arb = 116,
-    _meta_run = 117,
-    _meta_pop = 141,
-    _meta_limit = 189,
-    _meta_error = 255,
+    _meta_arb       = 116,
+    _meta_run       = 117,
+    _meta_pop       = 141,
+    _meta_limit     = 189,
+    _meta_error     = 255,
 
     _xxx_1_end
 };
@@ -416,7 +440,7 @@
   bc_invokespecial        = 183, // 0xb7
   bc_invokestatic         = 184, // 0xb8
   bc_invokeinterface      = 185, // 0xb9
-  bc_xxxunusedxxx         = 186, // 0xba
+  bc_invokedynamic        = 186, // 0xba
   bc_new                  = 187, // 0xbb
   bc_newarray             = 188, // 0xbc
   bc_anewarray            = 189, // 0xbd
@@ -455,17 +479,19 @@
   _invokeinit_limit = _invokeinit_op+3,
 
   _xldc_op = _invokeinit_limit,
-  bc_aldc = bc_ldc,
+  bc_sldc = bc_ldc,      // previously named bc_aldc
   bc_cldc = _xldc_op+0,
   bc_ildc = _xldc_op+1,
   bc_fldc = _xldc_op+2,
-  bc_aldc_w = bc_ldc_w,
+  bc_sldc_w = bc_ldc_w,  // previously named bc_aldc_w
   bc_cldc_w = _xldc_op+3,
   bc_ildc_w = _xldc_op+4,
   bc_fldc_w = _xldc_op+5,
   bc_lldc2_w = bc_ldc2_w,
   bc_dldc2_w = _xldc_op+6,
-  _xldc_limit = _xldc_op+7,
-
+  // anything other primitive, string, or class must be handled with qldc:
+  bc_qldc    = _xldc_op+7,
+  bc_qldc_w  = _xldc_op+8,
+  _xldc_limit = _xldc_op+9,
   _xxx_3_end
 };
--- a/jdk/src/share/native/com/sun/java/util/jar/pack/defines.h	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/src/share/native/com/sun/java/util/jar/pack/defines.h	Wed Jul 05 18:10:27 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -109,7 +109,8 @@
 #define dup2(a,b)       _dup2(a,b)
 #define strcasecmp(s1, s2) _stricmp(s1,s2)
 #define tempname        _tempname
-#define sleep Sleep
+#define sleep           Sleep
+#define snprintf        _snprintf
 #else
 typedef signed char byte;
 #ifdef _LP64
--- a/jdk/src/share/native/com/sun/java/util/jar/pack/unpack.cpp	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/src/share/native/com/sun/java/util/jar/pack/unpack.cpp	Wed Jul 05 18:10:27 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -81,7 +81,12 @@
   CONSTANT_NameandType,
   CONSTANT_Fieldref,
   CONSTANT_Methodref,
-  CONSTANT_InterfaceMethodref
+  CONSTANT_InterfaceMethodref,
+  // constants defined as of JDK 7
+  CONSTANT_MethodHandle,
+  CONSTANT_MethodType,
+  CONSTANT_BootstrapMethod,
+  CONSTANT_InvokeDynamic
 };
 #define N_TAGS_IN_ORDER (sizeof TAGS_IN_ORDER)
 
@@ -101,6 +106,11 @@
   "InterfaceMethodref",
   "NameandType",
   "*Signature",
+  "unused14",
+  "MethodHandle",
+  "MethodType",
+  "*BootstrapMethod",
+  "InvokeDynamic",
   0
 };
 
@@ -114,9 +124,13 @@
 
 #endif
 
-
-// REQUESTED must be -2 for u2 and REQUESTED_LDC must be -1 for u1
-enum { NOT_REQUESTED = 0, REQUESTED = -2, REQUESTED_LDC = -1 };
+// Note that REQUESTED_LDC comes first, then the normal REQUESTED,
+// in the regular constant pool.
+enum { REQUESTED_NONE = -1,
+       // The codes below REQUESTED_NONE are in constant pool output order,
+       // for the sake of outputEntry_cmp:
+       REQUESTED_LDC = -99, REQUESTED
+};
 
 #define NO_INORD ((uint)-1)
 
@@ -146,7 +160,7 @@
 
   void requestOutputIndex(cpool& cp, int req = REQUESTED);
   int getOutputIndex() {
-    assert(outputIndex > NOT_REQUESTED);
+    assert(outputIndex > REQUESTED_NONE);
     return outputIndex;
   }
 
@@ -167,12 +181,12 @@
   }
 
   entry* memberClass() {
-    assert(tagMatches(CONSTANT_Member));
+    assert(tagMatches(CONSTANT_AnyMember));
     return ref(0);
   }
 
   entry* memberDescr() {
-    assert(tagMatches(CONSTANT_Member));
+    assert(tagMatches(CONSTANT_AnyMember));
     return ref(1);
   }
 
@@ -199,9 +213,9 @@
     return (tag2 == tag)
       || (tag2 == CONSTANT_Utf8 && tag == CONSTANT_Signature)
       #ifndef PRODUCT
-      || (tag2 == CONSTANT_Literal
+      || (tag2 == CONSTANT_FieldSpecific
           && tag >= CONSTANT_Integer && tag <= CONSTANT_String && tag != CONSTANT_Class)
-      || (tag2 == CONSTANT_Member
+      || (tag2 == CONSTANT_AnyMember
           && tag >= CONSTANT_Fieldref && tag <= CONSTANT_InterfaceMethodref)
       #endif
       ;
@@ -309,6 +323,7 @@
   code_fixup_offset.free();
   code_fixup_source.free();
   requested_ics.free();
+  cp.requested_bsms.free();
   cur_classfile_head.free();
   cur_classfile_tail.free();
   for (i = 0; i < ATTR_CONTEXT_LIMIT; i++)
@@ -448,12 +463,12 @@
 int unpacker::putref_index(entry* e, int size) {
   if (e == null)
     return 0;
-  else if (e->outputIndex > NOT_REQUESTED)
+  else if (e->outputIndex > REQUESTED_NONE)
     return e->outputIndex;
   else if (e->tag == CONSTANT_Signature)
     return putref_index(e->ref(0), size);
   else {
-    e->requestOutputIndex(cp, -size);
+    e->requestOutputIndex(cp, (size == 1 ? REQUESTED_LDC : REQUESTED));
     // Later on we'll fix the bits.
     class_fixup_type.addByte(size);
     class_fixup_offset.add((int)wpoffset());
@@ -515,28 +530,33 @@
   b.copyFrom(ptr, len);
 }
 
+bool testBit(int archive_options, int bitMask) {
+    return (archive_options & bitMask) != 0;
+}
+
 // Read up through band_headers.
 // Do the archive_size dance to set the size of the input mega-buffer.
 void unpacker::read_file_header() {
   // Read file header to determine file type and total size.
   enum {
     MAGIC_BYTES = 4,
-    AH_LENGTH_0 = 3,  //minver, majver, options are outside of archive_size
+    AH_LENGTH_0 = 3,  // archive_header_0 = {minver, majver, options}
+    AH_LENGTH_MIN = 15, // observed in spec {header_0[3], cp_counts[8], class_counts[4]}
     AH_LENGTH_0_MAX = AH_LENGTH_0 + 1,  // options might have 2 bytes
-    AH_LENGTH   = 26, //maximum archive header length (w/ all fields)
+    AH_LENGTH   = 30, //maximum archive header length (w/ all fields)
     // Length contributions from optional header fields:
-    AH_FILE_HEADER_LEN = 5, // sizehi/lo/next/modtime/files
-    AH_ARCHIVE_SIZE_LEN = 2, // sizehi/lo only; part of AH_FILE_HEADER_LEN
-    AH_CP_NUMBER_LEN = 4,  // int/float/long/double
-    AH_SPECIAL_FORMAT_LEN = 2, // layouts/band-headers
-    AH_LENGTH_MIN = AH_LENGTH
-        -(AH_FILE_HEADER_LEN+AH_SPECIAL_FORMAT_LEN+AH_CP_NUMBER_LEN),
-    ARCHIVE_SIZE_MIN = AH_LENGTH_MIN - (AH_LENGTH_0 + AH_ARCHIVE_SIZE_LEN),
+    AH_LENGTH_S = 2, // archive_header_S = optional {size_hi, size_lo}
+    AH_ARCHIVE_SIZE_HI = 0, // offset in archive_header_S
+    AH_ARCHIVE_SIZE_LO = 1, // offset in archive_header_S
+    AH_FILE_HEADER_LEN = 5, // file_counts = {{size_hi, size_lo), next, modtile, files}
+    AH_SPECIAL_FORMAT_LEN = 2, // special_count = {layouts, band_headers}
+    AH_CP_NUMBER_LEN = 4,      // cp_number_counts = {int, float, long, double}
+    AH_CP_EXTRA_LEN = 4,        // cp_attr_counts = {MH, MT, InDy, BSM}
+    ARCHIVE_SIZE_MIN = AH_LENGTH_MIN - AH_LENGTH_0 - AH_LENGTH_S,
     FIRST_READ  = MAGIC_BYTES + AH_LENGTH_MIN
   };
 
   assert(AH_LENGTH_MIN    == 15); // # of UNSIGNED5 fields required after archive_magic
-  assert(ARCHIVE_SIZE_MIN == 10); // # of UNSIGNED5 fields required after archive_size
   // An absolute minimum null archive is magic[4], {minver,majver,options}[3],
   // archive_size[0], cp_counts[8], class_counts[4], for a total of 19 bytes.
   // (Note that archive_size is optional; it may be 0..10 bytes in length.)
@@ -622,23 +642,32 @@
   // Read the first 3 values from the header.
   value_stream hdr;
   int          hdrVals = 0;
-  int          hdrValsSkipped = 0;  // debug only
+  int          hdrValsSkipped = 0;  // for assert
   hdr.init(rp, rplimit, UNSIGNED5_spec);
   minver = hdr.getInt();
   majver = hdr.getInt();
   hdrVals += 2;
 
-  if (magic != (int)JAVA_PACKAGE_MAGIC ||
-      (majver != JAVA5_PACKAGE_MAJOR_VERSION  &&
-       majver != JAVA6_PACKAGE_MAJOR_VERSION) ||
-      (minver != JAVA5_PACKAGE_MINOR_VERSION  &&
-       minver != JAVA6_PACKAGE_MINOR_VERSION)) {
+  int majmin[3][2] = {
+      {JAVA5_PACKAGE_MAJOR_VERSION, JAVA5_PACKAGE_MINOR_VERSION},
+      {JAVA6_PACKAGE_MAJOR_VERSION, JAVA6_PACKAGE_MINOR_VERSION},
+      {JAVA7_PACKAGE_MAJOR_VERSION, JAVA7_PACKAGE_MINOR_VERSION}
+  };
+  int majminfound = false;
+  for (int i = 0 ; i < 3 ; i++) {
+      if (majver == majmin[i][0] && minver == majmin[i][1]) {
+          majminfound = true;
+          break;
+      }
+  }
+  if (majminfound == null) {
     char message[200];
     sprintf(message, "@" ERROR_FORMAT ": magic/ver = "
-            "%08X/%d.%d should be %08X/%d.%d OR %08X/%d.%d\n",
+            "%08X/%d.%d should be %08X/%d.%d OR %08X/%d.%d OR %08X/%d.%d\n",
             magic, majver, minver,
             JAVA_PACKAGE_MAGIC, JAVA5_PACKAGE_MAJOR_VERSION, JAVA5_PACKAGE_MINOR_VERSION,
-            JAVA_PACKAGE_MAGIC, JAVA6_PACKAGE_MAJOR_VERSION, JAVA6_PACKAGE_MINOR_VERSION);
+            JAVA_PACKAGE_MAGIC, JAVA6_PACKAGE_MAJOR_VERSION, JAVA6_PACKAGE_MINOR_VERSION,
+            JAVA_PACKAGE_MAGIC, JAVA7_PACKAGE_MAJOR_VERSION, JAVA7_PACKAGE_MINOR_VERSION);
     abort(message);
   }
   CHECK;
@@ -646,18 +675,26 @@
   archive_options = hdr.getInt();
   hdrVals += 1;
   assert(hdrVals == AH_LENGTH_0);  // first three fields only
-
-#define ORBIT(bit) |(bit)
-  int OPTION_LIMIT = (0 ARCHIVE_BIT_DO(ORBIT));
-#undef ORBIT
-  if ((archive_options & ~OPTION_LIMIT) != 0) {
-    fprintf(errstrm, "Warning: Illegal archive options 0x%x\n",
-        archive_options);
-    abort("illegal archive options");
+  bool haveSizeHi = testBit(archive_options, AO_HAVE_FILE_SIZE_HI);
+  bool haveModTime = testBit(archive_options, AO_HAVE_FILE_MODTIME);
+  bool haveFileOpt = testBit(archive_options, AO_HAVE_FILE_OPTIONS);
+
+  bool haveSpecial = testBit(archive_options, AO_HAVE_SPECIAL_FORMATS);
+  bool haveFiles = testBit(archive_options, AO_HAVE_FILE_HEADERS);
+  bool haveNumbers = testBit(archive_options, AO_HAVE_CP_NUMBERS);
+  bool haveCPExtra = testBit(archive_options, AO_HAVE_CP_EXTRAS);
+
+  if (majver < JAVA7_PACKAGE_MAJOR_VERSION) {
+    if (haveCPExtra) {
+        abort("Format bits for Java 7 must be zero in previous releases");
+        return;
+    }
+  }
+  if (testBit(archive_options, AO_UNUSED_MBZ)) {
+    abort("High archive option bits are reserved and must be zero");
     return;
   }
-
-  if ((archive_options & AO_HAVE_FILE_HEADERS) != 0) {
+  if (haveFiles) {
     uint hi = hdr.getInt();
     uint lo = hdr.getInt();
     julong x = band::makeLong(hi, lo);
@@ -738,13 +775,23 @@
     return;
   }
 
-  // read the rest of the header fields
-  ensure_input((AH_LENGTH-AH_LENGTH_0) * B_MAX);
+  // read the rest of the header fields  int assertSkipped = AH_LENGTH_MIN - AH_LENGTH_0 - AH_LENGTH_S;
+  int remainingHeaders = AH_LENGTH_MIN - AH_LENGTH_0 - AH_LENGTH_S;
+  if (haveSpecial)
+    remainingHeaders += AH_SPECIAL_FORMAT_LEN;
+  if (haveFiles)
+     remainingHeaders += AH_FILE_HEADER_LEN;
+  if (haveNumbers)
+    remainingHeaders += AH_CP_NUMBER_LEN;
+  if (haveCPExtra)
+    remainingHeaders += AH_CP_EXTRA_LEN;
+
+  ensure_input(remainingHeaders * B_MAX);
   CHECK;
   hdr.rp      = rp;
   hdr.rplimit = rplimit;
 
-  if ((archive_options & AO_HAVE_FILE_HEADERS) != 0) {
+  if (haveFiles) {
     archive_next_count = hdr.getInt();
     CHECK_COUNT(archive_next_count);
     archive_modtime = hdr.getInt();
@@ -755,7 +802,7 @@
     hdrValsSkipped += 3;
   }
 
-  if ((archive_options & AO_HAVE_SPECIAL_FORMATS) != 0) {
+  if (haveSpecial) {
     band_headers_size = hdr.getInt();
     CHECK_COUNT(band_headers_size);
     attr_definition_count = hdr.getInt();
@@ -767,7 +814,7 @@
 
   int cp_counts[N_TAGS_IN_ORDER];
   for (int k = 0; k < (int)N_TAGS_IN_ORDER; k++) {
-    if (!(archive_options & AO_HAVE_CP_NUMBERS)) {
+    if (!haveNumbers) {
       switch (TAGS_IN_ORDER[k]) {
       case CONSTANT_Integer:
       case CONSTANT_Float:
@@ -778,6 +825,17 @@
         continue;
       }
     }
+    if (!haveCPExtra) {
+        switch(TAGS_IN_ORDER[k]) {
+        case CONSTANT_MethodHandle:
+        case CONSTANT_MethodType:
+        case CONSTANT_InvokeDynamic:
+        case CONSTANT_BootstrapMethod:
+          cp_counts[k] = 0;
+          hdrValsSkipped += 1;
+          continue;
+        }
+    }
     cp_counts[k] = hdr.getInt();
     CHECK_COUNT(cp_counts[k]);
     hdrVals += 1;
@@ -791,36 +849,26 @@
   CHECK_COUNT(class_count);
   hdrVals += 4;
 
-  // done with archive_header
+  // done with archive_header, time to reconcile to ensure
+  // we have read everything correctly
   hdrVals += hdrValsSkipped;
   assert(hdrVals == AH_LENGTH);
-#ifndef PRODUCT
-  int assertSkipped = AH_LENGTH - AH_LENGTH_MIN;
-  if ((archive_options & AO_HAVE_FILE_HEADERS) != 0)
-    assertSkipped -= AH_FILE_HEADER_LEN;
-  if ((archive_options & AO_HAVE_SPECIAL_FORMATS) != 0)
-    assertSkipped -= AH_SPECIAL_FORMAT_LEN;
-  if ((archive_options & AO_HAVE_CP_NUMBERS) != 0)
-    assertSkipped -= AH_CP_NUMBER_LEN;
-  assert(hdrValsSkipped == assertSkipped);
-#endif //PRODUCT
-
   rp = hdr.rp;
   if (rp > rplimit)
     abort("EOF reading archive header");
 
   // Now size the CP.
 #ifndef PRODUCT
-  bool x = (N_TAGS_IN_ORDER == cpool::NUM_COUNTS);
-  assert(x);
+  // bool x = (N_TAGS_IN_ORDER == CONSTANT_Limit);
+  // assert(x);
 #endif //PRODUCT
   cp.init(this, cp_counts);
   CHECK;
 
   default_file_modtime = archive_modtime;
-  if (default_file_modtime == 0 && !(archive_options & AO_HAVE_FILE_MODTIME))
+  if (default_file_modtime == 0 && haveModTime)
     default_file_modtime = DEFAULT_ARCHIVE_MODTIME;  // taken from driver
-  if ((archive_options & AO_DEFLATE_HINT) != 0)
+  if (testBit(archive_options, AO_DEFLATE_HINT))
     default_file_options |= FO_DEFLATE_HINT;
 
   // meta-bytes, if any, immediately follow archive header
@@ -876,7 +924,7 @@
 
 
 // Cf. PackageReader.readConstantPoolCounts
-void cpool::init(unpacker* u_, int counts[NUM_COUNTS]) {
+void cpool::init(unpacker* u_, int counts[CONSTANT_Limit]) {
   this->u = u_;
 
   // Fill-pointer for CP.
@@ -924,13 +972,16 @@
   first_extra_entry = &entries[nentries];
 
   // Initialize the standard indexes.
-  tag_count[CONSTANT_All] = nentries;
-  tag_base[ CONSTANT_All] = 0;
   for (int tag = 0; tag < CONSTANT_Limit; tag++) {
     entry* cpMap = &entries[tag_base[tag]];
     tag_index[tag].init(tag_count[tag], cpMap, tag);
   }
 
+  // Initialize *all* our entries once
+  for (int i = 0 ; i < maxentries ; i++)
+    entries[i].outputIndex = REQUESTED_NONE;
+
+  initGroupIndexes();
   // Initialize hashTab to a generous power-of-two size.
   uint pow2 = 1;
   uint target = maxentries + maxentries/2;  // 60% full
@@ -1281,6 +1332,70 @@
   //cp_Signature_classes.done();
 }
 
+maybe_inline
+void unpacker::checkLegacy(const char* name) {
+  if (u->majver < JAVA7_PACKAGE_MAJOR_VERSION) {
+      char message[100];
+      snprintf(message, 99, "unexpected band %s\n", name);
+      abort(message);
+  }
+}
+
+maybe_inline
+void unpacker::read_method_handle(entry* cpMap, int len) {
+  if (len > 0) {
+    checkLegacy(cp_MethodHandle_refkind.name);
+  }
+  cp_MethodHandle_refkind.readData(len);
+  cp_MethodHandle_member.setIndexByTag(CONSTANT_AnyMember);
+  cp_MethodHandle_member.readData(len);
+  for (int i = 0 ; i < len ; i++) {
+    entry& e = cpMap[i];
+    e.value.i = cp_MethodHandle_refkind.getInt();
+    e.refs = U_NEW(entry*, e.nrefs = 1);
+    e.refs[0] = cp_MethodHandle_member.getRef();
+    CHECK;
+  }
+}
+
+maybe_inline
+void unpacker::read_method_type(entry* cpMap, int len) {
+  if (len > 0) {
+    checkLegacy(cp_MethodType.name);
+  }
+  cp_MethodType.setIndexByTag(CONSTANT_Signature);
+  cp_MethodType.readData(len);
+  for (int i = 0 ; i < len ; i++) {
+      entry& e = cpMap[i];
+      e.refs = U_NEW(entry*, e.nrefs = 1);
+      e.refs[0] = cp_MethodType.getRef();
+  }
+}
+
+maybe_inline
+void unpacker::read_bootstrap_methods(entry* cpMap, int len) {
+  if (len > 0) {
+    checkLegacy(cp_BootstrapMethod_ref.name);
+  }
+  cp_BootstrapMethod_ref.setIndexByTag(CONSTANT_MethodHandle);
+  cp_BootstrapMethod_ref.readData(len);
+
+  cp_BootstrapMethod_arg_count.readData(len);
+  int totalArgCount = cp_BootstrapMethod_arg_count.getIntTotal();
+  cp_BootstrapMethod_arg.setIndexByTag(CONSTANT_LoadableValue);
+  cp_BootstrapMethod_arg.readData(totalArgCount);
+  for (int i = 0; i < len; i++) {
+    entry& e = cpMap[i];
+    int argc = cp_BootstrapMethod_arg_count.getInt();
+    e.value.i = argc;
+    e.refs = U_NEW(entry*, e.nrefs = argc + 1);
+    e.refs[0] = cp_BootstrapMethod_ref.getRef();
+    for (int j = 1 ; j < e.nrefs ; j++) {
+      e.refs[j] = cp_BootstrapMethod_arg.getRef();
+      CHECK;
+    }
+  }
+}
 // Cf. PackageReader.readConstantPool
 void unpacker::read_cp() {
   byte* rp0 = rp;
@@ -1298,6 +1413,14 @@
       cpMap[i].tag = tag;
       cpMap[i].inord = i;
     }
+    // Initialize the tag's CP index right away, since it might be needed
+    // in the next pass to initialize the CP for another tag.
+#ifndef PRODUCT
+    cpindex* ix = &cp.tag_index[tag];
+    assert(ix->ixTag == tag);
+    assert((int)ix->len   == len);
+    assert(ix->base1 == cpMap);
+#endif
 
     switch (tag) {
     case CONSTANT_Utf8:
@@ -1344,19 +1467,27 @@
                        CONSTANT_Class, CONSTANT_NameandType,
                        cpMap, len);
       break;
+    case CONSTANT_MethodHandle:
+      // consumes cp_MethodHandle_refkind and cp_MethodHandle_member
+      read_method_handle(cpMap, len);
+      break;
+    case CONSTANT_MethodType:
+      // consumes cp_MethodType
+      read_method_type(cpMap, len);
+      break;
+    case CONSTANT_InvokeDynamic:
+      read_double_refs(cp_InvokeDynamic_spec, CONSTANT_BootstrapMethod,
+                       CONSTANT_NameandType,
+                       cpMap, len);
+      break;
+    case CONSTANT_BootstrapMethod:
+      // consumes cp_BootstrapMethod_ref, cp_BootstrapMethod_arg_count and cp_BootstrapMethod_arg
+      read_bootstrap_methods(cpMap, len);
+      break;
     default:
       assert(false);
       break;
     }
-
-    // Initialize the tag's CP index right away, since it might be needed
-    // in the next pass to initialize the CP for another tag.
-#ifndef PRODUCT
-    cpindex* ix = &cp.tag_index[tag];
-    assert(ix->ixTag == tag);
-    assert((int)ix->len   == len);
-    assert(ix->base1 == cpMap);
-#endif
     CHECK;
   }
 
@@ -1791,7 +1922,12 @@
           case 'F': ixTag = CONSTANT_Float; break;
           case 'D': ixTag = CONSTANT_Double; break;
           case 'S': ixTag = CONSTANT_String; break;
-          case 'Q': ixTag = CONSTANT_Literal; break;
+          case 'Q': ixTag = CONSTANT_FieldSpecific; break;
+
+          // new in 1.7
+          case 'M': ixTag = CONSTANT_MethodHandle; break;
+          case 'T': ixTag = CONSTANT_MethodType; break;
+          case 'L': ixTag = CONSTANT_LoadableValue; break;
           }
         } else {
           switch (*lp++) {
@@ -1803,6 +1939,11 @@
           case 'I': ixTag = CONSTANT_InterfaceMethodref; break;
           case 'U': ixTag = CONSTANT_Utf8; break; //utf8_ref
           case 'Q': ixTag = CONSTANT_All; break; //untyped_ref
+
+          // new in 1.7
+          case 'Y': ixTag = CONSTANT_InvokeDynamic; break;
+          case 'B': ixTag = CONSTANT_BootstrapMethod; break;
+          case 'N': ixTag = CONSTANT_AnyMember; break;
           }
         }
         if (ixTag == CONSTANT_None) {
@@ -1873,13 +2014,13 @@
 
   // Decide whether bands for the optional high flag words are present.
   attr_defs[ATTR_CONTEXT_CLASS]
-    .setHaveLongFlags((archive_options & AO_HAVE_CLASS_FLAGS_HI) != 0);
+    .setHaveLongFlags(testBit(archive_options, AO_HAVE_CLASS_FLAGS_HI));
   attr_defs[ATTR_CONTEXT_FIELD]
-    .setHaveLongFlags((archive_options & AO_HAVE_FIELD_FLAGS_HI) != 0);
+    .setHaveLongFlags(testBit(archive_options, AO_HAVE_FIELD_FLAGS_HI));
   attr_defs[ATTR_CONTEXT_METHOD]
-    .setHaveLongFlags((archive_options & AO_HAVE_METHOD_FLAGS_HI) != 0);
+    .setHaveLongFlags(testBit(archive_options, AO_HAVE_METHOD_FLAGS_HI));
   attr_defs[ATTR_CONTEXT_CODE]
-    .setHaveLongFlags((archive_options & AO_HAVE_CODE_FLAGS_HI) != 0);
+    .setHaveLongFlags(testBit(archive_options, AO_HAVE_CODE_FLAGS_HI));
 
   // Set up built-in attrs.
   // (The simple ones are hard-coded.  The metadata layouts are not.)
@@ -2579,7 +2720,7 @@
       // It has data, so unparse an element.
       if (b.ixTag != CONSTANT_None) {
         assert(le_kind == EK_REF);
-        if (b.ixTag == CONSTANT_Literal)
+        if (b.ixTag == CONSTANT_FieldSpecific)
           e = b.getRefUsing(cp.getKQIndex());
         else
           e = b.getRefN();
@@ -2653,13 +2794,13 @@
 
 void unpacker::read_files() {
   file_name.readData(file_count);
-  if ((archive_options & AO_HAVE_FILE_SIZE_HI) != 0)
+  if (testBit(archive_options, AO_HAVE_FILE_SIZE_HI))
     file_size_hi.readData(file_count);
   file_size_lo.readData(file_count);
-  if ((archive_options & AO_HAVE_FILE_MODTIME) != 0)
+  if (testBit(archive_options, AO_HAVE_FILE_MODTIME))
     file_modtime.readData(file_count);
   int allFiles = file_count + class_count;
-  if ((archive_options & AO_HAVE_FILE_OPTIONS) != 0) {
+  if (testBit(archive_options, AO_HAVE_FILE_OPTIONS)) {
     file_options.readData(file_count);
     // FO_IS_CLASS_STUB might be set, causing overlap between classes and files
     for (int i = 0; i < file_count; i++) {
@@ -2703,7 +2844,7 @@
   max_stack     = sc % mod;
   max_na_locals = sc / mod;  // caller must add static, siglen
   handler_count = nh;
-  if ((archive_options & AO_HAVE_ALL_CODE_FLAGS) != 0)
+  if (testBit(archive_options, AO_HAVE_ALL_CODE_FLAGS))
     cflags      = -1;
   else
     cflags      = 0;  // this one has no attributes
@@ -2777,12 +2918,14 @@
     return &bc_longref;
   case bc_dldc2_w:
     return &bc_doubleref;
-  case bc_aldc:
-  case bc_aldc_w:
+  case bc_sldc:
+  case bc_sldc_w:
     return &bc_stringref;
   case bc_cldc:
   case bc_cldc_w:
     return &bc_classref;
+  case bc_qldc: case bc_qldc_w:
+    return &bc_loadablevalueref;
 
   case bc_getstatic:
   case bc_putstatic:
@@ -2796,6 +2939,8 @@
     return &bc_methodref;
   case bc_invokeinterface:
     return &bc_imethodref;
+  case bc_invokedynamic:
+    return &bc_indyref;
 
   case bc_new:
   case bc_anewarray:
@@ -3131,6 +3276,71 @@
   }
 }
 
+bool isLoadableValue(int tag) {
+  switch(tag) {
+    case CONSTANT_Integer:
+    case CONSTANT_Float:
+    case CONSTANT_Long:
+    case CONSTANT_Double:
+    case CONSTANT_String:
+    case CONSTANT_Class:
+    case CONSTANT_MethodHandle:
+    case CONSTANT_MethodType:
+      return true;
+    default:
+      return false;
+  }
+}
+/*
+ * this method can be used to size an array using null as the parameter,
+ * thereafter can be reused to initialize the array using a valid pointer
+ * as a parameter.
+ */
+int cpool::initLoadableValues(entry** loadable_entries) {
+  int loadable_count = 0;
+  for (int i = 0; i < (int)N_TAGS_IN_ORDER; i++) {
+    int tag = TAGS_IN_ORDER[i];
+    if (!isLoadableValue(tag))
+      continue;
+    if (loadable_entries != NULL) {
+      for (int n = 0 ; n < tag_count[tag] ; n++) {
+        loadable_entries[loadable_count + n] = &entries[tag_base[tag] + n];
+      }
+    }
+    loadable_count += tag_count[tag];
+  }
+  return loadable_count;
+}
+
+// Initialize various views into the constant pool.
+void cpool::initGroupIndexes() {
+  // Initialize All
+  int all_count = 0;
+  for (int tag = CONSTANT_None ; tag < CONSTANT_Limit ; tag++) {
+    all_count += tag_count[tag];
+  }
+  entry* all_entries = &entries[tag_base[CONSTANT_None]];
+  tag_group_count[CONSTANT_All - CONSTANT_All] = all_count;
+  tag_group_index[CONSTANT_All - CONSTANT_All].init(all_count, all_entries, CONSTANT_All);
+
+  // Initialize LoadableValues
+  int loadable_count = initLoadableValues(NULL);
+  entry** loadable_entries = U_NEW(entry*, loadable_count);
+  initLoadableValues(loadable_entries);
+  tag_group_count[CONSTANT_LoadableValue - CONSTANT_All] = loadable_count;
+  tag_group_index[CONSTANT_LoadableValue - CONSTANT_All].init(loadable_count,
+                  loadable_entries, CONSTANT_LoadableValue);
+
+// Initialize AnyMembers
+  int any_count = tag_count[CONSTANT_Fieldref] +
+                  tag_count[CONSTANT_Methodref] +
+                  tag_count[CONSTANT_InterfaceMethodref];
+  entry *any_entries = &entries[tag_base[CONSTANT_Fieldref]];
+  tag_group_count[CONSTANT_AnyMember - CONSTANT_All] = any_count;
+  tag_group_index[CONSTANT_AnyMember - CONSTANT_All].init(any_count,
+                                               any_entries, CONSTANT_AnyMember);
+}
+
 void cpool::initMemberIndexes() {
   // This function does NOT refer to any class schema.
   // It is totally internal to the cpool.
@@ -3238,13 +3448,13 @@
 }
 
 void entry::requestOutputIndex(cpool& cp, int req) {
-  assert(outputIndex <= NOT_REQUESTED);  // must not have assigned indexes yet
+  assert(outputIndex <= REQUESTED_NONE);  // must not have assigned indexes yet
   if (tag == CONSTANT_Signature) {
     ref(0)->requestOutputIndex(cp, req);
     return;
   }
   assert(req == REQUESTED || req == REQUESTED_LDC);
-  if (outputIndex != NOT_REQUESTED) {
+  if (outputIndex != REQUESTED_NONE) {
     if (req == REQUESTED_LDC)
       outputIndex = req;  // this kind has precedence
     return;
@@ -3252,31 +3462,52 @@
   outputIndex = req;
   //assert(!cp.outputEntries.contains(this));
   assert(tag != CONSTANT_Signature);
-  cp.outputEntries.add(this);
+  // The BSMs are jetisoned to a side table, however all references
+  // that the BSMs refer to,  need to be considered.
+  if (tag == CONSTANT_BootstrapMethod) {
+    // this is a a pseudo-op entry; an attribute will be generated later on
+    cp.requested_bsms.add(this);
+  } else {
+    // all other tag types go into real output file CP:
+    cp.outputEntries.add(this);
+  }
   for (int j = 0; j < nrefs; j++) {
     ref(j)->requestOutputIndex(cp);
   }
 }
 
 void cpool::resetOutputIndexes() {
-  int i;
-  int    noes =           outputEntries.length();
+    /*
+     * reset those few entries that are being used in the current class
+     * (Caution since this method is called after every class written, a loop
+     * over every global constant pool entry would be a quadratic cost.)
+     */
+
+  int noes    = outputEntries.length();
   entry** oes = (entry**) outputEntries.base();
-  for (i = 0; i < noes; i++) {
+  for (int i = 0 ; i < noes ; i++) {
     entry& e = *oes[i];
-    e.outputIndex = NOT_REQUESTED;
+    e.outputIndex = REQUESTED_NONE;
+  }
+
+  // do the same for bsms and reset them if required
+  int nbsms = requested_bsms.length();
+  entry** boes = (entry**) requested_bsms.base();
+  for (int i = 0 ; i < nbsms ; i++) {
+    entry& e = *boes[i];
+    e.outputIndex = REQUESTED_NONE;
   }
   outputIndexLimit = 0;
   outputEntries.empty();
 #ifndef PRODUCT
-  // they must all be clear now
-  for (i = 0; i < (int)nentries; i++)
-    assert(entries[i].outputIndex == NOT_REQUESTED);
+  // ensure things are cleared out
+  for (int i = 0; i < (int)maxentries; i++)
+    assert(entries[i].outputIndex == REQUESTED_NONE);
 #endif
 }
 
 static const byte TAG_ORDER[CONSTANT_Limit] = {
-  0, 1, 0, 2, 3, 4, 5, 7, 6, 10, 11, 12, 9, 8
+  0, 1, 0, 2, 3, 4, 5, 7, 6, 10, 11, 12, 9, 8, 0, 13, 14, 15, 16
 };
 
 extern "C"
@@ -3323,10 +3554,18 @@
   if (nentries > 100)  checkStep = nentries / 100;
   for (i = (int)(checkStart++ % checkStep); i < (int)nentries; i += checkStep) {
     entry& e = entries[i];
-    if (e.outputIndex != NOT_REQUESTED) {
-      assert(outputEntries.contains(&e));
+    if (e.tag == CONSTANT_BootstrapMethod) {
+      if (e.outputIndex != REQUESTED_NONE) {
+        assert(requested_bsms.contains(&e));
+      } else {
+        assert(!requested_bsms.contains(&e));
+      }
     } else {
-      assert(!outputEntries.contains(&e));
+      if (e.outputIndex != REQUESTED_NONE) {
+        assert(outputEntries.contains(&e));
+      } else {
+        assert(!outputEntries.contains(&e));
+      }
     }
   }
 
@@ -3348,7 +3587,7 @@
   int nextIndex = 1;  // always skip index #0 in output cpool
   for (i = 0; i < noes; i++) {
     entry& e = *oes[i];
-    assert(e.outputIndex == REQUESTED || e.outputIndex == REQUESTED_LDC);
+    assert(e.outputIndex >= REQUESTED_LDC);
     e.outputIndex = nextIndex++;
     if (e.isDoubleWord())  nextIndex++;  // do not use the next index
   }
@@ -3396,7 +3635,7 @@
   default:
     if (nrefs == 0) {
       buf = getbuf(20);
-      sprintf((char*)buf.ptr, "<tag=%d>", tag);
+      sprintf((char*)buf.ptr, TAG_NAME[tag]);
     } else if (nrefs == 1) {
       return refs[0]->string();
     } else {
@@ -3674,6 +3913,7 @@
   class_fixup_offset.empty();
   class_fixup_ref.empty();
   requested_ics.empty();
+  cp.requested_bsms.empty();
 }
 
 cpindex* cpool::getKQIndex() {
@@ -3931,13 +4171,15 @@
         case bc_ildc:
         case bc_cldc:
         case bc_fldc:
-        case bc_aldc:
+        case bc_sldc:
+        case bc_qldc:
           origBC = bc_ldc;
           break;
         case bc_ildc_w:
         case bc_cldc_w:
         case bc_fldc_w:
-        case bc_aldc_w:
+        case bc_sldc_w:
+        case bc_qldc_w:
           origBC = bc_ldc_w;
           break;
         case bc_lldc2_w:
@@ -3962,6 +4204,10 @@
           int argSize = ref->memberDescr()->descrType()->typeSize();
           putu1_fast(1 + argSize);
           putu1_fast(0);
+        } else if (origBC == bc_invokedynamic) {
+          // pad the next two byte
+          putu1_fast(0);
+          putu1_fast(0);
         }
         continue;
       }
@@ -4353,49 +4599,12 @@
   return (p1 > p2)? 1: (p1 < p2)? -1: 0;
 }
 
-void unpacker::write_classfile_tail() {
-  cur_classfile_tail.empty();
-  set_output(&cur_classfile_tail);
-
-  int i, num;
-
-  attr_definitions& ad = attr_defs[ATTR_CONTEXT_CLASS];
-
-  bool haveLongFlags = ad.haveLongFlags();
-  julong kflags = class_flags_hi.getLong(class_flags_lo, haveLongFlags);
-  julong indexMask = ad.flagIndexMask();
-
-  cur_class = class_this.getRef();
-  cur_super = class_super.getRef();
-
-  CHECK;
-
-  if (cur_super == cur_class)  cur_super = null;
-  // special representation for java/lang/Object
-
-  putu2((ushort)(kflags & ~indexMask));
-  putref(cur_class);
-  putref(cur_super);
-
-  putu2(num = class_interface_count.getInt());
-  for (i = 0; i < num; i++) {
-    putref(class_interface.getRef());
-  }
-
-  write_members(class_field_count.getInt(),  ATTR_CONTEXT_FIELD);
-  write_members(class_method_count.getInt(), ATTR_CONTEXT_METHOD);
-  CHECK;
-
-  cur_class_has_local_ics = false;  // may be set true by write_attrs
-
-
-  int naOffset = (int)wpoffset();
-  int na = write_attrs(ATTR_CONTEXT_CLASS, (kflags & indexMask));
-
-
-  // at the very last, choose which inner classes (if any) pertain to k:
+/*
+ * writes the InnerClass attributes and returns the updated attribute
+ */
+int  unpacker::write_ics(int naOffset, int na) {
 #ifdef ASSERT
-  for (i = 0; i < ic_count; i++) {
+  for (int i = 0; i < ic_count; i++) {
     assert(!ics[i].requested);
   }
 #endif
@@ -4416,7 +4625,7 @@
   // include it and all its outers.
   int    noes =           cp.outputEntries.length();
   entry** oes = (entry**) cp.outputEntries.base();
-  for (i = 0; i < noes; i++) {
+  for (int i = 0; i < noes; i++) {
     entry& e = *oes[i];
     if (e.tag != CONSTANT_Class)  continue;  // wrong sort
     for (inner_class* ic = cp.getIC(&e);
@@ -4442,10 +4651,10 @@
       // Note:  extra_ics will be freed up by next call to get_next_file().
     }
   }
-  for (i = 0; i < num_extra_ics; i++) {
+  for (int i = 0; i < num_extra_ics; i++) {
     inner_class& extra_ic = extra_ics[i];
     extra_ic.inner = class_InnerClasses_RC.getRef();
-    CHECK;
+    CHECK_0;
     // Find the corresponding equivalent global IC:
     inner_class* global_ic = cp.getIC(extra_ic.inner);
     int flags = class_InnerClasses_F.getInt();
@@ -4493,7 +4702,7 @@
     putu2(local_ics);
     PTRLIST_QSORT(requested_ics, raw_address_cmp);
     int num_global_ics = requested_ics.length();
-    for (i = -num_global_ics; i < num_extra_ics; i++) {
+    for (int i = -num_global_ics; i < num_extra_ics; i++) {
       inner_class* ic;
       if (i < 0)
         ic = (inner_class*) requested_ics.get(num_global_ics+i);
@@ -4512,17 +4721,99 @@
   }
 
   // Tidy up global 'requested' bits:
-  for (i = requested_ics.length(); --i >= 0; ) {
+  for (int i = requested_ics.length(); --i >= 0; ) {
     inner_class* ic = (inner_class*) requested_ics.get(i);
     ic->requested = false;
   }
   requested_ics.empty();
-
+  return na;
+}
+
+/*
+ * Writes the BootstrapMethods attribute and returns the updated attribute count
+ */
+int unpacker::write_bsms(int naOffset, int na) {
+  cur_class_local_bsm_count = cp.requested_bsms.length();
+  if (cur_class_local_bsm_count > 0) {
+    int    noes =           cp.outputEntries.length();
+    entry** oes = (entry**) cp.outputEntries.base();
+    PTRLIST_QSORT(cp.requested_bsms, outputEntry_cmp);
+    // append the BootstrapMethods attribute (after the InnerClasses attr):
+    putref(cp.sym[cpool::s_BootstrapMethods]);
+    int sizeOffset = (int)wpoffset();
+    byte* sizewp = wp;
+    putu4(-99);  // attr size will be patched
+    putu2(cur_class_local_bsm_count);
+    int written_bsms = 0;
+    for (int i = 0 ; i < cur_class_local_bsm_count ; i++) {
+      entry* e = (entry*)cp.requested_bsms.get(i);
+      assert(e->outputIndex != REQUESTED_NONE);
+      // output index is the index within the array
+      e->outputIndex = i;
+      putref(e->refs[0]);  // bsm
+      putu2(e->nrefs-1);  // number of args after bsm
+      for (int j = 1; j < e->nrefs; j++) {
+        putref(e->refs[j]);
+      }
+      written_bsms += 1;
+    }
+    assert(written_bsms == cur_class_local_bsm_count);  // else insane
+    putu4_at(sizewp, (int)(wp - (sizewp+4)));  // size of code attr
+    putu2_at(wp_at(naOffset), ++na);  // increment class attr count
+  }
+  return na;
+}
+
+void unpacker::write_classfile_tail() {
+
+  cur_classfile_tail.empty();
+  set_output(&cur_classfile_tail);
+
+  int i, num;
+
+  attr_definitions& ad = attr_defs[ATTR_CONTEXT_CLASS];
+
+  bool haveLongFlags = ad.haveLongFlags();
+  julong kflags = class_flags_hi.getLong(class_flags_lo, haveLongFlags);
+  julong indexMask = ad.flagIndexMask();
+
+  cur_class = class_this.getRef();
+  cur_super = class_super.getRef();
   CHECK;
+
+  if (cur_super == cur_class)  cur_super = null;
+  // special representation for java/lang/Object
+
+  putu2((ushort)(kflags & ~indexMask));
+  putref(cur_class);
+  putref(cur_super);
+
+  putu2(num = class_interface_count.getInt());
+  for (i = 0; i < num; i++) {
+    putref(class_interface.getRef());
+  }
+
+  write_members(class_field_count.getInt(),  ATTR_CONTEXT_FIELD);
+  write_members(class_method_count.getInt(), ATTR_CONTEXT_METHOD);
+  CHECK;
+
+  cur_class_has_local_ics = false;  // may be set true by write_attrs
+
+  int naOffset = (int)wpoffset();   // note the attr count location
+  int na = write_attrs(ATTR_CONTEXT_CLASS, (kflags & indexMask));
+  CHECK;
+
+  na = write_bsms(naOffset, na);
+  CHECK;
+
+  // choose which inner classes (if any) pertain to k:
+  na = write_ics(naOffset, na);
+  CHECK;
+
   close_output();
+  cp.computeOutputIndexes();
 
   // rewrite CP references in the tail
-  cp.computeOutputIndexes();
   int nextref = 0;
   for (i = 0; i < (int)class_fixup_type.size(); i++) {
     int    type = class_fixup_type.getByte(i);
@@ -4579,9 +4870,18 @@
     case CONSTANT_Methodref:
     case CONSTANT_InterfaceMethodref:
     case CONSTANT_NameandType:
+    case CONSTANT_InvokeDynamic:
       putu2(e.refs[0]->getOutputIndex());
       putu2(e.refs[1]->getOutputIndex());
       break;
+    case CONSTANT_MethodHandle:
+        putu1(e.value.i);
+        putu2(e.refs[0]->getOutputIndex());
+        break;
+    case CONSTANT_MethodType:
+      putu2(e.refs[0]->getOutputIndex());
+      break;
+    case CONSTANT_BootstrapMethod: // should not happen
     default:
       abort(ERROR_INTERNAL);
     }
@@ -4620,11 +4920,11 @@
     entry* e = file_name.getRef();
     CHECK_0;
     cur_file.name = e->utf8String();
-    bool haveLongSize = ((archive_options & AO_HAVE_FILE_SIZE_HI) != 0);
+    bool haveLongSize = (testBit(archive_options, AO_HAVE_FILE_SIZE_HI));
     cur_file.size = file_size_hi.getLong(file_size_lo, haveLongSize);
-    if ((archive_options & AO_HAVE_FILE_MODTIME) != 0)
+    if (testBit(archive_options, AO_HAVE_FILE_MODTIME))
       cur_file.modtime += file_modtime.getInt();  //relative to archive modtime
-    if ((archive_options & AO_HAVE_FILE_OPTIONS) != 0)
+    if (testBit(archive_options, AO_HAVE_FILE_OPTIONS))
       cur_file.options |= file_options.getInt() & ~suppress_file_options;
   } else if (classes_written < class_count) {
     // there is a class for a missing file record
--- a/jdk/src/share/native/com/sun/java/util/jar/pack/unpack.h	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/src/share/native/com/sun/java/util/jar/pack/unpack.h	Wed Jul 05 18:10:27 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -22,9 +22,6 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-
-
-
 // Global Structures
 struct jar;
 struct gunzip;
@@ -70,6 +67,9 @@
   cpindex tag_index[CONSTANT_Limit];
   ptrlist tag_extras[CONSTANT_Limit];
 
+  int     tag_group_count[CONSTANT_GroupLimit - CONSTANT_GroupFirst];
+  cpindex tag_group_index[CONSTANT_GroupLimit - CONSTANT_GroupFirst];
+
   cpindex* member_indexes;   // indexed by 2*CONSTANT_Class.inord
   cpindex* getFieldIndex(entry* classRef);
   cpindex* getMethodIndex(entry* classRef);
@@ -82,6 +82,7 @@
 
   int outputIndexLimit;  // index limit after renumbering
   ptrlist outputEntries; // list of entry* needing output idx assigned
+  ptrlist requested_bsms; // which bsms need output?
 
   entry** hashTab;
   uint    hashTabLength;
@@ -100,24 +101,36 @@
   entry* sym[s_LIMIT];
 
   // read counts from hdr, allocate main arrays
-  enum { NUM_COUNTS = 12 };
-  void init(unpacker* u, int counts[NUM_COUNTS]);
+  void init(unpacker* u, int counts[CONSTANT_Limit]);
 
   // pointer to outer unpacker, for error checks etc.
   unpacker* u;
 
   int getCount(byte tag) {
-    assert((uint)tag < CONSTANT_Limit);
-    return tag_count[tag];
+    if ((uint)tag >= CONSTANT_GroupFirst) {
+      assert((uint)tag < CONSTANT_GroupLimit);
+      return tag_group_count[(uint)tag - CONSTANT_GroupFirst];
+    } else {
+      assert((uint)tag < CONSTANT_Limit);
+      return tag_count[(uint)tag];
+    }
   }
   cpindex* getIndex(byte tag) {
-    assert((uint)tag < CONSTANT_Limit);
-    return &tag_index[tag];
+    if ((uint)tag >= CONSTANT_GroupFirst) {
+      assert((uint)tag < CONSTANT_GroupLimit);
+      return &tag_group_index[(uint)tag - CONSTANT_GroupFirst];
+    } else {
+      assert((uint)tag < CONSTANT_Limit);
+      return &tag_index[(uint)tag];
+    }
   }
+
   cpindex* getKQIndex();  // uses cur_descr
 
   void expandSignatures();
+  void initGroupIndexes();
   void initMemberIndexes();
+  int  initLoadableValues(entry** loadable_entries);
 
   void computeOutputOrder();
   void computeOutputIndexes();
@@ -234,6 +247,7 @@
   int       cur_descr_flags;  // flags corresponding to cur_descr
   int       cur_class_minver, cur_class_majver;
   bool      cur_class_has_local_ics;
+  int       cur_class_local_bsm_count;
   fillbytes cur_classfile_head;
   fillbytes cur_classfile_tail;
   int       files_written;   // also tells which file we're working on
@@ -412,7 +426,7 @@
   void         abort(const char* s = null);
   bool         aborting() { return abort_message != null; }
   static unpacker* current();  // find current instance
-
+  void checkLegacy(const char* name);
   // Output management
   void set_output(fillbytes* which) {
     assert(wp == null);
@@ -464,6 +478,8 @@
   void write_bc_ops();
   void write_members(int num, int attrc);  // attrc=ATTR_CONTEXT_FIELD/METHOD
   int  write_attrs(int attrc, julong indexBits);
+  int  write_ics(int naOffset, int na);
+  int  write_bsms(int naOffset, int na);
 
   // The readers
   void read_bands();
@@ -484,6 +500,9 @@
   void read_single_refs(band& cp_band, byte refTag, entry* cpMap, int len);
   void read_double_refs(band& cp_band, byte ref1Tag, byte ref2Tag, entry* cpMap, int len);
   void read_signature_values(entry* cpMap, int len);
+  void read_method_handle(entry* cpMap, int len);
+  void read_method_type(entry* cpMap, int len);
+  void read_bootstrap_methods(entry* cpMap, int len);
 };
 
 inline void cpool::abort(const char* msg) { u->abort(msg); }
--- a/jdk/src/share/native/java/util/zip/ZipFile.c	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/src/share/native/java/util/zip/ZipFile.c	Wed Jul 05 18:10:27 2017 +0200
@@ -117,6 +117,7 @@
             result = ptr_to_jlong(zip);
         } else if (msg != 0) {
             ThrowZipException(env, msg);
+            free(msg);
         } else if (errno == ENOMEM) {
             JNU_ThrowOutOfMemoryError(env, 0);
         } else {
--- a/jdk/src/share/native/java/util/zip/zip_util.c	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/src/share/native/java/util/zip/zip_util.c	Wed Jul 05 18:10:27 2017 +0200
@@ -726,7 +726,7 @@
  * Opens a zip file with the specified mode. Returns the jzfile object
  * or NULL if an error occurred. If a zip error occurred then *pmsg will
  * be set to the error message text if pmsg != 0. Otherwise, *pmsg will be
- * set to NULL.
+ * set to NULL. Caller is responsible to free the error message.
  */
 jzfile *
 ZIP_Open_Generic(const char *name, char **pmsg, int mode, jlong lastModified)
@@ -751,12 +751,12 @@
  * Returns the jzfile corresponding to the given file name from the cache of
  * zip files, or NULL if the file is not in the cache.  If the name is longer
  * than PATH_MAX or a zip error occurred then *pmsg will be set to the error
- * message text if pmsg != 0. Otherwise, *pmsg will be set to NULL.
+ * message text if pmsg != 0. Otherwise, *pmsg will be set to NULL. Caller
+ * is responsible to free the error message.
  */
 jzfile *
 ZIP_Get_From_Cache(const char *name, char **pmsg, jlong lastModified)
 {
-    static char errbuf[256];
     char buf[PATH_MAX];
     jzfile *zip;
 
@@ -771,7 +771,7 @@
 
     if (strlen(name) >= PATH_MAX) {
         if (pmsg) {
-            *pmsg = "zip file name too long";
+            *pmsg = strdup("zip file name too long");
         }
         return NULL;
     }
@@ -796,7 +796,8 @@
  * Reads data from the given file descriptor to create a jzfile, puts the
  * jzfile in a cache, and returns that jzfile.  Returns NULL in case of error.
  * If a zip error occurs, then *pmsg will be set to the error message text if
- * pmsg != 0. Otherwise, *pmsg will be set to NULL.
+ * pmsg != 0. Otherwise, *pmsg will be set to NULL. Caller is responsible to
+ * free the error message.
  */
 
 jzfile *
@@ -809,7 +810,7 @@
 ZIP_Put_In_Cache0(const char *name, ZFILE zfd, char **pmsg, jlong lastModified,
                  jboolean usemmap)
 {
-    static char errbuf[256];
+    char errbuf[256];
     jlong len;
     jzfile *zip;
 
@@ -825,7 +826,7 @@
 
     if (zfd == -1) {
         if (pmsg && JVM_GetLastErrorString(errbuf, sizeof(errbuf)) > 0)
-            *pmsg = errbuf;
+            *pmsg = strdup(errbuf);
         freeZip(zip);
         return NULL;
     }
@@ -834,11 +835,11 @@
     if (len <= 0) {
         if (len == 0) { /* zip file is empty */
             if (pmsg) {
-                *pmsg = "zip file is empty";
+                *pmsg = strdup("zip file is empty");
             }
         } else { /* error */
             if (pmsg && JVM_GetLastErrorString(errbuf, sizeof(errbuf)) > 0)
-                *pmsg = errbuf;
+                *pmsg = strdup(errbuf);
         }
         ZFILE_Close(zfd);
         freeZip(zip);
@@ -850,7 +851,8 @@
         /* An error occurred while trying to read the zip file */
         if (pmsg != 0) {
             /* Set the zip error message */
-            *pmsg = zip->msg;
+            if (zip->msg != NULL)
+                *pmsg = strdup(zip->msg);
         }
         freeZip(zip);
         return NULL;
@@ -867,12 +869,17 @@
  * Opens a zip file for reading. Returns the jzfile object or NULL
  * if an error occurred. If a zip error occurred then *msg will be
  * set to the error message text if msg != 0. Otherwise, *msg will be
- * set to NULL.
+ * set to NULL. Caller doesn't need to free the error message.
  */
 jzfile * JNICALL
 ZIP_Open(const char *name, char **pmsg)
 {
-    return ZIP_Open_Generic(name, pmsg, O_RDONLY, 0);
+    jzfile *file = ZIP_Open_Generic(name, pmsg, O_RDONLY, 0);
+    if (file == NULL && pmsg != NULL && *pmsg != NULL) {
+        free(*pmsg);
+        *pmsg = "Zip file open error";
+    }
+    return file;
 }
 
 /*
--- a/jdk/src/solaris/classes/sun/awt/X11/XTextAreaPeer.java	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/src/solaris/classes/sun/awt/X11/XTextAreaPeer.java	Wed Jul 05 18:10:27 2017 +0200
@@ -657,10 +657,13 @@
     }
 
 
-    // TODO : fix this duplicate code
-    class XAWTCaret extends DefaultCaret {
+    static class XAWTCaret extends DefaultCaret {
         public void focusGained(FocusEvent e) {
             super.focusGained(e);
+            if (getComponent().isEnabled()){
+                // Make sure the cursor is visible in case of non-editable TextArea
+                super.setVisible(true);
+            }
             getComponent().repaint();
         }
 
--- a/jdk/src/solaris/classes/sun/awt/X11/XTextFieldPeer.java	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/src/solaris/classes/sun/awt/X11/XTextFieldPeer.java	Wed Jul 05 18:10:27 2017 +0200
@@ -578,31 +578,7 @@
         }
 
         protected Caret createCaret() {
-            return new XAWTCaret();
-        }
-    }
-
-    class XAWTCaret extends DefaultCaret {
-        public void focusGained(FocusEvent e) {
-            super.focusGained(e);
-            getComponent().repaint();
-        }
-
-        public void focusLost(FocusEvent e) {
-            super.focusLost(e);
-            getComponent().repaint();
-        }
-
-        // Fix for 5100950: textarea.getSelectedText() returns the de-selected text, on XToolkit
-        // Restoring Motif behaviour
-        // If the text is unhighlighted then we should sets the selection range to zero
-        public void setSelectionVisible(boolean vis) {
-            if (vis){
-                super.setSelectionVisible(vis);
-            }else{
-                // In order to de-select the selection
-                setDot(getDot());
-            }
+            return new XTextAreaPeer.XAWTCaret();
         }
     }
 
--- a/jdk/src/solaris/classes/sun/management/FileSystemImpl.java	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/src/solaris/classes/sun/management/FileSystemImpl.java	Wed Jul 05 18:10:27 2017 +0200
@@ -48,7 +48,12 @@
     // Initialization
 
     static {
-        java.security.AccessController
-            .doPrivileged(new sun.security.action.LoadLibraryAction("management"));
+        java.security.AccessController.doPrivileged(
+            new java.security.PrivilegedAction<Void>() {
+                public Void run() {
+                    System.loadLibrary("management");
+                    return null;
+                }
+            });
     }
 }
--- a/jdk/src/solaris/classes/sun/net/dns/ResolverConfigurationImpl.java	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/src/solaris/classes/sun/net/dns/ResolverConfigurationImpl.java	Wed Jul 05 18:10:27 2017 +0200
@@ -251,7 +251,12 @@
 
     static {
         java.security.AccessController.doPrivileged(
-            new sun.security.action.LoadLibraryAction("net"));
+            new java.security.PrivilegedAction<Void>() {
+                public Void run() {
+                    System.loadLibrary("net");
+                    return null;
+                }
+            });
     }
 
 }
--- a/jdk/src/solaris/classes/sun/nio/ch/DefaultAsynchronousChannelProvider.java	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/src/solaris/classes/sun/nio/ch/DefaultAsynchronousChannelProvider.java	Wed Jul 05 18:10:27 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -50,7 +50,7 @@
             return new SolarisAsynchronousChannelProvider();
         if (osname.equals("Linux"))
             return new LinuxAsynchronousChannelProvider();
-        if (osname.startsWith("Mac OS"))
+        if (osname.contains("OS X"))
             return new BsdAsynchronousChannelProvider();
         throw new InternalError("platform not recognized");
     }
--- a/jdk/src/solaris/classes/sun/nio/ch/sctp/SctpChannelImpl.java	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/src/solaris/classes/sun/nio/ch/sctp/SctpChannelImpl.java	Wed Jul 05 18:10:27 2017 +0200
@@ -1100,7 +1100,12 @@
     static {
         Util.load();   /* loads nio & net native libraries */
         java.security.AccessController.doPrivileged(
-                new sun.security.action.LoadLibraryAction("sctp"));
+            new java.security.PrivilegedAction<Void>() {
+                public Void run() {
+                    System.loadLibrary("sctp");
+                    return null;
+                }
+            });
         initIDs();
     }
 }
--- a/jdk/src/solaris/classes/sun/nio/ch/sctp/SctpMultiChannelImpl.java	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/src/solaris/classes/sun/nio/ch/sctp/SctpMultiChannelImpl.java	Wed Jul 05 18:10:27 2017 +0200
@@ -989,6 +989,11 @@
     static {
         Util.load();   /* loads nio & net native libraries */
         java.security.AccessController.doPrivileged(
-                new sun.security.action.LoadLibraryAction("sctp"));
+            new java.security.PrivilegedAction<Void>() {
+                public Void run() {
+                    System.loadLibrary("sctp");
+                    return null;
+                }
+            });
     }
 }
--- a/jdk/src/solaris/classes/sun/nio/ch/sctp/SctpServerChannelImpl.java	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/src/solaris/classes/sun/nio/ch/sctp/SctpServerChannelImpl.java	Wed Jul 05 18:10:27 2017 +0200
@@ -428,7 +428,12 @@
     static {
         Util.load();   // loads nio & net native libraries
         java.security.AccessController.doPrivileged(
-                new sun.security.action.LoadLibraryAction("sctp"));
+            new java.security.PrivilegedAction<Void>() {
+                public Void run() {
+                    System.loadLibrary("sctp");
+                    return null;
+                }
+            });
         initIDs();
     }
 }
--- a/jdk/src/solaris/classes/sun/nio/fs/DefaultFileSystemProvider.java	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/src/solaris/classes/sun/nio/fs/DefaultFileSystemProvider.java	Wed Jul 05 18:10:27 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -68,7 +68,7 @@
             return createProvider("sun.nio.fs.SolarisFileSystemProvider");
         if (osname.equals("Linux"))
             return createProvider("sun.nio.fs.LinuxFileSystemProvider");
-        if (osname.equals("Darwin") || osname.startsWith("Mac OS X"))
+        if (osname.equals("Darwin") || osname.contains("OS X"))
             return createProvider("sun.nio.fs.BsdFileSystemProvider");
         throw new AssertionError("Platform not recognized");
     }
--- a/jdk/src/solaris/classes/sun/nio/fs/SolarisWatchService.java	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/src/solaris/classes/sun/nio/fs/SolarisWatchService.java	Wed Jul 05 18:10:27 2017 +0200
@@ -314,7 +314,7 @@
             fileKey2WatchKey.put(fileKey, watchKey);
 
             // register all entries in directory
-            registerChildren(dir, watchKey, false);
+            registerChildren(dir, watchKey, false, false);
 
             return watchKey;
         }
@@ -486,7 +486,8 @@
         void processDirectoryEvents(SolarisWatchKey key, int mask) {
             if ((mask & (FILE_MODIFIED | FILE_ATTRIB)) != 0) {
                 registerChildren(key.getDirectory(), key,
-                    key.events().contains(StandardWatchEventKinds.ENTRY_CREATE));
+                    key.events().contains(StandardWatchEventKinds.ENTRY_CREATE),
+                    key.events().contains(StandardWatchEventKinds.ENTRY_DELETE));
             }
         }
 
@@ -535,14 +536,16 @@
         /**
          * Registers all entries in the given directory
          *
-         * The {@code sendEvents} parameter indicates if ENTRY_CREATE events
-         * should be queued when new entries are found. When initially
-         * registering a directory then will always be false. When re-scanning
-         * a directory then it depends on if the event is enabled or not.
+         * The {@code sendCreateEvents} and {@code sendDeleteEvents} parameters
+         * indicates if ENTRY_CREATE and ENTRY_DELETE events should be queued
+         * when new entries are found. When initially registering a directory
+         * they will always be false. When re-scanning a directory then it
+         * depends on if the events are enabled or not.
          */
         void registerChildren(UnixPath dir,
                               SolarisWatchKey parent,
-                              boolean sendEvents)
+                              boolean sendCreateEvents,
+                              boolean sendDeleteEvents)
         {
             // if the ENTRY_MODIFY event is not enabled then we don't need
             // modification events for entries in the directory
@@ -550,14 +553,7 @@
             if (parent.events().contains(StandardWatchEventKinds.ENTRY_MODIFY))
                 events |= (FILE_MODIFIED | FILE_ATTRIB);
 
-            DirectoryStream<Path> stream = null;
-            try {
-                stream = Files.newDirectoryStream(dir);
-            } catch (IOException x) {
-                // nothing we can do
-                return;
-            }
-            try {
+            try (DirectoryStream<Path> stream = Files.newDirectoryStream(dir)) {
                 for (Path entry: stream) {
                     Path name = entry.getFileName();
 
@@ -565,32 +561,34 @@
                     if (parent.getChild(name) != null)
                         continue;
 
-                    // send ENTRY_CREATE if enabled
-                    if (sendEvents) {
-                        parent.signalEvent(StandardWatchEventKinds.ENTRY_CREATE, name);
-                    }
-
-                    // register it
+                    // attempt to register entry
                     long object = 0L;
+                    int errno = 0;
                     try {
                         object = registerImpl((UnixPath)entry, events);
                     } catch (UnixException x) {
-                        // can't register so ignore for now.
-                        continue;
+                        errno = x.errno();
                     }
 
-                    // create node
-                    EntryNode node = new EntryNode(object, entry.getFileName(), parent);
-                    // tell the parent about it
-                    parent.addChild(entry.getFileName(), node);
-                    object2Node.put(object, node);
+                    boolean registered = (object != 0L);
+                    boolean deleted = (errno == ENOENT);
+
+                    if (registered) {
+                        // create node
+                        EntryNode node = new EntryNode(object, entry.getFileName(), parent);
+                        // tell the parent about it
+                        parent.addChild(entry.getFileName(), node);
+                        object2Node.put(object, node);
+                    }
+
+                    if (sendCreateEvents && (registered || deleted))
+                        parent.signalEvent(StandardWatchEventKinds.ENTRY_CREATE, name);
+                    if (sendDeleteEvents && deleted)
+                        parent.signalEvent(StandardWatchEventKinds.ENTRY_DELETE, name);
+
                 }
-            } catch (ConcurrentModificationException x) {
-                // error during iteration which we ignore for now
-            } finally {
-                try {
-                    stream.close();
-                } catch (IOException x) { }
+            } catch (DirectoryIteratorException | IOException x) {
+                // nothing we can do
             }
         }
 
--- a/jdk/src/solaris/classes/sun/print/CUPSPrinter.java	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/src/solaris/classes/sun/print/CUPSPrinter.java	Wed Jul 05 18:10:27 2017 +0200
@@ -77,7 +77,12 @@
     static {
         // load awt library to access native code
         java.security.AccessController.doPrivileged(
-            new sun.security.action.LoadLibraryAction("awt"));
+            new java.security.PrivilegedAction<Void>() {
+                public Void run() {
+                    System.loadLibrary("awt");
+                    return null;
+                }
+            });
         libFound = initIDs();
         if (libFound) {
            cupsServer = getCupsServer();
--- a/jdk/src/solaris/classes/sun/print/UnixPrintServiceLookup.java	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/src/solaris/classes/sun/print/UnixPrintServiceLookup.java	Wed Jul 05 18:10:27 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -120,7 +120,7 @@
 
     static boolean isBSD() {
         return (osname.equals("Linux") ||
-                osname.startsWith("Mac OS X"));
+                osname.contains("OS X"));
     }
 
     static final int UNINITIALIZED = -1;
--- a/jdk/src/solaris/native/java/net/PlainDatagramSocketImpl.c	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/src/solaris/native/java/net/PlainDatagramSocketImpl.c	Wed Jul 05 18:10:27 2017 +0200
@@ -84,6 +84,7 @@
 #endif
 
 extern void setDefaultScopeID(JNIEnv *env, struct sockaddr *him);
+extern int getDefaultScopeID(JNIEnv *env);
 
 /*
  * Returns a java.lang.Integer based on 'i'
@@ -2418,7 +2419,11 @@
                 }
             }
 #endif
-
+#ifdef MACOSX
+            if (family == AF_INET6 && index == 0) {
+                index = getDefaultScopeID(env);
+            }
+#endif
             mname6.ipv6mr_interface = index;
         } else {
             jint idx = (*env)->GetIntField(env, niObj, ni_indexID);
--- a/jdk/src/solaris/native/java/net/net_util_md.c	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/src/solaris/native/java/net/net_util_md.c	Wed Jul 05 18:10:27 2017 +0200
@@ -109,6 +109,24 @@
 #endif
 }
 
+int getDefaultScopeID(JNIEnv *env) {
+    static jclass ni_class = NULL;
+    static jfieldID ni_defaultIndexID;
+    if (ni_class == NULL) {
+        jclass c = (*env)->FindClass(env, "java/net/NetworkInterface");
+        CHECK_NULL(c);
+        c = (*env)->NewGlobalRef(env, c);
+        CHECK_NULL(c);
+        ni_defaultIndexID = (*env)->GetStaticFieldID(env, c,
+                                                     "defaultIndex", "I");
+        ni_class = c;
+    }
+    int defaultIndex = 0;
+    defaultIndex = (*env)->GetStaticIntField(env, ni_class,
+                                             ni_defaultIndexID);
+    return defaultIndex;
+}
+
 #ifdef __solaris__
 static int init_tcp_max_buf, init_udp_max_buf;
 static int tcp_max_buf;
--- a/jdk/src/solaris/native/sun/nio/ch/DatagramChannelImpl.c	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/src/solaris/native/sun/nio/ch/DatagramChannelImpl.c	Wed Jul 05 18:10:27 2017 +0200
@@ -77,7 +77,7 @@
 
 JNIEXPORT void JNICALL
 Java_sun_nio_ch_DatagramChannelImpl_disconnect0(JNIEnv *env, jobject this,
-                                                jobject fdo)
+                                                jobject fdo, jboolean isIPv6)
 {
     jint fd = fdval(env, fdo);
     int rv;
@@ -94,7 +94,7 @@
         memset(&sa, 0, sizeof(sa));
 
 #ifdef AF_INET6
-        if (ipv6_available()) {
+        if (isIPv6) {
             struct sockaddr_in6 *him6 = (struct sockaddr_in6 *)&sa;
 #if defined(_ALLBSD_SOURCE)
             him6->sin6_family = AF_INET6;
--- a/jdk/src/windows/classes/sun/awt/shell/Win32ShellFolderManager2.java	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/src/windows/classes/sun/awt/shell/Win32ShellFolderManager2.java	Wed Jul 05 18:10:27 2017 +0200
@@ -37,8 +37,6 @@
 import java.util.List;
 import java.util.concurrent.*;
 
-import sun.security.action.LoadLibraryAction;
-
 import static sun.awt.shell.Win32ShellFolder2.*;
 import sun.awt.OSInfo;
 
@@ -56,7 +54,13 @@
 
     static {
         // Load library here
-        AccessController.doPrivileged(new LoadLibraryAction("awt"));
+        AccessController.doPrivileged(
+            new java.security.PrivilegedAction<Void>() {
+                public Void run() {
+                    System.loadLibrary("awt");
+                    return null;
+                }
+            });
     }
 
     public ShellFolder createShellFolder(File file) throws FileNotFoundException {
--- a/jdk/src/windows/classes/sun/awt/windows/WToolkit.java	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/src/windows/classes/sun/awt/windows/WToolkit.java	Wed Jul 05 18:10:27 2017 +0200
@@ -94,7 +94,12 @@
     public static void loadLibraries() {
         if (!loaded) {
             java.security.AccessController.doPrivileged(
-                          new sun.security.action.LoadLibraryAction("awt"));
+                new java.security.PrivilegedAction<Void>() {
+                    public Void run() {
+                        System.loadLibrary("awt");
+                        return null;
+                    }
+                });
             loaded = true;
         }
     }
--- a/jdk/src/windows/classes/sun/management/FileSystemImpl.java	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/src/windows/classes/sun/management/FileSystemImpl.java	Wed Jul 05 18:10:27 2017 +0200
@@ -56,8 +56,13 @@
     // Initialization
 
     static {
-        java.security.AccessController
-            .doPrivileged(new sun.security.action.LoadLibraryAction("management"));
+        java.security.AccessController.doPrivileged(
+            new java.security.PrivilegedAction<Void>() {
+                public Void run() {
+                    System.loadLibrary("management");
+                    return null;
+                }
+            });
         init0();
     }
 }
--- a/jdk/src/windows/classes/sun/net/dns/ResolverConfigurationImpl.java	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/src/windows/classes/sun/net/dns/ResolverConfigurationImpl.java	Wed Jul 05 18:10:27 2017 +0200
@@ -161,7 +161,12 @@
 
     static {
         java.security.AccessController.doPrivileged(
-            new sun.security.action.LoadLibraryAction("net"));
+            new java.security.PrivilegedAction<Void>() {
+                public Void run() {
+                    System.loadLibrary("net");
+                    return null;
+                }
+            });
         init0();
 
         // start the address listener thread
--- a/jdk/src/windows/classes/sun/print/Win32PrintServiceLookup.java	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/src/windows/classes/sun/print/Win32PrintServiceLookup.java	Wed Jul 05 18:10:27 2017 +0200
@@ -56,7 +56,12 @@
 
     static {
         java.security.AccessController.doPrivileged(
-                    new sun.security.action.LoadLibraryAction("awt"));
+            new java.security.PrivilegedAction<Void>() {
+                public Void run() {
+                    System.loadLibrary("awt");
+                    return null;
+                }
+            });
     }
 
     /* The singleton win32 print lookup service.
--- a/jdk/src/windows/classes/sun/security/smartcardio/PlatformPCSC.java	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/src/windows/classes/sun/security/smartcardio/PlatformPCSC.java	Wed Jul 05 18:10:27 2017 +0200
@@ -26,8 +26,7 @@
 package sun.security.smartcardio;
 
 import java.security.AccessController;
-
-import sun.security.action.LoadLibraryAction;
+import java.security.PrivilegedAction;
 
 // Platform specific code and constants
 class PlatformPCSC {
@@ -44,7 +43,12 @@
 
     private static Throwable loadLibrary() {
         try {
-            AccessController.doPrivileged(new LoadLibraryAction("j2pcsc"));
+            AccessController.doPrivileged(new PrivilegedAction<Void>() {
+                public Void run() {
+                    System.loadLibrary("j2pcsc");
+                    return null;
+                }
+            });
             return null;
         } catch (Throwable e) {
             return e;
--- a/jdk/src/windows/native/java/net/NetworkInterface.c	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/src/windows/native/java/net/NetworkInterface.c	Wed Jul 05 18:10:27 2017 +0200
@@ -178,7 +178,7 @@
     int count;
     netif *netifP;
     DWORD i;
-    int lo=0, eth=0, tr=0, fddi=0, ppp=0, sl=0, net=0;
+    int lo=0, eth=0, tr=0, fddi=0, ppp=0, sl=0, wlan=0, net=0;
 
     /*
      * Ask the IP Helper library to enumerate the adapters
@@ -218,15 +218,15 @@
          */
         switch (ifrowP->dwType) {
             case MIB_IF_TYPE_ETHERNET:
-                sprintf(dev_name, "eth%d", eth++);
+                _snprintf_s(dev_name, 8, _TRUNCATE, "eth%d", eth++);
                 break;
 
             case MIB_IF_TYPE_TOKENRING:
-                sprintf(dev_name, "tr%d", tr++);
+                _snprintf_s(dev_name, 8, _TRUNCATE, "tr%d", tr++);
                 break;
 
             case MIB_IF_TYPE_FDDI:
-                sprintf(dev_name, "fddi%d", fddi++);
+                _snprintf_s(dev_name, 8, _TRUNCATE, "fddi%d", fddi++);
                 break;
 
             case MIB_IF_TYPE_LOOPBACK:
@@ -234,20 +234,24 @@
                 if (lo > 0) {
                     continue;
                 }
-                strcpy(dev_name, "lo");
+                strncpy_s(dev_name, 8, "lo", _TRUNCATE);
                 lo++;
                 break;
 
             case MIB_IF_TYPE_PPP:
-                sprintf(dev_name, "ppp%d", ppp++);
+                _snprintf_s(dev_name, 8, _TRUNCATE, "ppp%d", ppp++);
                 break;
 
             case MIB_IF_TYPE_SLIP:
-                sprintf(dev_name, "sl%d", sl++);
+                _snprintf_s(dev_name, 8, _TRUNCATE, "sl%d", sl++);
+                break;
+
+            case IF_TYPE_IEEE80211:
+                _snprintf_s(dev_name, 8, _TRUNCATE, "wlan%d", wlan++);
                 break;
 
             default:
-                sprintf(dev_name, "net%d", net++);
+                _snprintf_s(dev_name, 8, _TRUNCATE, "net%d", net++);
         }
 
         /*
@@ -382,6 +386,7 @@
             case MIB_IF_TYPE_TOKENRING:
             case MIB_IF_TYPE_FDDI:
             case MIB_IF_TYPE_LOOPBACK:
+            case IF_TYPE_IEEE80211:
               /**
                * Contrary to what it seems to indicate, dwBCastAddr doesn't
                * contain the broadcast address but 0 or 1 depending on whether
@@ -928,6 +933,7 @@
       case MIB_IF_TYPE_ETHERNET:
       case MIB_IF_TYPE_TOKENRING:
       case MIB_IF_TYPE_FDDI:
+      case IF_TYPE_IEEE80211:
         len = ifRowP->dwPhysAddrLen;
         ret = (*env)->NewByteArray(env, len);
         if (!IS_NULL(ret)) {
--- a/jdk/src/windows/native/java/net/NetworkInterface.h	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/src/windows/native/java/net/NetworkInterface.h	Wed Jul 05 18:10:27 2017 +0200
@@ -89,4 +89,9 @@
 
 int enumInterfaces(JNIEnv *env, netif **netifPP);
 
+// Windows Visa (and later) only.....
+#ifndef IF_TYPE_IEEE80211
+#define IF_TYPE_IEEE80211     71
 #endif
+
+#endif
--- a/jdk/src/windows/native/sun/nio/ch/DatagramChannelImpl.c	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/src/windows/native/sun/nio/ch/DatagramChannelImpl.c	Wed Jul 05 18:10:27 2017 +0200
@@ -108,7 +108,7 @@
 
 JNIEXPORT void JNICALL
 Java_sun_nio_ch_DatagramChannelImpl_disconnect0(JNIEnv *env, jobject this,
-                                                jobject fdo)
+                                                jobject fdo, jboolean isIPv6)
 {
     jint fd = fdval(env, fdo);
     int rv = 0;
--- a/jdk/test/ProblemList.txt	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/test/ProblemList.txt	Wed Jul 05 18:10:27 2017 +0200
@@ -286,13 +286,13 @@
 
 # Failing on Solaris i586, 3/9/2010, not a -samevm issue (jdk_security3)
 sun/security/pkcs11/Secmod/AddPrivateKey.java                   solaris-i586
-sun/security/pkcs11/ec/ReadCertificates.java                    solaris-i586
-sun/security/pkcs11/ec/ReadPKCS12.java                          solaris-i586
+sun/security/pkcs11/ec/ReadCertificates.java                    generic-all
+sun/security/pkcs11/ec/ReadPKCS12.java                          generic-all
 sun/security/pkcs11/ec/TestCurves.java                          solaris-i586
 sun/security/pkcs11/ec/TestECDSA.java                           solaris-i586
 #sun/security/pkcs11/ec/TestECGenSpec.java                      solaris-i586
 #sun/security/pkcs11/ec/TestKeyFactory.java                     solaris-i586
-sun/security/pkcs11/sslecc/ClientJSSEServerJSSE.java            solaris-i586
+sun/security/pkcs11/sslecc/ClientJSSEServerJSSE.java            generic-all
 
 # Fails on Fedora 9/Ubuntu 10.04 64bit, PKCS11Exception: CKR_DEVICE_ERROR
 sun/security/pkcs11/KeyAgreement/TestDH.java                    generic-all
--- a/jdk/test/com/sun/crypto/provider/Mac/MacClone.java	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/test/com/sun/crypto/provider/Mac/MacClone.java	Wed Jul 05 18:10:27 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2007, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -23,7 +23,7 @@
 
 /*
  * @test
- * @bug 0000000
+ * @bug 7087021
  * @summary MacClone
  * @author Jan Luehe
  */
@@ -56,7 +56,7 @@
         KeyGenerator kgen = KeyGenerator.getInstance("DES");
         SecretKey skey = kgen.generateKey();
 
-        mac = Mac.getInstance("HmacSHA1");
+        mac = Mac.getInstance("HmacSHA1", "SunJCE");
         mac.init(skey);
         macClone = (Mac)mac.clone();
         System.out.println(macClone.getProvider().toString());
--- a/jdk/test/demo/jvmti/DemoRun.java	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/test/demo/jvmti/DemoRun.java	Wed Jul 05 18:10:27 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004, 2007, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -124,7 +124,7 @@
         String os_name   = System.getProperty("os.name");
         String libprefix = os_name.contains("Windows")?"":"lib";
         String libsuffix = os_name.contains("Windows")?".dll":
-                                os_name.startsWith("Mac OS")?".dylib":".so";
+                                os_name.contains("OS X")?".dylib":".so";
         boolean d64      =    ( os_name.contains("Solaris") ||
                                 os_name.contains("SunOS") )
                            && ( os_arch.equals("sparcv9") ||
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/Frame/FrameStateTest/FrameStateTest.html	Wed Jul 05 18:10:27 2017 +0200
@@ -0,0 +1,50 @@
+<!--  
+
+ Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+ This code is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License version 2 only, as
+ published by the Free Software Foundation.
+
+ This code is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ version 2 for more details (a copy is included in the LICENSE file that
+ accompanied this code).
+
+ You should have received a copy of the GNU General Public License version
+ 2 along with this work; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+ Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ or visit www.oracle.com if you need additional information or have any
+ questions.
+
+  @test
+  @bug 4157271
+  @summary Checks that when a Frame is created it honors the state it
+  	was set to. The bug was that if setState(Frame.ICONIFIED) was 
+  	called before setVisible(true) the Frame would be shown in NORMAL 
+  	state instead of ICONIFIED.
+  @author JTG East Team: area=awt.Frame
+  @run applet/manual=yesno FrameStateTest.html
+
+ -->
+
+<html>
+<head>
+<title> FrameStateTest </title>
+</head>
+<body>
+
+<h1>FrameStateTest<br>Bug ID: 4157271</h1>
+<p>This test checks that when setState(Frame.ICONIFIED) is called before
+  	setVisible(true) the Frame is shown in the proper iconified state.
+  	The problem was that it did not honor the initial iconic state, but
+ 	instead was shown in the NORMAL state.</p>
+<p>See the dialog box (usually in upper left corner) for instructions</p>
+
+<APPLET CODE="FrameStateTest.class" WIDTH=600 HEIGHT=200></APPLET>
+</body>
+</html>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/Frame/FrameStateTest/FrameStateTest.java	Wed Jul 05 18:10:27 2017 +0200
@@ -0,0 +1,459 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+  test
+  @bug 4157271
+  @summary Checks that when a Frame is created it honors the state it
+        was set to. The bug was that if setState(Frame.ICONIFIED) was
+        called before setVisible(true) the Frame would be shown in NORMAL
+        state instead of ICONIFIED.
+  @author JTG East Team: area=awt.Frame
+  @run applet/manual=yesno FrameStateTest.html
+*/
+
+/**
+ * FrameStateTest.java
+ *
+ * summary: Checks that when setState(Frame.ICONIFIED) is called before
+ *      setVisible(true) the Frame is shown in the proper iconified state.
+ *      The problem was that it did not honor the initial iconic state, but
+ *      instead was shown in the NORMAL state.
+ */
+
+import java.awt.event.*;
+import java.awt.*;
+import java.lang.*;
+import java.applet.Applet;
+
+
+public class FrameStateTest extends Applet implements ActionListener, ItemListener{
+
+   Button btnCreate = new Button("Create Frame");
+   Button btnDispose = new Button("Dispose Frame");
+   CheckboxGroup cbgState = new CheckboxGroup();
+   CheckboxGroup cbgResize = new CheckboxGroup();
+   Checkbox cbIconState = new Checkbox("Frame state ICONIFIED",cbgState,false);
+   Checkbox cbNormState = new Checkbox("Frame state NORMAL",cbgState,true);
+   Checkbox cbNonResize = new Checkbox("Frame Nonresizable",cbgResize,false);
+   Checkbox cbResize = new Checkbox("Frame Resizable",cbgResize,true);
+   int iState = 0;
+   boolean bResize = true;
+   CreateFrame icontst;
+
+   public void init() {
+      this.setLayout (new BorderLayout ());
+
+      String[] instructions =
+       {
+        "Steps to try to reproduce this problem:",
+        "When this test is run an Applet Viewer window will display. In the",
+        "Applet Viewer window select the different options for the Frame (i.e.",
+        "{Normal, Non-resizalbe}, {Normal, Resizable}, {Iconified, Resizable},",
+        "{Iconified, Non-resizalbe}). After chosing the Frame's state click the",
+        "Create Frame button. After the Frame (Frame State Test (Window2)) comes",
+        "up make sure the proper behavior occurred (Frame shown in proper state).",
+        "Click the Dispose button to close the Frame. Do the above steps for all",
+        "the different Frame state combinations available. If you observe the",
+        "proper behavior the test has passed, Press the Pass button. Otherwise",
+        "the test has failed, Press the Fail button.",
+        "Note: In Frame State Test (Window2) you can also chose the different",
+        "buttons to see different Frame behavior. An example of a problem that",
+        "has been seen, With the Frame nonresizable you can not iconify the Frame."
+       };
+      Sysout.createDialogWithInstructions( instructions );
+
+      btnDispose.setEnabled(false);
+      add(btnCreate, BorderLayout.NORTH);
+      add(btnDispose, BorderLayout.SOUTH);
+
+      Panel p = new Panel(new GridLayout(0,1));
+      p.add(cbIconState);
+      p.add(cbResize);
+      add(p, BorderLayout.WEST);
+
+      p = new Panel(new GridLayout(0,1));
+      p.add(cbNormState);
+      p.add(cbNonResize);
+      add(p, BorderLayout.EAST);
+
+      // Add Listeners
+      btnDispose.addActionListener(this);
+      btnCreate.addActionListener(this);
+      cbNormState.addItemListener(this);
+      cbResize.addItemListener(this);
+      cbIconState.addItemListener(this);
+      cbNonResize.addItemListener(this);
+
+      resize(600, 200);
+
+   }//End  init()
+
+   public void actionPerformed(ActionEvent evt) {
+
+
+        if (evt.getSource() == btnCreate) {
+            btnCreate.setEnabled(false);
+            btnDispose.setEnabled(true);
+            icontst = new CreateFrame(iState, bResize);
+            icontst.show();
+        } else if (evt.getSource() == btnDispose) {
+            btnCreate.setEnabled(true);
+            btnDispose.setEnabled(false);
+            icontst.dispose();
+        }
+    }
+
+    public void itemStateChanged(ItemEvent evt) {
+
+        if (cbNormState.getState()) iState = 0;
+        if (cbIconState.getState()) iState = 1;
+        if (cbResize.getState()) bResize = true;
+        if (cbNonResize.getState()) bResize = false;
+
+    }
+
+}// class FrameStateTest
+
+
+class CreateFrame extends Frame implements ActionListener , WindowListener {
+
+  static int e=0;
+  static int u=0;
+  static int p=0;
+  static int i=0;
+  static int v=0;
+
+  Button b1, b2, b3, b4, b5, b6, b7;
+  boolean resizable = true;
+  boolean iconic = false;
+  String name = "Frame State Test";
+
+  CreateFrame (int iFrameState, boolean bFrameResizable) {
+
+    setTitle("Frame State Test (Window 2)");
+
+    if (iFrameState == 1) {
+        iconic = true;
+    }
+
+    if (!(bFrameResizable)) {
+        resizable = false;
+    }
+
+    System.out.println("CREATING FRAME - Initially "+
+        ((iconic) ? "ICONIFIED" : "NORMAL (NON-ICONIFIED)") + " and " +
+        ((resizable) ? "RESIZABLE" : "NON-RESIZABLE") );
+
+    Sysout.println("CREATING FRAME - Initially "+
+        ((iconic) ? "ICONIFIED" : "NORMAL (NON-ICONIFIED)") + " and " +
+        ((resizable) ? "RESIZABLE" : "NON-RESIZABLE") );
+
+    setLayout(new FlowLayout() );
+    b1 = new Button("resizable");
+    add(b1);
+    b2 = new Button("resize");
+    add(b2);
+    b3 = new Button("iconify");
+    add(b3);
+    b4 = new Button("iconify and restore");
+    add(b4);
+    b5 = new Button("hide and show");
+    add(b5);
+    b6 = new Button("hide, iconify and show");
+    add(b6);
+    b7 = new Button("hide, iconify, show, and restore");
+    add(b7);
+    b1.addActionListener(this);
+    b2.addActionListener(this);
+    b3.addActionListener(this);
+    b4.addActionListener(this);
+    b5.addActionListener(this);
+    b6.addActionListener(this);
+    b7.addActionListener(this);
+    addWindowListener(this);
+
+    setBounds(100,2,200, 200);
+    setState(iconic ? Frame.ICONIFIED: Frame.NORMAL);
+    setResizable(resizable);
+    pack();
+    setVisible(true);
+
+  }
+
+  public void actionPerformed ( ActionEvent e )
+  {
+    if ( e.getSource() == b2 ) {
+        Rectangle r = this.getBounds();
+        r.width += 10;
+        System.out.println(" - button pressed - setting bounds on Frame to: "+r);
+        setBounds(r);
+        validate();
+    } else if ( e.getSource() == b1 ) {
+        resizable = !resizable;
+        System.out.println(" - button pressed - setting Resizable to: "+resizable);
+        ((Frame)(b1.getParent())).setResizable(resizable);
+    } else if ( e.getSource() == b3 ) {
+        System.out.println(" - button pressed - setting Iconic: ");
+        dolog();
+        ((Frame)(b1.getParent())).setState(Frame.ICONIFIED);
+        dolog();
+    } else if ( e.getSource() == b4 ) {
+        System.out.println(" - button pressed - setting Iconic: ");
+        dolog();
+        ((Frame)(b1.getParent())).setState(Frame.ICONIFIED);
+        dolog();
+        try {
+                Thread.sleep(1000);
+        } catch (Exception ex) {};
+        System.out.println(" - now restoring: ");
+        ((Frame)(b1.getParent())).setState(Frame.NORMAL);
+        dolog();
+    } else if ( e.getSource() == b5 ) {
+        System.out.println(" - button pressed - hiding : ");
+        dolog();
+        ((Frame)(b1.getParent())).setVisible(false);
+        dolog();
+        try {
+                Thread.sleep(1000);
+        } catch (Exception ex) {};
+        System.out.println(" - now reshowing: ");
+        ((Frame)(b1.getParent())).setVisible(true);
+        dolog();
+    } else if ( e.getSource() == b6 ) {
+        System.out.println(" - button pressed - hiding : ");
+        dolog();
+        ((Frame)(b1.getParent())).setVisible(false);
+        dolog();
+        try {
+                Thread.sleep(1000);
+        } catch (Exception ex) {};
+        System.out.println(" - setting Iconic: ");
+        dolog();
+        ((Frame)(b1.getParent())).setState(Frame.ICONIFIED);
+        try {
+                Thread.sleep(1000);
+        } catch (Exception ex) {};
+        System.out.println(" - now reshowing: ");
+        ((Frame)(b1.getParent())).setVisible(true);
+        dolog();
+    } else if ( e.getSource() == b7 ) {
+        System.out.println(" - button pressed - hiding : ");
+        dolog();
+        ((Frame)(b1.getParent())).setVisible(false);
+        dolog();
+        try {
+                Thread.sleep(1000);
+        } catch (Exception ex) {};
+        System.out.println(" - setting Iconic: ");
+        dolog();
+        ((Frame)(b1.getParent())).setState(Frame.ICONIFIED);
+        try {
+                Thread.sleep(1000);
+        } catch (Exception ex) {};
+        System.out.println(" - now reshowing: ");
+        ((Frame)(b1.getParent())).setVisible(true);
+        dolog();
+        try {
+                Thread.sleep(1000);
+        } catch (Exception ex) {};
+        System.out.println(" - now restoring: ");
+        ((Frame)(b1.getParent())).setState(Frame.NORMAL);
+        dolog();
+    }
+  }
+
+    public void windowActivated(WindowEvent e) {
+        System.out.println(name + " Activated");
+        dolog();
+    }
+    public void windowClosed(WindowEvent e) {
+        System.out.println(name + " Closed");
+        dolog();
+    }
+    public void windowClosing(WindowEvent e) {
+        ((Window)(e.getSource())).dispose();
+        System.out.println(name + " Closing");
+        dolog();
+    }
+    public void windowDeactivated(WindowEvent e) {
+        System.out.println(name + " Deactivated");
+        dolog();
+    }
+    public void windowDeiconified(WindowEvent e) {
+        System.out.println(name + " Deiconified");
+        dolog();
+    }
+    public void windowIconified(WindowEvent e) {
+        System.out.println(name + " Iconified");
+        dolog();
+    }
+    public void windowOpened(WindowEvent e) {
+        System.out.println(name + " Opened");
+        dolog();
+    }
+
+    public void dolog() {
+        System.out.println(" getState returns: "+getState());
+    }
+}
+
+// }// class FrameStateTest
+
+/****************************************************
+ Standard Test Machinery
+ DO NOT modify anything below -- it's a standard
+  chunk of code whose purpose is to make user
+  interaction uniform, and thereby make it simpler
+  to read and understand someone else's test.
+ ****************************************************/
+
+/**
+ This is part of the standard test machinery.
+ It creates a dialog (with the instructions), and is the interface
+  for sending text messages to the user.
+ To print the instructions, send an array of strings to Sysout.createDialog
+  WithInstructions method.  Put one line of instructions per array entry.
+ To display a message for the tester to see, simply call Sysout.println
+  with the string to be displayed.
+ This mimics System.out.println but works within the test harness as well
+  as standalone.
+ */
+
+class Sysout
+ {
+   private static TestDialog dialog;
+
+   public static void createDialogWithInstructions( String[] instructions )
+    {
+      dialog = new TestDialog( new Frame(), "Instructions" );
+      dialog.printInstructions( instructions );
+      dialog.show();
+      println( "Any messages for the tester will display here." );
+    }
+
+   public static void createDialog( )
+    {
+      dialog = new TestDialog( new Frame(), "Instructions" );
+      String[] defInstr = { "Instructions will appear here. ", "" } ;
+      dialog.printInstructions( defInstr );
+      dialog.show();
+      println( "Any messages for the tester will display here." );
+    }
+
+
+   public static void printInstructions( String[] instructions )
+    {
+      dialog.printInstructions( instructions );
+    }
+
+
+   public static void println( String messageIn )
+    {
+      dialog.displayMessage( messageIn );
+    }
+
+ }// Sysout  class
+
+/**
+  This is part of the standard test machinery.  It provides a place for the
+   test instructions to be displayed, and a place for interactive messages
+   to the user to be displayed.
+  To have the test instructions displayed, see Sysout.
+  To have a message to the user be displayed, see Sysout.
+  Do not call anything in this dialog directly.
+  */
+class TestDialog extends Dialog
+ {
+
+   TextArea instructionsText;
+   TextArea messageText;
+   int maxStringLength = 80;
+
+   //DO NOT call this directly, go through Sysout
+   public TestDialog( Frame frame, String name )
+    {
+      super( frame, name );
+      int scrollBoth = TextArea.SCROLLBARS_BOTH;
+      int scrollNone = TextArea.SCROLLBARS_NONE;
+      instructionsText = new TextArea( "", 15, maxStringLength, scrollBoth );
+      add( "North", instructionsText );
+
+      messageText = new TextArea( "", 10, maxStringLength, scrollBoth );
+      add("South", messageText);
+
+      pack();
+
+      show();
+    }// TestDialog()
+
+   //DO NOT call this directly, go through Sysout
+   public void printInstructions( String[] instructions )
+    {
+      //Clear out any current instructions
+      instructionsText.setText( "" );
+
+      //Go down array of instruction strings
+
+      String printStr, remainingStr;
+      for( int i=0; i < instructions.length; i++ )
+       {
+         //chop up each into pieces maxSringLength long
+         remainingStr = instructions[ i ];
+         while( remainingStr.length() > 0 )
+          {
+            //if longer than max then chop off first max chars to print
+            if( remainingStr.length() >= maxStringLength )
+             {
+               //Try to chop on a word boundary
+               int posOfSpace = remainingStr.
+                  lastIndexOf( ' ', maxStringLength - 1 );
+
+               if( posOfSpace <= 0 ) posOfSpace = maxStringLength - 1;
+
+               printStr = remainingStr.substring( 0, posOfSpace + 1 );
+               remainingStr = remainingStr.substring( posOfSpace + 1 );
+             }
+            //else just print
+            else
+             {
+               printStr = remainingStr;
+               remainingStr = "";
+             }
+
+            instructionsText.append( printStr + "\n" );
+
+          }// while
+
+       }// for
+
+    }//printInstructions()
+
+   //DO NOT call this directly, go through Sysout
+   public void displayMessage( String messageIn )
+    {
+      messageText.append( messageIn + "\n" );
+    }
+
+
+ }// TestDialog  class
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/Mouse/EnterExitEvents/DragWindowOutOfFrameTest.java	Wed Jul 05 18:10:27 2017 +0200
@@ -0,0 +1,267 @@
+/*
+ * Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved.
+ * 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 7154048
+ * @summary Window created under a mouse does not receive mouse enter event.
+ *     Mouse Entered/Exited events should be generated during dragging the window
+ *     out of the frame and to the frame.
+ * @library ../../regtesthelpers
+ * @build Util
+ * @author alexandr.scherbatiy area=awt.event
+ * @run main DragWindowOutOfFrameTest
+ */
+import java.awt.*;
+import java.awt.event.*;
+import javax.swing.*;
+
+import java.util.concurrent.*;
+import sun.awt.SunToolkit;
+
+import test.java.awt.regtesthelpers.Util;
+
+public class DragWindowOutOfFrameTest {
+
+    private static volatile int dragWindowMouseEnteredCount = 0;
+    private static volatile int dragWindowMouseExitedCount = 0;
+    private static volatile int dragWindowMouseReleasedCount = 0;
+    private static volatile int buttonMouseEnteredCount = 0;
+    private static volatile int buttonMouseExitedCount = 0;
+    private static volatile int labelMouseEnteredCount = 0;
+    private static volatile int labelMouseExitedCount = 0;
+    private static volatile int labelMouseReleasedCount = 0;
+    private static MyDragWindow dragWindow;
+    private static JLabel label;
+    private static JButton button;
+
+    public static void main(String[] args) throws Exception {
+
+        SunToolkit toolkit = (SunToolkit) Toolkit.getDefaultToolkit();
+        Robot robot = new Robot();
+        robot.setAutoDelay(50);
+
+        SwingUtilities.invokeAndWait(new Runnable() {
+
+            @Override
+            public void run() {
+                createAndShowGUI();
+            }
+        });
+
+        toolkit.realSync();
+
+        Point pointToClick = Util.invokeOnEDT(new Callable<Point>() {
+
+            @Override
+            public Point call() throws Exception {
+                return getCenterPoint(label);
+            }
+        });
+
+
+        robot.mouseMove(pointToClick.x, pointToClick.y);
+        robot.mousePress(InputEvent.BUTTON1_MASK);
+        toolkit.realSync();
+
+        if (dragWindowMouseEnteredCount != 1 && dragWindowMouseExitedCount != 0) {
+            throw new RuntimeException(
+                    "Wrong number mouse Entered/Exited events on Drag Window!");
+        }
+
+        Point pointToDrag = Util.invokeOnEDT(new Callable<Point>() {
+
+            @Override
+            public Point call() throws Exception {
+                label.addMouseListener(new LabelMouseListener());
+                button.addMouseListener(new ButtonMouseListener());
+                return getCenterPoint(button);
+            }
+        });
+
+        robot.mouseMove(450, pointToClick.y);
+        toolkit.realSync();
+
+        if (labelMouseEnteredCount != 0 && labelMouseExitedCount != 1) {
+            throw new RuntimeException(
+                    "Wrong number Mouse Entered/Exited events on label!");
+        }
+
+        robot.mouseMove(450, pointToDrag.y);
+        toolkit.realSync();
+
+        if (labelMouseEnteredCount != 0 && labelMouseExitedCount != 1) {
+            throw new RuntimeException(
+                    "Wrong number Mouse Entered/Exited events on label!");
+        }
+
+        if (buttonMouseEnteredCount != 0 && buttonMouseExitedCount != 0) {
+            throw new RuntimeException(
+                    "Wrong number Mouse Entered/Exited events on button!");
+        }
+
+        robot.mouseMove(pointToDrag.y, pointToDrag.y);
+        toolkit.realSync();
+
+        if (buttonMouseEnteredCount != 1 && buttonMouseExitedCount != 0) {
+            throw new RuntimeException(
+                    "Wrong number Mouse Entered/Exited events on button!");
+        }
+
+        robot.mouseRelease(InputEvent.BUTTON1_MASK);
+        toolkit.realSync();
+
+        if (labelMouseReleasedCount != 1) {
+            throw new RuntimeException("No MouseReleased event on label!");
+        }
+    }
+
+    private static Point getCenterPoint(Component comp) {
+        Point p = comp.getLocationOnScreen();
+        Rectangle rect = comp.getBounds();
+        return new Point(p.x + rect.width / 2, p.y + rect.height / 2);
+    }
+
+    private static void createAndShowGUI() {
+
+        JFrame frame = new JFrame("Main Frame");
+        frame.setLocation(100, 100);
+        frame.setSize(300, 200);
+        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+
+        label = new JLabel("Label");
+
+        DragWindowCreationMouseListener listener = new DragWindowCreationMouseListener(frame);
+        label.addMouseListener(listener);
+        label.addMouseMotionListener(listener);
+
+        button = new JButton("Button");
+        Panel panel = new Panel(new BorderLayout());
+
+        panel.add(label, BorderLayout.NORTH);
+        panel.add(button, BorderLayout.CENTER);
+
+        frame.getContentPane().add(panel);
+        frame.setVisible(true);
+
+    }
+
+    private static Point getAbsoluteLocation(MouseEvent e) {
+        return new Point(e.getXOnScreen(), e.getYOnScreen());
+    }
+
+    static class MyDragWindow extends Window {
+
+        public MyDragWindow(Window parent, Point location) {
+            super(parent);
+            setSize(500, 300);
+            setVisible(true);
+            JPanel panel = new JPanel();
+            add(panel);
+            setLocation(location.x - 250, location.y - 150);
+            addMouseListener(new DragWindowMouseListener());
+        }
+
+        void dragTo(Point point) {
+            setLocation(point.x - 250, point.y - 150);
+        }
+    }
+
+    static class DragWindowCreationMouseListener extends MouseAdapter {
+
+        Point origin;
+        Window parent;
+
+        public DragWindowCreationMouseListener(Window parent) {
+            this.parent = parent;
+        }
+
+        @Override
+        public void mousePressed(MouseEvent e) {
+            if (dragWindow == null) {
+                dragWindow = new MyDragWindow(parent, getAbsoluteLocation(e));
+            } else {
+                dragWindow.setVisible(true);
+                dragWindow.dragTo(getAbsoluteLocation(e));
+            }
+        }
+
+        @Override
+        public void mouseReleased(MouseEvent e) {
+            labelMouseReleasedCount++;
+            if (dragWindow != null) {
+                dragWindow.setVisible(false);
+            }
+        }
+
+        public void mouseDragged(MouseEvent e) {
+            if (dragWindow != null) {
+                dragWindow.dragTo(getAbsoluteLocation(e));
+            }
+        }
+    }
+
+    static class DragWindowMouseListener extends MouseAdapter {
+
+        @Override
+        public void mouseEntered(MouseEvent e) {
+            dragWindowMouseEnteredCount++;
+        }
+
+        @Override
+        public void mouseExited(MouseEvent e) {
+            dragWindowMouseExitedCount++;
+        }
+
+        @Override
+        public void mouseReleased(MouseEvent e) {
+            dragWindowMouseReleasedCount++;
+        }
+    }
+
+    static class LabelMouseListener extends MouseAdapter {
+
+        @Override
+        public void mouseEntered(MouseEvent e) {
+            labelMouseEnteredCount++;
+        }
+
+        @Override
+        public void mouseExited(MouseEvent e) {
+            labelMouseExitedCount++;
+        }
+    }
+
+    static class ButtonMouseListener extends MouseAdapter {
+
+        @Override
+        public void mouseEntered(MouseEvent e) {
+            buttonMouseEnteredCount++;
+        }
+
+        @Override
+        public void mouseExited(MouseEvent e) {
+            buttonMouseExitedCount++;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/Mouse/EnterExitEvents/DragWindowTest.java	Wed Jul 05 18:10:27 2017 +0200
@@ -0,0 +1,219 @@
+/*
+ * Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved.
+ * 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 7154048
+ * @summary Window created under a mouse does not receive mouse enter event.
+ *     Mouse Entered/Exited events are wrongly generated during dragging the window
+ *     from one component to another
+ * @library ../../regtesthelpers
+ * @build Util
+ * @author alexandr.scherbatiy area=awt.event
+ * @run main DragWindowTest
+ */
+
+import java.awt.*;
+import java.awt.event.*;
+import javax.swing.*;
+
+import java.util.concurrent.*;
+import sun.awt.SunToolkit;
+
+import test.java.awt.regtesthelpers.Util;
+
+public class DragWindowTest {
+
+    private static volatile int dragWindowMouseEnteredCount = 0;
+    private static volatile int dragWindowMouseReleasedCount = 0;
+    private static volatile int buttonMouseEnteredCount = 0;
+    private static volatile int labelMouseReleasedCount = 0;
+    private static MyDragWindow dragWindow;
+    private static JLabel label;
+    private static JButton button;
+
+    public static void main(String[] args) throws Exception {
+
+        SunToolkit toolkit = (SunToolkit) Toolkit.getDefaultToolkit();
+        Robot robot = new Robot();
+        robot.setAutoDelay(50);
+
+        SwingUtilities.invokeAndWait(new Runnable() {
+
+            @Override
+            public void run() {
+                createAndShowGUI();
+            }
+        });
+
+        toolkit.realSync();
+
+        Point pointToClick = Util.invokeOnEDT(new Callable<Point>() {
+
+            @Override
+            public Point call() throws Exception {
+                return getCenterPoint(label);
+            }
+        });
+
+
+        robot.mouseMove(pointToClick.x, pointToClick.y);
+        robot.mousePress(InputEvent.BUTTON1_MASK);
+        toolkit.realSync();
+
+        if (dragWindowMouseEnteredCount != 1) {
+            throw new RuntimeException("No MouseEntered event on Drag Window!");
+        }
+
+        Point pointToDrag = Util.invokeOnEDT(new Callable<Point>() {
+
+            @Override
+            public Point call() throws Exception {
+                button.addMouseListener(new ButtonMouseListener());
+                return getCenterPoint(button);
+            }
+        });
+
+        robot.mouseMove(pointToDrag.x, pointToDrag.y);
+        toolkit.realSync();
+
+        if (buttonMouseEnteredCount != 0) {
+            throw new RuntimeException("Extra MouseEntered event on button!");
+        }
+
+        robot.mouseRelease(InputEvent.BUTTON1_MASK);
+        toolkit.realSync();
+
+        if (labelMouseReleasedCount != 1) {
+            throw new RuntimeException("No MouseReleased event on label!");
+        }
+
+    }
+
+    private static Point getCenterPoint(Component comp) {
+        Point p = comp.getLocationOnScreen();
+        Rectangle rect = comp.getBounds();
+        return new Point(p.x + rect.width / 2, p.y + rect.height / 2);
+    }
+
+    private static void createAndShowGUI() {
+
+        JFrame frame = new JFrame("Main Frame");
+        frame.setSize(300, 200);
+        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+
+        label = new JLabel("Label");
+
+        LabelMouseListener listener = new LabelMouseListener(frame);
+        label.addMouseListener(listener);
+        label.addMouseMotionListener(listener);
+
+        button = new JButton("Button");
+        Panel panel = new Panel(new BorderLayout());
+
+        panel.add(label, BorderLayout.NORTH);
+        panel.add(button, BorderLayout.CENTER);
+
+        frame.getContentPane().add(panel);
+        frame.setVisible(true);
+
+    }
+
+    private static Point getAbsoluteLocation(MouseEvent e) {
+        return new Point(e.getXOnScreen(), e.getYOnScreen());
+    }
+
+    static class MyDragWindow extends Window {
+
+        static int d = 30;
+
+        public MyDragWindow(Window parent, Point location) {
+            super(parent);
+            setSize(150, 150);
+            setVisible(true);
+            JPanel panel = new JPanel();
+            add(panel);
+            setLocation(location.x - d, location.y - d);
+            addMouseListener(new DragWindowMouseListener());
+        }
+
+        void dragTo(Point point) {
+            setLocation(point.x - d, point.y - d);
+        }
+    }
+
+    static class LabelMouseListener extends MouseAdapter {
+
+        Point origin;
+        Window parent;
+
+        public LabelMouseListener(Window parent) {
+            this.parent = parent;
+        }
+
+        @Override
+        public void mousePressed(MouseEvent e) {
+            if (dragWindow == null) {
+                dragWindow = new MyDragWindow(parent, getAbsoluteLocation(e));
+            } else {
+                dragWindow.setVisible(true);
+                dragWindow.dragTo(getAbsoluteLocation(e));
+            }
+        }
+
+        @Override
+        public void mouseReleased(MouseEvent e) {
+            labelMouseReleasedCount++;
+            if (dragWindow != null) {
+                dragWindow.setVisible(false);
+            }
+        }
+
+        public void mouseDragged(MouseEvent e) {
+            if (dragWindow != null) {
+                dragWindow.dragTo(getAbsoluteLocation(e));
+            }
+        }
+    }
+
+    static class DragWindowMouseListener extends MouseAdapter {
+
+        @Override
+        public void mouseEntered(MouseEvent e) {
+            dragWindowMouseEnteredCount++;
+        }
+
+        @Override
+        public void mouseReleased(MouseEvent e) {
+            dragWindowMouseReleasedCount++;
+        }
+    }
+
+    static class ButtonMouseListener extends MouseAdapter {
+
+        @Override
+        public void mouseEntered(MouseEvent e) {
+            buttonMouseEnteredCount++;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/Mouse/EnterExitEvents/ResizingFrameTest.java	Wed Jul 05 18:10:27 2017 +0200
@@ -0,0 +1,232 @@
+/*
+ * Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved.
+ * 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 7154048
+ * @summary Programmatically resized  window does not receive mouse entered/exited events
+ * @author  alexandr.scherbatiy area=awt.event
+ * @run main ResizingFrameTest
+ */
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+import java.awt.*;
+import java.awt.event.*;
+import javax.swing.*;
+import sun.awt.SunToolkit;
+
+public class ResizingFrameTest {
+
+    private static volatile int mouseEnteredCount = 0;
+    private static volatile int mouseExitedCount = 0;
+    private static JFrame frame;
+
+    public static void main(String[] args) throws Exception {
+
+        SunToolkit toolkit = (SunToolkit) Toolkit.getDefaultToolkit();
+        Robot robot = new Robot();
+        robot.setAutoDelay(50);
+        robot.mouseMove(100, 100);
+
+        // create a frame under the mouse cursor
+        SwingUtilities.invokeAndWait(new Runnable() {
+
+            @Override
+            public void run() {
+                createAndShowGUI();
+            }
+        });
+
+
+        toolkit.realSync();
+
+        if (mouseEnteredCount != 1 || mouseExitedCount != 0) {
+            throw new RuntimeException("No Mouse Entered/Exited events!");
+        }
+
+        // iconify frame
+        SwingUtilities.invokeAndWait(new Runnable() {
+
+            @Override
+            public void run() {
+                frame.setExtendedState(Frame.ICONIFIED);
+            }
+        });
+
+        toolkit.realSync();
+        robot.delay(200);
+
+        if (mouseEnteredCount != 1 || mouseExitedCount != 1) {
+            throw new RuntimeException("No Mouse Entered/Exited events!");
+        }
+
+        // deiconify frame
+        SwingUtilities.invokeAndWait(new Runnable() {
+
+            @Override
+            public void run() {
+                frame.setExtendedState(Frame.NORMAL);
+            }
+        });
+
+        toolkit.realSync();
+        robot.delay(200);
+
+        if (mouseEnteredCount != 2 || mouseExitedCount != 1) {
+            throw new RuntimeException("No Mouse Entered/Exited events!");
+        }
+
+        // move the mouse out of the frame
+        robot.mouseMove(500, 500);
+        toolkit.realSync();
+        robot.delay(200);
+
+        if (mouseEnteredCount != 2 || mouseExitedCount != 2) {
+            throw new RuntimeException("No Mouse Entered/Exited events!");
+        }
+
+        // maximize the frame
+        SwingUtilities.invokeAndWait(new Runnable() {
+
+            @Override
+            public void run() {
+                frame.setExtendedState(Frame.MAXIMIZED_BOTH);
+            }
+        });
+
+        toolkit.realSync();
+        robot.delay(200);
+
+        if (mouseEnteredCount != 3 || mouseExitedCount != 2) {
+            throw new RuntimeException("No Mouse Entered/Exited events!");
+        }
+
+
+        // demaximize the frame
+        SwingUtilities.invokeAndWait(new Runnable() {
+
+            @Override
+            public void run() {
+                frame.setExtendedState(Frame.NORMAL);
+            }
+        });
+
+        toolkit.realSync();
+        robot.delay(200);
+
+        if (mouseEnteredCount != 3 || mouseExitedCount != 3) {
+            throw new RuntimeException("No Mouse Entered/Exited events!");
+
+        }
+
+        // move the frame under the mouse
+        SwingUtilities.invokeAndWait(new Runnable() {
+
+            @Override
+            public void run() {
+                frame.setLocation(400, 400);
+            }
+        });
+
+        toolkit.realSync();
+        robot.delay(200);
+
+        if (mouseEnteredCount != 4 || mouseExitedCount != 3) {
+            throw new RuntimeException("No Mouse Entered/Exited events!");
+        }
+
+        // move the frame out of the mouse
+        SwingUtilities.invokeAndWait(new Runnable() {
+
+            @Override
+            public void run() {
+                frame.setLocation(100, 100);
+            }
+        });
+
+        toolkit.realSync();
+        robot.delay(400);
+
+        if (mouseEnteredCount != 4 || mouseExitedCount != 4) {
+            throw new RuntimeException("No Mouse Entered/Exited events!");
+        }
+
+        // enlarge the frame bounds
+        SwingUtilities.invokeAndWait(new Runnable() {
+
+            @Override
+            public void run() {
+                frame.setBounds(100, 100, 800, 800);
+            }
+        });
+
+        toolkit.realSync();
+        robot.delay(200);
+
+        if (mouseEnteredCount != 5 || mouseExitedCount != 4) {
+            throw new RuntimeException("No Mouse Entered/Exited events!");
+        }
+
+        // make the frame bounds smaller
+        SwingUtilities.invokeAndWait(new Runnable() {
+
+            @Override
+            public void run() {
+                frame.setBounds(100, 100, 200, 300);
+            }
+        });
+
+        toolkit.realSync();
+        robot.delay(400);
+
+
+        if (mouseEnteredCount != 5 || mouseExitedCount != 5) {
+            throw new RuntimeException("No Mouse Entered/Exited events!");
+        }
+    }
+
+    private static void createAndShowGUI() {
+
+        frame = new JFrame("Main Frame");
+        frame.setSize(300, 200);
+        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+
+        frame.addMouseListener(new MouseAdapter() {
+
+            @Override
+            public void mouseEntered(MouseEvent e) {
+                mouseEnteredCount++;
+            }
+
+            @Override
+            public void mouseExited(MouseEvent e) {
+                mouseExitedCount++;
+            }
+        });
+
+        frame.setVisible(true);
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/TextArea/TextAreaCaretVisibilityTest/bug7129742.java	Wed Jul 05 18:10:27 2017 +0200
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 2012 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * Portions Copyright (c) 2012 IBM Corporation
+ */
+
+
+/* @test
+ * @bug 7129742
+ * @summary Focus in non-editable TextArea is not shown on Linux.
+ * @author Sean Chou
+ */
+
+import java.awt.FlowLayout;
+import java.awt.TextArea;
+import java.awt.Toolkit;
+import java.lang.reflect.Field;
+
+import javax.swing.JFrame;
+import javax.swing.JTextArea;
+import javax.swing.SwingUtilities;
+import javax.swing.text.DefaultCaret;
+
+import sun.awt.SunToolkit;
+
+public class bug7129742 {
+
+    public static DefaultCaret caret = null;
+    public static JFrame frame = null;
+    public static boolean fastreturn = false;
+
+    public static void main(String[] args) throws Exception {
+        SunToolkit toolkit = (SunToolkit) Toolkit.getDefaultToolkit();
+
+        SwingUtilities.invokeAndWait(new Runnable() {
+            @Override
+            public void run() {
+                frame = new JFrame("Test");
+                TextArea textArea = new TextArea("Non-editable textArea");
+                textArea.setEditable(false);
+                frame.setLayout(new FlowLayout());
+                frame.add(textArea);
+                frame.pack();
+                frame.setVisible(true);
+
+                try {
+                    Class XTextAreaPeerClzz  = textArea.getPeer().getClass();
+                    System.out.println(XTextAreaPeerClzz.getName());
+                    if (!XTextAreaPeerClzz.getName().equals("sun.awt.X11.XTextAreaPeer")) {
+                        fastreturn = true;
+                        return;
+                    }
+
+                    Field jtextField = XTextAreaPeerClzz.getDeclaredField("jtext");
+                    jtextField.setAccessible(true);
+                    JTextArea jtext = (JTextArea)jtextField.get(textArea.getPeer());
+                    caret = (DefaultCaret) jtext.getCaret();
+
+                    textArea.requestFocusInWindow();
+                } catch (NoSuchFieldException | SecurityException
+                         | IllegalArgumentException | IllegalAccessException e) {
+                    /* These exceptions mean the implementation of XTextAreaPeer is
+                     * changed, this testcase is not valid any more, fix it or remove.
+                     */
+                    frame.dispose();
+                    throw new RuntimeException("This testcase is not valid any more!");
+                }
+            }
+        });
+        toolkit.realSync();
+
+        SwingUtilities.invokeAndWait(new Runnable() {
+            @Override
+            public void run() {
+                try{
+                    if (fastreturn) {
+                        return;
+                    }
+                    boolean passed = caret.isActive();
+                    System.out.println("is caret visible : " + passed);
+
+                    if (!passed) {
+                        throw new RuntimeException("The test for bug 71297422 failed");
+                    }
+                } finally {
+                    frame.dispose();
+                }
+            }
+        });
+    }
+
+}
--- a/jdk/test/java/awt/regtesthelpers/Util.java	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/test/java/awt/regtesthelpers/Util.java	Wed Jul 05 18:10:27 2017 +0200
@@ -600,4 +600,34 @@
                                 time, printEvent);
 
     }
+
+
+    /**
+     * Invokes the <code>task</code> on the EDT thread.
+     *
+     * @return result of the <code>task</code>
+     */
+    public static <T> T invokeOnEDT(final java.util.concurrent.Callable<T> task) throws Exception {
+        final java.util.List<T> result = new java.util.ArrayList<T>(1);
+        final Exception[] exception = new Exception[1];
+
+        javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+
+            @Override
+            public void run() {
+                try {
+                    result.add(task.call());
+                } catch (Exception e) {
+                    exception[0] = e;
+                }
+            }
+        });
+
+        if (exception[0] != null) {
+            throw exception[0];
+        }
+
+        return result.get(0);
+    }
+
 }
--- a/jdk/test/java/io/File/GetXSpace.java	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/test/java/io/File/GetXSpace.java	Wed Jul 05 18:10:27 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -51,7 +51,7 @@
     private static final String dfFormat;
     static {
         if (name.equals("SunOS") || name.equals("Linux")
-                || name.startsWith("Mac OS")) {
+                || name.contains("OS X")) {
             // FileSystem Total Used Available Use% MountedOn
             dfFormat = "([^\\s]+)\\s+(\\d+)\\s+\\d+\\s+(\\d+)\\s+\\d+%\\s+([^\\s]+)";
         } else if (name.startsWith("Windows")) {
--- a/jdk/test/java/lang/ProcessBuilder/Basic.java	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/test/java/lang/ProcessBuilder/Basic.java	Wed Jul 05 18:10:27 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -597,7 +597,7 @@
     static class MacOSX {
         public static boolean is() { return is; }
         private static final String osName = System.getProperty("os.name");
-        private static final boolean is = osName.startsWith("Mac OS");
+        private static final boolean is = osName.contains("OS X");
     }
 
     static class True {
--- a/jdk/test/java/lang/ProcessBuilder/Zombies.java	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/test/java/lang/ProcessBuilder/Zombies.java	Wed Jul 05 18:10:27 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -34,7 +34,7 @@
 
     static final String os = System.getProperty("os.name");
 
-    static final String TrueCommand = os.startsWith("Mac OS")?
+    static final String TrueCommand = os.contains("OS X")?
         "/usr/bin/true" : "/bin/true";
 
     public static void main(String[] args) throws Throwable {
--- a/jdk/test/java/lang/invoke/InvokeGenericTest.java	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/test/java/lang/invoke/InvokeGenericTest.java	Wed Jul 05 18:10:27 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -76,7 +76,7 @@
         String name = properties.getProperty("java.vm.name");
         String arch = properties.getProperty("os.arch");
         if ((arch.equals("amd64") || arch.equals("i386") || arch.equals("x86") ||
-             arch.equals("sparc") || arch.equals("sparcv9")) &&
+             arch.equals("x86_64") || arch.equals("sparc") || arch.equals("sparcv9")) &&
             (name.contains("Client") || name.contains("Server"))
             ) {
             platformOK = true;
--- a/jdk/test/java/lang/management/OperatingSystemMXBean/GetSystemLoadAverage.java	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/test/java/lang/management/OperatingSystemMXBean/GetSystemLoadAverage.java	Wed Jul 05 18:10:27 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -80,7 +80,7 @@
     }
 
     private static String LOAD_AVERAGE_TEXT
-            = System.getProperty("os.name").startsWith("Mac OS")
+            = System.getProperty("os.name").contains("OS X")
                 ? "load averages:"
                 : "load average:";
 
@@ -99,7 +99,7 @@
         System.out.println("Load average returned from uptime = " + output);
         System.out.println("getSystemLoadAverage() returned " + loadavg);
 
-        String[] lavg = System.getProperty("os.name").startsWith("Mac OS")
+        String[] lavg = System.getProperty("os.name").contains("OS X")
                 ? output.split(" ")
                 : output.split(",");
         double expected = Double.parseDouble(lavg[0]);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/nio/channels/DatagramChannel/Disconnect.java	Wed Jul 05 18:10:27 2017 +0200
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/* @test
+ * @bug 7132924
+ * @summary Test DatagramChannel.disconnect when DatagramChannel is connected to an IPv4 socket
+ * @run main Disconnect
+ * @run main/othervm -Djava.net.preferIPv4Stack=true Disconnect
+ */
+
+import java.net.*;
+import java.nio.*;
+import java.nio.channels.*;
+import java.io.IOException;
+
+public class Disconnect {
+    public static void main(String[] args) throws IOException {
+        // test with default protocol family
+        try (DatagramChannel dc = DatagramChannel.open()) {
+            test(dc);
+            test(dc);
+        }
+
+        // test with IPv4 only
+        try (DatagramChannel dc = DatagramChannel.open(StandardProtocolFamily.INET)) {
+            test(dc);
+            test(dc);
+        }
+    }
+
+    /**
+     * Connect DatagramChannel to a server, write a datagram and disconnect. Invoke
+     * a second or subsequent time with the same DatagramChannel instance to check
+     * that disconnect works as expected.
+     */
+    static void test(DatagramChannel dc) throws IOException {
+        try (DatagramChannel server = DatagramChannel.open()) {
+            server.bind(new InetSocketAddress(0));
+
+            InetAddress lh = InetAddress.getLocalHost();
+            dc.connect(new InetSocketAddress(lh, server.socket().getLocalPort()));
+
+            dc.write(ByteBuffer.wrap("hello".getBytes()));
+
+            ByteBuffer bb = ByteBuffer.allocate(100);
+            server.receive(bb);
+
+            dc.disconnect();
+
+            try {
+                dc.write(ByteBuffer.wrap("another message".getBytes()));
+                throw new RuntimeException("write should fail, not connected");
+            } catch (NotYetConnectedException expected) {
+            }
+        }
+    }
+}
--- a/jdk/test/java/nio/channels/FileChannel/Size.java	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/test/java/nio/channels/FileChannel/Size.java	Wed Jul 05 18:10:27 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -69,7 +69,7 @@
         // Windows and Linux can't handle the really large file sizes for a truncate
         // or a positional write required by the test for 4563125
         String osName = System.getProperty("os.name");
-        if (osName.startsWith("SunOS") || osName.startsWith("Mac OS")) {
+        if (osName.startsWith("SunOS") || osName.contains("OS X")) {
             blah = File.createTempFile("blah", null);
             long testSize = ((long)Integer.MAX_VALUE) * 2;
             initTestFile(blah, 10);
--- a/jdk/test/java/nio/channels/FileChannel/Transfer.java	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/test/java/nio/channels/FileChannel/Transfer.java	Wed Jul 05 18:10:27 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -228,7 +228,7 @@
         // Windows and Linux can't handle the really large file sizes for a
         // truncate or a positional write required by the test for 4563125
         String osName = System.getProperty("os.name");
-        if (!(osName.startsWith("SunOS") || osName.startsWith("Mac OS")))
+        if (!(osName.startsWith("SunOS") || osName.contains("OS X")))
             return;
         File source = File.createTempFile("blah", null);
         source.deleteOnExit();
--- a/jdk/test/java/nio/file/FileSystem/Basic.java	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/test/java/nio/file/FileSystem/Basic.java	Wed Jul 05 18:10:27 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -76,7 +76,7 @@
             checkSupported(fs, "posix", "unix", "owner", "acl", "user");
         if (os.equals("Linux"))
             checkSupported(fs, "posix", "unix", "owner", "dos", "user");
-        if (os.startsWith("Mac OS"))
+        if (os.contains("OS X"))
             checkSupported(fs, "posix", "unix", "owner");
         if (os.equals("Windows"))
             checkSupported(fs, "owner", "dos", "acl", "user");
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/nio/file/WatchService/MayFlies.java	Wed Jul 05 18:10:27 2017 +0200
@@ -0,0 +1,181 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/* @test
+ * @bug 7164570
+ * @summary Test that CREATE and DELETE events are paired for very
+ *     short lived files
+ * @library ..
+ * @run main MayFlies
+ */
+
+import java.nio.file.*;
+import static java.nio.file.StandardWatchEventKinds.*;
+import java.util.*;
+import java.util.concurrent.*;
+
+public class MayFlies {
+
+    static volatile boolean stopped;
+
+    static volatile boolean failure;
+
+    /**
+     * Continuously creates short-lived files in a directory until {@code
+     * stopped} is set to {@code true}.
+     */
+    static class MayFlyHatcher implements Runnable {
+        static final Random rand = new Random();
+
+        private final Path dir;
+        private final String prefix;
+
+        private MayFlyHatcher(Path dir, String prefix) {
+            this.dir = dir;
+            this.prefix = prefix;
+        }
+
+        static void start(Path dir, String prefix) {
+            MayFlyHatcher hatcher = new MayFlyHatcher(dir, prefix);
+            new Thread(hatcher).start();
+        }
+
+        public void run() {
+            try {
+                int n = 0;
+                while (!stopped) {
+                    Path name = dir.resolve(prefix + (++n));
+                    Files.createFile(name);
+                    if (rand.nextBoolean())
+                        Thread.sleep(rand.nextInt(500));
+                    Files.delete(name);
+                    Thread.sleep(rand.nextInt(100));
+                }
+                System.out.format("%d %ss hatched%n", n, prefix);
+            } catch (Exception x) {
+                failure = true;
+                x.printStackTrace();
+            }
+        }
+    }
+
+    /**
+     * Test phases.
+     */
+    static enum Phase {
+        /**
+         * Short-lived files are being created
+         */
+        RUNNING,
+        /**
+         * Draining the final events
+         */
+        FINISHING,
+        /**
+         * No more events or overflow detected
+         */
+        FINISHED
+    };
+
+
+    public static void main(String[] args) throws Exception {
+
+        // schedules file creation to stop after 10 seconds
+        ScheduledExecutorService pool = Executors.newSingleThreadScheduledExecutor();
+        pool.schedule(
+            new Runnable() { public void run() { stopped = true; }},
+            10, TimeUnit.SECONDS);
+
+        Path dir = TestUtil.createTemporaryDirectory();
+
+        Set<Path> entries = new HashSet<>();
+        int nCreateEvents = 0;
+        boolean overflow = false;
+
+        try (WatchService watcher = FileSystems.getDefault().newWatchService()) {
+            WatchKey key = dir.register(watcher, ENTRY_CREATE, ENTRY_DELETE);
+
+            // start hatching Mayflies
+            MayFlyHatcher.start(dir, "clinger");
+            MayFlyHatcher.start(dir, "crawler");
+            MayFlyHatcher.start(dir, "burrower");
+            MayFlyHatcher.start(dir, "swimmer");
+
+            Phase phase = Phase.RUNNING;
+            while (phase != Phase.FINISHED) {
+                // during the running phase then poll for 1 second.
+                // once the file creation has stopped then move to the finishing
+                // phase where we do a long poll to ensure that all events have
+                // been read.
+                int time = (phase == Phase.RUNNING) ? 1 : 15;
+                key = watcher.poll(time, TimeUnit.SECONDS);
+                if (key == null) {
+                    if (phase == Phase.RUNNING && stopped)
+                        phase = Phase.FINISHING;
+                    else if (phase == Phase.FINISHING)
+                        phase = Phase.FINISHED;
+                } else {
+                    // process events
+                    for (WatchEvent<?> event: key.pollEvents()) {
+                        if (event.kind() == ENTRY_CREATE) {
+                            Path name = (Path)event.context();
+                            boolean added = entries.add(name);
+                            if (!added)
+                                throw new RuntimeException("Duplicate ENTRY_CREATE event");
+                            nCreateEvents++;
+                        } else if (event.kind() == ENTRY_DELETE) {
+                            Path name = (Path)event.context();
+                            boolean removed = entries.remove(name);
+                            if (!removed)
+                                throw new RuntimeException("ENTRY_DELETE event without ENTRY_CREATE event");
+                        } else if (event.kind() == OVERFLOW) {
+                            overflow = true;
+                            phase = Phase.FINISHED;
+                        } else {
+                            throw new RuntimeException("Unexpected event: " + event.kind());
+                        }
+                    }
+                    key.reset();
+                }
+            }
+
+            System.out.format("%d ENTRY_CREATE events read%n", nCreateEvents);
+
+            // there should be a DELETE event for each CREATE event and so the
+            // entries set should be empty.
+            if (!overflow && !entries.isEmpty())
+                throw new RuntimeException("Missed " + entries.size() + " DELETE event(s)");
+
+
+        } finally {
+            try {
+                TestUtil.removeAll(dir);
+            } finally {
+                pool.shutdown();
+            }
+        }
+
+        if (failure)
+            throw new RuntimeException("Test failed - see log file for details");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/prefs/RemoveNullKeyCheck.java	Wed Jul 05 18:10:27 2017 +0200
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/* @test
+ * @bug 7160242
+ * @summary Check if NullPointerException is thrown if the key passed
+ *          to remove() is null.
+ */
+
+import java.util.prefs.Preferences;
+
+public class RemoveNullKeyCheck {
+
+    public static void main(String[] args) throws Exception {
+       try {
+           Preferences node = Preferences.userRoot().node("N1");
+           node.remove(null);
+           throw new RuntimeException("Expected NullPointerException " +
+                                      "not thrown");
+       } catch (NullPointerException npe) {
+           System.out.println("NullPointerException thrown");
+       }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/swing/JComponent/7154030/bug7154030.java	Wed Jul 05 18:10:27 2017 +0200
@@ -0,0 +1,169 @@
+/*
+ * Copyright (c) 2012 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * Portions Copyright (c) 2012 IBM Corporation
+ */
+
+import javax.swing.JButton;
+import javax.swing.JDesktopPane;
+import javax.swing.JFrame;
+import javax.swing.SwingUtilities;
+import sun.awt.SunToolkit;
+
+import java.awt.AWTException;
+import java.awt.AlphaComposite;
+import java.awt.Color;
+import java.awt.Graphics;
+import java.awt.Graphics2D;
+import java.awt.Rectangle;
+import java.awt.Robot;
+import java.awt.Toolkit;
+import java.awt.image.BufferedImage;
+
+/* @test 1.1 2012/04/12
+ * @bug 7154030
+ * @summary Swing components fail to hide after calling hide()
+ * @author Jonathan Lu
+ * @library ../../regtesthelpers/
+ * @build Util
+ * @run main bug7154030
+ */
+
+public class bug7154030 {
+
+    private static JButton button = null;
+
+    public static void main(String[] args) throws Exception {
+        BufferedImage imageInit = null;
+
+        BufferedImage imageShow = null;
+
+        BufferedImage imageHide = null;
+
+        SunToolkit toolkit = (SunToolkit) Toolkit.getDefaultToolkit();
+
+        Robot robot = new Robot();
+
+        SwingUtilities.invokeAndWait(new Runnable() {
+
+            @Override
+            public void run() {
+                JDesktopPane desktop = new JDesktopPane();
+                button = new JButton("button");
+                JFrame frame = new JFrame();
+
+                button.setSize(200, 200);
+                button.setLocation(100, 100);
+                button.setForeground(Color.RED);
+                button.setBackground(Color.RED);
+                button.setOpaque(true);
+                button.setVisible(false);
+                desktop.add(button);
+
+                frame.setContentPane(desktop);
+                frame.setSize(300, 300);
+                frame.setLocation(0, 0);
+                frame.setVisible(true);
+                frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
+            }
+        });
+
+        toolkit.realSync();
+        imageInit = robot.createScreenCapture(new Rectangle(0, 0, 300, 300));
+
+        SwingUtilities.invokeAndWait(new Runnable() {
+
+            @Override
+            public void run() {
+                button.show();
+            }
+        });
+
+        toolkit.realSync();
+        imageShow = robot.createScreenCapture(new Rectangle(0, 0, 300, 300));
+        if (Util.compareBufferedImages(imageInit, imageShow)) {
+            throw new Exception("Failed to show opaque button");
+        }
+
+        toolkit.realSync();
+
+        SwingUtilities.invokeAndWait(new Runnable() {
+
+            @Override
+            public void run() {
+                button.hide();
+            }
+        });
+
+        toolkit.realSync();
+        imageHide = robot.createScreenCapture(new Rectangle(0, 0, 300, 300));
+
+        if (!Util.compareBufferedImages(imageInit, imageHide)) {
+            throw new Exception("Failed to hide opaque button");
+        }
+
+        SwingUtilities.invokeAndWait(new Runnable() {
+
+            @Override
+            public void run() {
+                button.setOpaque(false);
+                button.setBackground(new Color(128, 128, 0));
+                button.setVisible(false);
+            }
+        });
+
+        toolkit.realSync();
+        imageInit = robot.createScreenCapture(new Rectangle(0, 0, 300, 300));
+
+        SwingUtilities.invokeAndWait(new Runnable() {
+
+            @Override
+            public void run() {
+                button.show();
+            }
+        });
+
+        toolkit.realSync();
+        imageShow = robot.createScreenCapture(new Rectangle(0, 0, 300, 300));
+
+        SwingUtilities.invokeAndWait(new Runnable() {
+
+            @Override
+            public void run() {
+                button.hide();
+            }
+        });
+
+        if (Util.compareBufferedImages(imageInit, imageShow)) {
+            throw new Exception("Failed to show non-opaque button");
+        }
+
+        toolkit.realSync();
+        imageHide = robot.createScreenCapture(new Rectangle(0, 0, 300, 300));
+
+        if (!Util.compareBufferedImages(imageInit, imageHide)) {
+            throw new Exception("Failed to hide non-opaque button");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/swing/JTable/7055065/bug7055065.java	Wed Jul 05 18:10:27 2017 +0200
@@ -0,0 +1,178 @@
+/*
+ * Copyright (c) 2012 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * Portions Copyright (c) 2012 IBM Corporation
+ */
+
+/* @test 1.1 2012/04/19
+ * @bug 7055065
+ * @summary NullPointerException when sorting JTable with empty cell
+ * @author Jonathan Lu
+ * @library ../../regtesthelpers/
+ * @build Util
+ * @run main bug7055065
+ */
+
+import java.awt.Dimension;
+import java.awt.Point;
+import java.awt.Rectangle;
+import java.awt.Robot;
+import java.awt.Toolkit;
+import java.awt.event.InputEvent;
+import java.awt.event.KeyEvent;
+import javax.swing.JFrame;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JTable;
+import javax.swing.SwingUtilities;
+import javax.swing.table.AbstractTableModel;
+import javax.swing.table.TableModel;
+import javax.swing.table.TableRowSorter;
+import sun.awt.SunToolkit;
+import java.util.concurrent.Callable;
+
+public class bug7055065 {
+
+    private static JTable table;
+
+    public static void main(String[] args) throws Exception {
+        SunToolkit toolkit = (SunToolkit) Toolkit.getDefaultToolkit();
+        Robot robot = new Robot();
+
+        SwingUtilities.invokeAndWait(new Runnable() {
+
+            public void run() {
+                createAndShowUI();
+            }
+        });
+
+        toolkit.realSync();
+        clickCell(robot, 1, 1);
+        Util.hitKeys(robot, KeyEvent.VK_BACK_SPACE, KeyEvent.VK_BACK_SPACE,
+                KeyEvent.VK_BACK_SPACE);
+
+        toolkit.realSync();
+        clickColumnHeader(robot, 1);
+
+        toolkit.realSync();
+        clickColumnHeader(robot, 1);
+    }
+
+    private static void clickCell(Robot robot, final int row, final int column)
+        throws Exception {
+        Point point = Util.invokeOnEDT(new Callable<Point>() {
+            @Override
+            public Point call() throws Exception {
+                Rectangle rect = table.getCellRect(row, column, false);
+                Point point = new Point(rect.x + rect.width / 2, rect.y
+                    + rect.height / 2);
+                SwingUtilities.convertPointToScreen(point, table);
+                return point;
+            }
+        });
+
+        robot.mouseMove(point.x, point.y);
+        robot.mousePress(InputEvent.BUTTON1_MASK);
+        robot.mouseRelease(InputEvent.BUTTON1_MASK);
+    }
+
+    private static void clickColumnHeader(Robot robot, final int column)
+        throws Exception {
+        Point point = Util.invokeOnEDT(new Callable<Point>() {
+            @Override
+            public Point call() throws Exception {
+                Rectangle rect = table.getCellRect(0, column, false);
+                int headerHeight = table.getTableHeader().getHeight();
+                Point point = new Point(rect.x + rect.width / 2, rect.y
+                    - headerHeight / 2);
+                SwingUtilities.convertPointToScreen(point, table);
+                return point;
+            }
+        });
+
+        robot.mouseMove(point.x, point.y);
+        robot.mousePress(InputEvent.BUTTON1_MASK);
+        robot.mouseRelease(InputEvent.BUTTON1_MASK);
+    }
+
+    private static void createAndShowUI() {
+        JFrame frame = new JFrame("SimpleTableDemo");
+        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+
+        JPanel newContentPane = new JPanel();
+        newContentPane.setOpaque(true);
+        frame.setContentPane(newContentPane);
+
+        final String[] columnNames = { "String", "Number" };
+        final Object[][] data = { { "aaaa", new Integer(1) },
+            { "bbbb", new Integer(3) }, { "cccc", new Integer(2) },
+            { "dddd", new Integer(4) }, { "eeee", new Integer(5) } };
+        table = new JTable(data, columnNames);
+
+        table.setPreferredScrollableViewportSize(new Dimension(500, 400));
+        table.setFillsViewportHeight(true);
+
+        TableModel dataModel = new AbstractTableModel() {
+
+            public int getColumnCount() {
+                return columnNames.length;
+            }
+
+            public int getRowCount() {
+                return data.length;
+            }
+
+            public Object getValueAt(int row, int col) {
+                return data[row][col];
+            }
+
+            public String getColumnName(int column) {
+                return columnNames[column];
+            }
+
+            public Class<?> getColumnClass(int c) {
+                return getValueAt(0, c).getClass();
+            }
+
+            public boolean isCellEditable(int row, int col) {
+                return col != 5;
+            }
+
+            public void setValueAt(Object aValue, int row, int column) {
+                data[row][column] = aValue;
+            }
+        };
+        table.setModel(dataModel);
+        TableRowSorter<TableModel> sorter = new TableRowSorter<TableModel>(
+                dataModel);
+        table.setRowSorter(sorter);
+
+        JScrollPane scrollPane = new JScrollPane(table);
+        newContentPane.add(scrollPane);
+
+        frame.pack();
+        frame.setLocation(0, 0);
+        frame.setVisible(true);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/swing/JTree/4908142/bug4908142.java	Wed Jul 05 18:10:27 2017 +0200
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+/*
+ * @test
+ * @bug 4908142
+ * @summary JList doesn't handle search function appropriately
+ * @author Andrey Pikalev
+ * @library ../../regtesthelpers
+ * @build Util
+ * @run main bug4908142
+ */
+import javax.swing.*;
+import javax.swing.tree.*;
+import java.awt.*;
+import java.awt.event.*;
+import java.util.concurrent.Callable;
+import sun.awt.SunToolkit;
+
+public class bug4908142 {
+
+    private static JTree tree;
+
+    public static void main(String[] args) throws Exception {
+
+        SunToolkit toolkit = (SunToolkit) Toolkit.getDefaultToolkit();
+        Robot robot = new Robot();
+        robot.setAutoDelay(50);
+
+        SwingUtilities.invokeAndWait(new Runnable() {
+
+            public void run() {
+                createAndShowGUI();
+            }
+        });
+
+        toolkit.realSync();
+
+        SwingUtilities.invokeAndWait(new Runnable() {
+
+            public void run() {
+                tree.requestFocus();
+                tree.setSelectionRow(0);
+            }
+        });
+
+        toolkit.realSync();
+
+
+        robot.keyPress(KeyEvent.VK_A);
+        robot.keyRelease(KeyEvent.VK_A);
+        robot.keyPress(KeyEvent.VK_A);
+        robot.keyRelease(KeyEvent.VK_A);
+        robot.keyPress(KeyEvent.VK_D);
+        robot.keyRelease(KeyEvent.VK_D);
+        toolkit.realSync();
+
+
+        String sel = Util.invokeOnEDT(new Callable<String>() {
+
+            @Override
+            public String call() throws Exception {
+                return tree.getLastSelectedPathComponent().toString();
+            }
+        });
+
+        if (!"aad".equals(sel)) {
+            throw new Error("The selected index should be \"aad\", but not " + sel);
+        }
+    }
+
+    private static void createAndShowGUI() {
+        JFrame fr = new JFrame("Test");
+        fr.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+
+        String[] data = {"aaa", "aab", "aac", "aad", "ade", "bba"};
+        final DefaultMutableTreeNode root = new DefaultMutableTreeNode(data[0]);
+        for (int i = 1; i < data.length; i++) {
+            DefaultMutableTreeNode node = new DefaultMutableTreeNode(data[i]);
+            root.add(node);
+        }
+
+        tree = new JTree(root);
+
+        JScrollPane sp = new JScrollPane(tree);
+        fr.getContentPane().add(sp);
+        fr.setSize(200, 200);
+        fr.setVisible(true);
+    }
+}
--- a/jdk/test/sun/net/www/protocol/jar/B4957695.java	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/test/sun/net/www/protocol/jar/B4957695.java	Wed Jul 05 18:10:27 2017 +0200
@@ -62,7 +62,8 @@
                 readOneRequest(s.getInputStream());
                 try (OutputStreamWriter ow =
                      new OutputStreamWriter((s.getOutputStream()))) {
-                    FileInputStream fin = new FileInputStream("foo1.jar");
+                    FileInputStream fin = new FileInputStream(new File(
+                        System.getProperty("test.src", "."), "foo1.jar"));
                     int length = fin.available();
                     byte[] b = new byte[length-10];
                     fin.read(b, 0, length-10);
--- a/jdk/test/sun/nio/ch/SelProvider.java	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/test/sun/nio/ch/SelProvider.java	Wed Jul 05 18:10:27 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2012 Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -39,7 +39,7 @@
             expected = "sun.nio.ch.DevPollSelectorProvider";
         } else if ("Linux".equals(osname)) {
             expected = "sun.nio.ch.EPollSelectorProvider";
-        } else if (osname.startsWith("Mac OS")) {
+        } else if (osname.contains("OS X")) {
             expected = "sun.nio.ch.KQueueSelectorProvider";
         } else
             return;
--- a/jdk/test/tools/launcher/Arrrghs.java	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/test/tools/launcher/Arrrghs.java	Wed Jul 05 18:10:27 2017 +0200
@@ -24,7 +24,7 @@
 /**
  * @test
  * @bug 5030233 6214916 6356475 6571029 6684582 6742159 4459600 6758881 6753938
- *      6894719 6968053
+ *      6894719 6968053 7151314
  * @summary Argument parsing validation.
  * @compile -XDignore.symbol.file Arrrghs.java
  * @run main Arrrghs
@@ -237,6 +237,13 @@
         tr.checkNegative();
         tr.isNotZeroOutput();
         System.out.println(tr);
+
+        // 7151314, test for non-negative exit value for an incorrectly formed
+        // command line, '% java -jar -W', note the bogus -W
+        tr = doExec(javaCmd, "-jar", "-W");
+        tr.checkNegative();
+        tr.contains("Unrecognized option: -W");
+        System.out.println(tr);
     }
 
     /*
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/tools/launcher/EnvironmentVariables.java	Wed Jul 05 18:10:27 2017 +0200
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * see TestSpecialArgs.java
+ * bug 7131021
+ * summary Checks for environment variables set by the launcher
+ * author anthony.petrov@oracle.com: area=launcher
+ */
+
+public class EnvironmentVariables {
+    public static void main(String[] args) {
+        if (args.length != 2) {
+            throw new RuntimeException("ERROR: two command line arguments expected");
+        }
+
+        String name = args[0];
+        String expect = args[1];
+        String key = null;
+
+        if (!name.endsWith("*")) {
+            key = name;
+        } else {
+            name = name.split("\\*")[0];
+
+            for (String s : System.getenv().keySet()) {
+                if (s.startsWith(name)) {
+                    if (key == null) {
+                        key = s;
+                    } else {
+                        System.err.println("WARNING: more variables match: " + s);
+                    }
+                }
+            }
+
+            if (key == null) {
+                throw new RuntimeException("ERROR: unable to find a match for: " + name);
+            }
+        }
+
+        System.err.println("Will check the variable named: '" + key +
+                "' expecting the value: '" + expect + "'");
+
+        if (!System.getenv().containsKey(key)) {
+            throw new RuntimeException("ERROR: the variable '" + key +
+                    "' is not present in the environment");
+        }
+
+        if (!expect.equals(System.getenv().get(key))) {
+            throw new RuntimeException("ERROR: expected: '" + expect +
+                    "', got: '" + System.getenv().get(key) + "'");
+        }
+        for (String x : args) {
+            System.err.print(x + " ");
+        }
+        System.err.println("-----> Passed!");
+    }
+}
+
--- a/jdk/test/tools/launcher/TestHelper.java	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/test/tools/launcher/TestHelper.java	Wed Jul 05 18:10:27 2017 +0200
@@ -21,6 +21,9 @@
  * questions.
  */
 
+import java.io.StringWriter;
+import java.io.PrintWriter;
+import java.util.Set;
 import java.io.BufferedReader;
 import java.io.File;
 import java.io.FileFilter;
@@ -66,7 +69,7 @@
     static final boolean isWindows =
             System.getProperty("os.name", "unknown").startsWith("Windows");
     static final boolean isMacOSX =
-            System.getProperty("os.name", "unknown").startsWith("Mac");
+            System.getProperty("os.name", "unknown").contains("OS X");
     static final boolean is64Bit =
             System.getProperty("sun.arch.data.model").equals("64");
     static final boolean is32Bit =
@@ -87,6 +90,7 @@
     static final String EXE_FILE_EXT   = ".exe";
     static final String JLDEBUG_KEY     = "_JAVA_LAUNCHER_DEBUG";
     static final String EXPECTED_MARKER = "TRACER_MARKER:About to EXEC";
+    static final String TEST_PREFIX     = "###TestError###: ";
 
     static int testExitValue = 0;
 
@@ -316,19 +320,28 @@
     }
 
     static TestResult doExec(String...cmds) {
-        return doExec(null, cmds);
+        return doExec(null, null, cmds);
     }
 
+    static TestResult doExec(Map<String, String> envToSet, String...cmds) {
+        return doExec(envToSet, null, cmds);
+    }
     /*
      * A method which executes a java cmd and returns the results in a container
      */
-    static TestResult doExec(Map<String, String> envToSet, String...cmds) {
+    static TestResult doExec(Map<String, String> envToSet,
+                             Set<String> envToRemove, String...cmds) {
         String cmdStr = "";
         for (String x : cmds) {
             cmdStr = cmdStr.concat(x + " ");
         }
         ProcessBuilder pb = new ProcessBuilder(cmds);
         Map<String, String> env = pb.environment();
+        if (envToRemove != null) {
+            for (String key : envToRemove) {
+                env.remove(key);
+            }
+        }
         if (envToSet != null) {
             env.putAll(envToSet);
         }
@@ -376,7 +389,8 @@
      * of use methods to check the test results.
      */
     static class TestResult {
-        StringBuilder status;
+        PrintWriter status;
+        StringWriter sw;
         int exitValue;
         List<String> testOutput;
         Map<String, String> env;
@@ -384,27 +398,33 @@
 
         public TestResult(String str, int rv, List<String> oList,
                 Map<String, String> env, Throwable t) {
-            status = new StringBuilder("Executed command: " + str + "\n");
+            sw = new StringWriter();
+            status = new PrintWriter(sw);
+            status.println("Executed command: " + str + "\n");
             exitValue = rv;
             testOutput = oList;
             this.env = env;
             this.t = t;
         }
 
-        void appendStatus(String x) {
-            status = status.append("  " + x + "\n");
+        void appendError(String x) {
+            status.println(TEST_PREFIX + x);
+        }
+
+        void indentStatus(String x) {
+            status.println("  " + x);
         }
 
         void checkNegative() {
             if (exitValue == 0) {
-                appendStatus("Error: test must not return 0 exit value");
+                appendError("test must not return 0 exit value");
                 testExitValue++;
             }
         }
 
         void checkPositive() {
             if (exitValue != 0) {
-                appendStatus("Error: test did not return 0 exit value");
+                appendError("test did not return 0 exit value");
                 testExitValue++;
             }
         }
@@ -415,7 +435,7 @@
 
         boolean isZeroOutput() {
             if (!testOutput.isEmpty()) {
-                appendStatus("Error: No message from cmd please");
+                appendError("No message from cmd please");
                 testExitValue++;
                 return false;
             }
@@ -424,7 +444,7 @@
 
         boolean isNotZeroOutput() {
             if (testOutput.isEmpty()) {
-                appendStatus("Error: Missing message");
+                appendError("Missing message");
                 testExitValue++;
                 return false;
             }
@@ -433,22 +453,25 @@
 
         @Override
         public String toString() {
-            status.append("++++Begin Test Info++++\n");
-            status.append("++++Test Environment++++\n");
+            status.println("++++Begin Test Info++++");
+            status.println("++++Test Environment++++");
             for (String x : env.keySet()) {
-                status.append(x).append("=").append(env.get(x)).append("\n");
+                indentStatus(x + "=" + env.get(x));
             }
-            status.append("++++Test Output++++\n");
+            status.println("++++Test Output++++");
             for (String x : testOutput) {
-                appendStatus(x);
+                indentStatus(x);
             }
-            status.append("++++Test Stack Trace++++\n");
-            status.append(t.toString());
+            status.println("++++Test Stack Trace++++");
+            status.println(t.toString());
             for (StackTraceElement e : t.getStackTrace()) {
-                status.append(e.toString());
+                indentStatus(e.toString());
             }
-            status.append("++++End of Test Info++++\n");
-            return status.toString();
+            status.println("++++End of Test Info++++");
+            status.flush();
+            String out = sw.toString();
+            status.close();
+            return out;
         }
 
         boolean contains(String str) {
@@ -457,7 +480,7 @@
                     return true;
                 }
             }
-            appendStatus("Error: string <" + str + "> not found");
+            appendError("string <" + str + "> not found");
             testExitValue++;
             return false;
         }
@@ -468,7 +491,7 @@
                     return true;
                 }
             }
-            appendStatus("Error: string <" + stringToMatch + "> not found");
+            appendError("string <" + stringToMatch + "> not found");
             testExitValue++;
             return false;
         }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/tools/launcher/TestSpecialArgs.java	Wed Jul 05 18:10:27 2017 +0200
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 7124089 7131021
+ * @summary Checks for MacOSX specific flags are accepted or rejected, and
+ *          MacOSX platforms specific environment is consistent.
+ * @compile -XDignore.symbol.file TestSpecialArgs.java EnvironmentVariables.java
+ * @run main TestSpecialArgs
+ */
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+public class TestSpecialArgs extends TestHelper {
+
+    public static void main(String... args) {
+        final Map<String, String> envMap = new HashMap<>();
+        envMap.put("_JAVA_LAUNCHER_DEBUG", "true");
+
+        TestResult tr = doExec(envMap, javaCmd, "-XstartOnFirstThread", "-version");
+        if (isMacOSX) {
+            if (!tr.contains("In same thread")) {
+                System.out.println(tr);
+                throw new RuntimeException("Error: not running in the same thread ?");
+            }
+            if (!tr.isOK()) {
+                System.out.println(tr);
+                throw new RuntimeException("Error: arg was rejected ????");
+            }
+        } else {
+            if (tr.isOK()) {
+                System.out.println(tr);
+                throw new RuntimeException("Error: argument was accepted ????");
+            }
+        }
+
+        tr = doExec(javaCmd, "-Xdock:/tmp/not-available", "-version");
+        if (isMacOSX) {
+            if (!tr.isOK()) {
+                System.out.println(tr);
+                throw new RuntimeException("Error: arg was rejected ????");
+            }
+        } else {
+            if (tr.isOK()) {
+                System.out.println(tr);
+                throw new RuntimeException("Error: argument was accepted ????");
+            }
+        }
+        // MacOSX specific tests ensue......
+        if (!isMacOSX)
+            return;
+        Set<String> envToRemove = new HashSet<>();
+        Map<String, String> map = System.getenv();
+        for (String s : map.keySet()) {
+            if (s.startsWith("JAVA_MAIN_CLASS_")
+                    || s.startsWith("APP_NAME_")
+                    || s.startsWith("APP_ICON_")) {
+                envToRemove.add(s);
+            }
+        }
+        runTest(envToRemove, javaCmd, "-cp", TEST_CLASSES_DIR.getAbsolutePath(),
+                "EnvironmentVariables", "JAVA_MAIN_CLASS_*",
+                "EnvironmentVariables");
+
+        runTest(envToRemove, javaCmd, "-cp", TEST_CLASSES_DIR.getAbsolutePath(),
+                "-Xdock:name=TestAppName", "EnvironmentVariables",
+                "APP_NAME_*", "TestAppName");
+
+        runTest(envToRemove, javaCmd, "-cp", TEST_CLASSES_DIR.getAbsolutePath(),
+                "-Xdock:icon=TestAppIcon", "EnvironmentVariables",
+                "APP_ICON_*", "TestAppIcon");
+    }
+
+    static void runTest(Set<String> envToRemove, String... args) {
+        TestResult tr = doExec(null, envToRemove, args);
+        if (!tr.isOK()) {
+            System.err.println(tr.toString());
+            throw new RuntimeException("Test Fails");
+        }
+    }
+}
--- a/jdk/test/tools/pack200/AttributeTests.java	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/test/tools/pack200/AttributeTests.java	Wed Jul 05 18:10:27 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -27,7 +27,7 @@
 import java.util.List;
 /*
  * @test
- * @bug 6982312
+ * @bug 6746111
  * @summary tests various classfile format and attribute handling by pack200
  * @compile -XDignore.symbol.file Utils.java AttributeTests.java
  * @run main AttributeTests
@@ -36,40 +36,8 @@
 public class AttributeTests {
 
     public static void main(String... args) throws Exception {
-        test6982312();
         test6746111();
     }
-    /*
-     * This is an interim test, which ensures pack200 handles JSR-292 related
-     * classfile changes seamlessly, until all the classfile changes in jdk7
-     * and jdk8 are fully supported. At that time this test should be jettisoned,
-     * along with the associated jar file.
-     *
-     * The jar file  contains sources and classes noting the classes were
-     * derived by using the javac from the lambda project,
-     * see http://openjdk.java.net/projects/lambda/.
-     * Therefore the classes contained in the jar cannot be compiled, using
-     * the standard jdk7's javac compiler.
-     */
-    static void test6982312() throws IOException {
-        String pack200Cmd = Utils.getPack200Cmd();
-        File dynJar = new File(".", "dyn.jar");
-        Utils.copyFile(new File(Utils.TEST_SRC_DIR, "dyn.jar"), dynJar);
-        File testJar = new File(".", "test.jar");
-        List<String> cmds = new ArrayList<String>();
-        cmds.add(pack200Cmd);
-        cmds.add("--repack");
-        cmds.add(testJar.getAbsolutePath());
-        cmds.add(dynJar.getAbsolutePath());
-        Utils.runExec(cmds);
-        /*
-         * compare the repacked jar bit-wise, as all the files
-         * should be transmitted "as-is".
-         */
-        Utils.doCompareBitWise(dynJar.getAbsoluteFile(), testJar.getAbsoluteFile());
-        testJar.delete();
-        dynJar.delete();
-    }
 
     /*
      * this test checks to see if we get the expected strings for output
--- a/jdk/test/tools/pack200/PackageVersionTest.java	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/test/tools/pack200/PackageVersionTest.java	Wed Jul 05 18:10:27 2017 +0200
@@ -1,6 +1,6 @@
 
 /*
- * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -51,6 +51,9 @@
     public final static int JAVA6_PACKAGE_MAJOR_VERSION = 160;
     public final static int JAVA6_PACKAGE_MINOR_VERSION = 1;
 
+    public final static int JAVA7_PACKAGE_MAJOR_VERSION = 170;
+    public final static int JAVA7_PACKAGE_MINOR_VERSION = 1;
+
     public static void main(String... args) {
         if (!javaHome.getName().endsWith("jre")) {
             throw new RuntimeException("Error: requires an SDK to run");
@@ -68,9 +71,8 @@
         verifyPack("Test6.class", JAVA6_PACKAGE_MAJOR_VERSION,
                 JAVA6_PACKAGE_MINOR_VERSION);
 
-        // TODO: change this to the java7 package version as needed.
-        verifyPack("Test7.class", JAVA6_PACKAGE_MAJOR_VERSION,
-                JAVA6_PACKAGE_MINOR_VERSION);
+        verifyPack("Test7.class", JAVA7_PACKAGE_MAJOR_VERSION,
+                JAVA7_PACKAGE_MINOR_VERSION);
 
         // test for resource file, ie. no class files
         verifyPack("Test6.java", JAVA5_PACKAGE_MAJOR_VERSION,
--- a/jdk/test/tools/pack200/Utils.java	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/test/tools/pack200/Utils.java	Wed Jul 05 18:10:27 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -129,8 +129,10 @@
         init();
         List<String> cmds = new ArrayList<String>();
         cmds.add(getJavaCmd());
-        cmds.add("-jar");
-        cmds.add(VerifierJar.getName());
+        cmds.add("-cp");
+        cmds.add(Utils.locateJar("tools.jar") +
+                System.getProperty("path.separator") + VerifierJar.getName());
+        cmds.add("sun.tools.pack.verify.Main");
         cmds.add(reference.getAbsolutePath());
         cmds.add(specimen.getAbsolutePath());
         cmds.add("-O");
@@ -142,8 +144,10 @@
         init();
         List<String> cmds = new ArrayList<String>();
         cmds.add(getJavaCmd());
-        cmds.add("-jar");
-        cmds.add(VerifierJar.getName());
+        cmds.add("-cp");
+        cmds.add(Utils.locateJar("tools.jar")
+                + System.getProperty("path.separator") + VerifierJar.getName());
+        cmds.add("sun.tools.pack.verify.Main");
         cmds.add(reference.getName());
         cmds.add(specimen.getName());
         cmds.add("-O");
Binary file jdk/test/tools/pack200/dyn.jar has changed
--- a/jdk/test/tools/pack200/pack200-verifier/data/README	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/test/tools/pack200/pack200-verifier/data/README	Wed Jul 05 18:10:27 2017 +0200
@@ -2,19 +2,19 @@
 different sources, some are hand-crafted invalid class files (odds directory),
 or from random JDK builds.
 
-Generally these files serve to ensure the integrity of the packer and unpacker
-by,
-   1. maximizing the test coverage.
-   2. exercising all the Bands in the pack200 specification.
-   2. testing the behavior of the packer with invalid classes.
-   3. testing the archive integrity, ordering and description (date, sizes,
+Generally these files serve to ensure the integrity of the packer and 
+unpacker by,
+   * maximizing the test coverage.
+   * exercising all the Bands in the pack200 specification.
+   * testing the behavior of the packer with invalid classes.
+   * testing the archive integrity, ordering and description (date, sizes,
       CRC etc.)
 
 Build:
 To rebuild this JAR follow these steps:
     1. unzip the golden.jar to some directory lets call it "example"
     2. now we can add any directories with files into example.
-    2. run the script BUILDME.sh  as
+    3. run the script BUILDME.sh  as
        % sh BUILDME.sh example
 
 Note: the BUILDME.sh is known to work on all Unix platforms as well as Windows
@@ -32,7 +32,7 @@
     Basic:
         % pack200 --repack test.jar golden.jar
 
-    Advanced:
+    Advanced: inspection of band contents
        Create a pack.conf as follows:
        % cat pack.conf
        com.sun.java.util.jar.pack.dump.bands=true
@@ -41,5 +41,6 @@
            --verbose golden.jar.pack golden.jar
 
        This command will dump the Bands in a unique directory BD_XXXXXX,
-       one can inspect the directory to ensure all of the bands are being
-       generated. Familiarity of the  Pack200 specification is suggested.
\ No newline at end of file
+       one can then inspect the directory to ensure all of the bands are being
+       generated. Familiarity of the Pack200 specification is strongly
+       suggested.
Binary file jdk/test/tools/pack200/pack200-verifier/data/golden.jar has changed
--- a/jdk/test/tools/pack200/pack200-verifier/make/build.xml	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/test/tools/pack200/pack200-verifier/make/build.xml	Wed Jul 05 18:10:27 2017 +0200
@@ -1,5 +1,5 @@
 <project name="PackageVerify" default="dist" basedir="..">
-  <!-- Requires ant 1.6.1+ and JDK 1.6+-->
+  <!-- Requires ant 1.6.1+ and JDK 1.7+-->
 
   <!-- set global properties for this build -->
   <property name="src"      value="${basedir}/src"/>
@@ -22,7 +22,7 @@
   <target name="compile" depends="init">
     <!-- Compile the java code from ${src} into ${build} -->
     <javac 
-	source="1.6"
+	source="1.7"
 	srcdir="${src}"
 	destdir="${build}/classes"
 	verbose="no"
@@ -32,7 +32,7 @@
 
   <target name="doc" depends="init, compile">
       <javadoc
-        source="1.6"
+        source="1.7"
         sourcepath="${src}"
         destdir="${api}"
       />
--- a/jdk/test/tools/pack200/pack200-verifier/src/xmlkit/ClassReader.java	Wed Jul 05 18:09:43 2017 +0200
+++ b/jdk/test/tools/pack200/pack200-verifier/src/xmlkit/ClassReader.java	Wed Jul 05 18:10:27 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -24,16 +24,58 @@
  */
 package xmlkit; // -*- mode: java; indent-tabs-mode: nil -*-
 
+import com.sun.tools.classfile.AccessFlags;
+import com.sun.tools.classfile.Annotation;
+import com.sun.tools.classfile.Annotation.*;
+import com.sun.tools.classfile.AnnotationDefault_attribute;
+import com.sun.tools.classfile.Attribute;
+import com.sun.tools.classfile.Attributes;
+import com.sun.tools.classfile.BootstrapMethods_attribute;
+import com.sun.tools.classfile.CharacterRangeTable_attribute;
+import com.sun.tools.classfile.ClassFile;
+import com.sun.tools.classfile.Code_attribute;
+import com.sun.tools.classfile.CompilationID_attribute;
+import com.sun.tools.classfile.ConstantPool;
+import com.sun.tools.classfile.ConstantPool.*;
+import com.sun.tools.classfile.ConstantPoolException;
+import com.sun.tools.classfile.ConstantValue_attribute;
+import com.sun.tools.classfile.DefaultAttribute;
+import com.sun.tools.classfile.Deprecated_attribute;
+import com.sun.tools.classfile.Descriptor.InvalidDescriptor;
+import com.sun.tools.classfile.EnclosingMethod_attribute;
+import com.sun.tools.classfile.Exceptions_attribute;
+import com.sun.tools.classfile.Field;
+import com.sun.tools.classfile.InnerClasses_attribute;
+import com.sun.tools.classfile.InnerClasses_attribute.Info;
+import com.sun.tools.classfile.Instruction;
+import com.sun.tools.classfile.Instruction.TypeKind;
+import com.sun.tools.classfile.LineNumberTable_attribute;
+import com.sun.tools.classfile.LocalVariableTable_attribute;
+import com.sun.tools.classfile.LocalVariableTypeTable_attribute;
+import com.sun.tools.classfile.Method;
+import com.sun.tools.classfile.Opcode;
+import com.sun.tools.classfile.RuntimeInvisibleAnnotations_attribute;
+import com.sun.tools.classfile.RuntimeInvisibleParameterAnnotations_attribute;
+import com.sun.tools.classfile.RuntimeVisibleAnnotations_attribute;
+import com.sun.tools.classfile.RuntimeVisibleParameterAnnotations_attribute;
+import com.sun.tools.classfile.Signature_attribute;
+import com.sun.tools.classfile.SourceDebugExtension_attribute;
+import com.sun.tools.classfile.SourceFile_attribute;
+import com.sun.tools.classfile.SourceID_attribute;
+import com.sun.tools.classfile.StackMapTable_attribute;
+import com.sun.tools.classfile.StackMapTable_attribute.*;
+import com.sun.tools.classfile.StackMap_attribute;
+import com.sun.tools.classfile.Synthetic_attribute;
 import java.util.*;
-import java.util.jar.*;
-import java.lang.reflect.*;
 import java.io.*;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
 import xmlkit.XMLKit.Element;
 
 /*
- * @author jrose
+ * @author jrose, ksrini
  */
-public class ClassReader extends ClassSyntax {
+public class ClassReader {
 
     private static final CommandLineParser CLP = new CommandLineParser(""
             + "-source:     +> = \n"
@@ -41,23 +83,24 @@
             + "-encoding:   +> = \n"
             + "-jcov           $ \n   -nojcov         !-jcov        \n"
             + "-verbose        $ \n   -noverbose      !-verbose     \n"
-            + "-pretty         $ \n   -nopretty       !-pretty      \n"
             + "-keepPath       $ \n   -nokeepPath     !-keepPath    \n"
             + "-keepCP         $ \n   -nokeepCP       !-keepCP      \n"
-            + "-keepBytes      $ \n   -nokeepBytes    !-keepBytes   \n"
-            + "-parseBytes     $ \n   -noparseBytes   !-parseBytes  \n"
-            + "-resolveRefs    $ \n   -noresolveRefs  !-resolveRefs \n"
             + "-keepOrder      $ \n   -nokeepOrder    !-keepOrder   \n"
-            + "-keepSizes      $ \n   -nokeepSizes    !-keepSizes   \n"
             + "-continue       $ \n   -nocontinue     !-continue    \n"
-            + "-attrDef        & \n"
             + "-@         >-@  . \n"
             + "-              +? \n"
             + "\n");
 
+
+    // Protected state for representing the class file.
+    protected Element cfile;          // <ClassFile ...>
+    protected Element cpool;          // <ConstantPool ...>
+    protected Element klass;          // <Class ...>
+    protected List<String> thePool;    // stringified flattened Constant Pool
+
     public static void main(String[] ava) throws IOException {
-        ArrayList<String> av = new ArrayList<String>(Arrays.asList(ava));
-        HashMap<String, String> props = new HashMap<String, String>();
+        ArrayList<String> av = new ArrayList<>(Arrays.asList(ava));
+        HashMap<String, String> props = new HashMap<>();
         props.put("-encoding:", "UTF8");  // default
         props.put("-keepOrder", null);    // CLI default
         props.put("-pretty", "1");     // CLI default
@@ -80,7 +123,7 @@
         }
          */
         if (av.isEmpty()) {
-            av.add("doit");  //to enter this loop
+            av.add("");  //to enter this loop
         }
         boolean readList = false;
         for (String a : av) {
@@ -119,7 +162,7 @@
     private static void doFile(String a,
             File source, File dest,
             ClassReader options, String encoding,
-            boolean contError) throws IOException {
+            boolean contError) throws IOException  {
         if (!contError) {
             doFile(a, source, dest, options, encoding);
         } else {
@@ -127,40 +170,49 @@
                 doFile(a, source, dest, options, encoding);
             } catch (Exception ee) {
                 System.out.println("Error processing " + source + ": " + ee);
+                ee.printStackTrace();
             }
         }
     }
 
-    private static void doJar(String a, File source, File dest, ClassReader options,
-            String encoding, Boolean contError) throws IOException {
+    private static void doJar(String a, File source, File dest,
+                              ClassReader options, String encoding,
+                              Boolean contError) throws IOException {
         try {
             JarFile jf = new JarFile(source);
-            for (JarEntry je : Collections.list((Enumeration<JarEntry>) jf.entries())) {
+            for (JarEntry je : Collections.list(jf.entries())) {
                 String name = je.getName();
                 if (!name.endsWith(".class")) {
                     continue;
                 }
-                doStream(name, jf.getInputStream(je), dest, options, encoding);
+                try {
+                    doStream(name, jf.getInputStream(je), dest, options, encoding);
+                } catch (Exception e) {
+                    if (contError) {
+                        System.out.println("Error processing " + source + ": " + e);
+                        e.printStackTrace();
+                        continue;
+                    }
+                }
             }
         } catch (IOException ioe) {
-            if (contError) {
-                System.out.println("Error processing " + source + ": " + ioe);
-            } else {
-                throw ioe;
-            }
+            throw ioe;
         }
     }
 
     private static void doStream(String a, InputStream in, File dest,
-            ClassReader options, String encoding) throws IOException {
+                                 ClassReader options, String encoding) throws IOException {
 
         File f = new File(a);
         ClassReader cr = new ClassReader(options);
-        Element e = cr.readFrom(in);
+        Element e;
+        if (options.verbose) {
+            System.out.println("Reading " + f);
+        }
+        e = cr.readFrom(in);
 
         OutputStream out;
         if (dest == null) {
-            //System.out.println(e.prettyString());
             out = System.out;
         } else {
             File outf = new File(dest, f.isAbsolute() ? f.getName() : f.getPath());
@@ -202,20 +254,8 @@
 
     }
 
-    public static BufferedReader makeReader(InputStream in, String encoding) throws IOException {
-        // encoding in DEFAULT, '', UTF8, 8BIT, , or any valid encoding name
-        if (encoding.equals("8BIT")) {
-            encoding = EIGHT_BIT_CHAR_ENCODING;
-        }
-        if (encoding.equals("UTF8")) {
-            encoding = UTF8_ENCODING;
-        }
-        if (encoding.equals("DEFAULT")) {
-            encoding = null;
-        }
-        if (encoding.equals("-")) {
-            encoding = null;
-        }
+    public static BufferedReader makeReader(InputStream in,
+                                            String encoding) throws IOException {
         Reader inw;
         in = new BufferedInputStream(in);  // add buffering
         if (encoding == null) {
@@ -226,20 +266,8 @@
         return new BufferedReader(inw);  // add buffering
     }
 
-    public static Writer makeWriter(OutputStream out, String encoding) throws IOException {
-        // encoding in DEFAULT, '', UTF8, 8BIT, , or any valid encoding name
-        if (encoding.equals("8BIT")) {
-            encoding = EIGHT_BIT_CHAR_ENCODING;
-        }
-        if (encoding.equals("UTF8")) {
-            encoding = UTF8_ENCODING;
-        }
-        if (encoding.equals("DEFAULT")) {
-            encoding = null;
-        }
-        if (encoding.equals("-")) {
-            encoding = null;
-        }
+    public static Writer makeWriter(OutputStream out,
+                                    String encoding) throws IOException {
         Writer outw;
         if (encoding == null) {
             outw = new OutputStreamWriter(out);
@@ -252,12 +280,9 @@
     public Element result() {
         return cfile;
     }
+
     protected InputStream in;
     protected ByteArrayOutputStream buf = new ByteArrayOutputStream(1024);
-    protected byte cpTag[];
-    protected String cpName[];
-    protected String[] callables;     // varies
-    public static final String REF_PREFIX = "#";
     // input options
     public boolean pretty = false;
     public boolean verbose = false;
@@ -270,7 +295,7 @@
     public boolean keepSizes = false;
 
     public ClassReader() {
-        super.cfile = new Element("ClassFile");
+        cfile = new Element("ClassFile");
     }
 
     public ClassReader(ClassReader options) {
@@ -283,12 +308,7 @@
         verbose = options.verbose;
         keepPath = options.keepPath;
         keepCP = options.keepCP;
-        keepBytes = options.keepBytes;
-        parseBytes = options.parseBytes;
-        resolveRefs = options.resolveRefs;
-        keepSizes = options.keepSizes;
         keepOrder = options.keepOrder;
-        attrTypes = options.attrTypes;
     }
 
     public void copyOptionsFrom(Map<String, String> options) {
@@ -304,274 +324,177 @@
         if (options.containsKey("-keepCP")) {
             keepCP = (options.get("-keepCP") != null);
         }
-        if (options.containsKey("-keepBytes")) {
-            keepBytes = (options.get("-keepBytes") != null);
-        }
-        if (options.containsKey("-parseBytes")) {
-            parseBytes = (options.get("-parseBytes") != null);
-        }
-        if (options.containsKey("-resolveRefs")) {
-            resolveRefs = (options.get("-resolveRefs") != null);
-        }
-        if (options.containsKey("-keepSizes")) {
-            keepSizes = (options.get("-keepSizes") != null);
-        }
         if (options.containsKey("-keepOrder")) {
             keepOrder = (options.get("-keepOrder") != null);
         }
-        if (options.containsKey("-attrDef")) {
-            addAttrTypes(options.get("-attrDef").split(" "));
-        }
-        if (options.get("-jcov") != null) {
-            addJcovAttrTypes();
-        }
     }
 
+    protected String getCpString(int i) {
+        return thePool.get(i);
+    }
+
     public Element readFrom(InputStream in) throws IOException {
-        this.in = in;
-        // read the file header
-        int magic = u4();
-        if (magic != 0xCAFEBABE) {
-            throw new RuntimeException("bad magic number " + Integer.toHexString(magic));
+        try {
+            this.in = in;
+            ClassFile c = ClassFile.read(in);
+            // read the file header
+            if (c.magic != 0xCAFEBABE) {
+                throw new RuntimeException("bad magic number " +
+                        Integer.toHexString(c.magic));
+            }
+            cfile.setAttr("magic", "" + c.magic);
+            int minver = c.minor_version;
+            int majver = c.major_version;
+            cfile.setAttr("minver", "" + minver);
+            cfile.setAttr("majver", "" + majver);
+            readCP(c);
+            readClass(c);
+            return result();
+        } catch (InvalidDescriptor | ConstantPoolException ex) {
+            throw new IOException("Fatal error", ex);
         }
-        cfile.setAttr("magic", "" + magic);
-        int minver = u2();
-        int majver = u2();
-        cfile.setAttr("minver", "" + minver);
-        cfile.setAttr("majver", "" + majver);
-        readCP();
-        readClass();
-        return result();
     }
 
     public Element readFrom(File file) throws IOException {
-        InputStream in = null;
-        try {
-            in = new FileInputStream(file);
-            Element e = readFrom(new BufferedInputStream(in));
+        try (InputStream strm = new FileInputStream(file)) {
+            Element e = readFrom(new BufferedInputStream(strm));
             if (keepPath) {
                 e.setAttr("path", file.toString());
             }
             return e;
-        } finally {
-            if (in != null) {
-                in.close();
-            }
         }
     }
 
-    private void readClass() throws IOException {
+    private void readClass(ClassFile c) throws IOException,
+                                               ConstantPoolException,
+                                               InvalidDescriptor {
         klass = new Element("Class");
         cfile.add(klass);
-        int flags = u2();
-        String thisk = cpRef();
-        String superk = cpRef();
+        String thisk = c.getName();
+
         klass.setAttr("name", thisk);
-        boolean flagsSync = ((flags & Modifier.SYNCHRONIZED) != 0);
-        flags &= ~Modifier.SYNCHRONIZED;
-        String flagString = flagString(flags, klass);
-        if (!flagsSync) {
-            if (flagString.length() > 0) {
-                flagString += " ";
-            }
-            flagString += "!synchronized";
+
+        AccessFlags af = new AccessFlags(c.access_flags.flags);
+        klass.setAttr("flags", flagString(af, klass));
+        if (!"java/lang/Object".equals(thisk)) {
+            klass.setAttr("super", c.getSuperclassName());
+        }
+        for (int i : c.interfaces) {
+            klass.add(new Element("Interface", "name", getCpString(i)));
         }
-        klass.setAttr("flags", flagString);
-        klass.setAttr("super", superk);
-        for (int len = u2(), i = 0; i < len; i++) {
-            String interk = cpRef();
-            klass.add(new Element("Interface", "name", interk));
+        readFields(c, klass);
+        readMethods(c, klass);
+        readAttributesFor(c, c.attributes, klass);
+        klass.trimToSize();
+    }
+
+    private void readFields(ClassFile c, Element klass) throws IOException {
+        int len = c.fields.length;
+        Element fields = new Element(len);
+        for (Field f : c.fields) {
+            Element field = new Element("Field");
+            field.setAttr("name", getCpString(f.name_index));
+            field.setAttr("type", getCpString(f.descriptor.index));
+            field.setAttr("flags", flagString(f.access_flags.flags, field));
+            readAttributesFor(c, f.attributes, field);
+
+            field.trimToSize();
+            fields.add(field);
         }
-        Element fields = readMembers("Field");
+        if (!keepOrder) {
+            fields.sort();
+        }
         klass.addAll(fields);
-        Element methods = readMembers("Method");
+    }
+
+
+    private void readMethods(ClassFile c, Element klass) throws IOException {
+        int len = c.methods.length;
+        Element methods = new Element(len);
+        for (Method m : c.methods) {
+            Element member = new Element("Method");
+            member.setAttr("name", getCpString(m.name_index));
+            member.setAttr("type", getCpString(m.descriptor.index));
+            member.setAttr("flags", flagString(m.access_flags.flags, member));
+            readAttributesFor(c, m.attributes, member);
+
+            member.trimToSize();
+            methods.add(member);
+        }
         if (!keepOrder) {
             methods.sort();
         }
         klass.addAll(methods);
-        readAttributesFor(klass);
-        klass.trimToSize();
-        if (keepSizes) {
-            attachTo(cfile, formatAttrSizes());
-        }
-        if (paddingSize != 0) {
-            cfile.setAttr("padding", "" + paddingSize);
-        }
     }
 
-    private Element readMembers(String kind) throws IOException {
-        int len = u2();
-        Element members = new Element(len);
-        for (int i = 0; i < len; i++) {
-            Element member = new Element(kind);
-            int flags = u2();
-            String name = cpRef();
-            String type = cpRef();
-            member.setAttr("name", name);
-            member.setAttr("type", type);
-            member.setAttr("flags", flagString(flags, member));
-            readAttributesFor(member);
-            member.trimToSize();
-            members.add(member);
+    private AccessFlags.Kind getKind(Element e) {
+        switch(e.getName()) {
+            case "Class":
+                return AccessFlags.Kind.Class;
+            case "InnerClass":
+                return AccessFlags.Kind.InnerClass;
+            case "Field":
+                return AccessFlags.Kind.Field ;
+            case "Method":
+                return AccessFlags.Kind.Method;
+            default: throw new RuntimeException("should not reach here");
         }
-        return members;
     }
 
     protected String flagString(int flags, Element holder) {
-        // Superset of Modifier.toString.
-        int kind = 0;
-        if (holder.getName() == "Field") {
-            kind = 1;
-        }
-        if (holder.getName() == "Method") {
-            kind = 2;
+        return flagString(new AccessFlags(flags), holder);
+    }
+    protected String flagString(AccessFlags af, Element holder) {
+        return flagString(af, holder.getName());
+    }
+    protected String flagString(int flags, String kind) {
+        return flagString(new AccessFlags(flags), kind);
+    }
+    protected String flagString(AccessFlags af, String kind) {
+        Set<String> mods = null;
+        switch (kind) {
+            case "Class":
+                mods = af.getClassFlags();
+                break;
+            case "InnerClass":
+                mods = af.getInnerClassFlags();
+                break;
+            case "Field":
+                mods = af.getFieldFlags();
+                break;
+            case "Method":
+                mods = af.getMethodFlags();
+                break;
+            default:
+                throw new RuntimeException("should not reach here");
         }
-        StringBuffer sb = new StringBuffer();
-        for (int i = 0; flags != 0; i++, flags >>>= 1) {
-            if ((flags & 1) != 0) {
-                if (sb.length() > 0) {
-                    sb.append(' ');
-                }
-                if (i < modifierNames.length) {
-                    String[] names = modifierNames[i];
-                    String name = (kind < names.length) ? names[kind] : null;
-                    for (String name2 : names) {
-                        if (name != null) {
-                            break;
-                        }
-                        name = name2;
-                    }
-                    sb.append(name);
-                } else {
-                    sb.append("#").append(1 << i);
-                }
-            }
+        StringBuilder sb = new StringBuilder();
+        for (String x : mods) {
+            sb.append(x.substring(x.indexOf('_') + 1).toLowerCase()).append(" ");
         }
-        return sb.toString();
+        return sb.toString().trim();
     }
 
-    private void readAttributesFor(Element x) throws IOException {
-        Element prevCurrent;
-        Element y = new Element();
-        if (x.getName() == "Code") {
-            prevCurrent = currentCode;
-            currentCode = x;
-        } else {
-            prevCurrent = currentMember;
-            currentMember = x;
-        }
-        for (int len = u2(), i = 0; i < len; i++) {
-            int ref = u2();
-            String uname = cpName(ref).intern();
-            String refName = uname;
-            if (!resolveRefs) {
-                refName = (REF_PREFIX + ref).intern();
-            }
-            String qname = (x.getName() + "." + uname).intern();
-            String wname = ("*." + uname).intern();
-            String type = attrTypes.get(qname);
-            if (type == null || "".equals(type)) {
-                type = attrTypes.get(wname);
-            }
-            if ("".equals(type)) {
-                type = null;
-            }
-            int size = u4();
-            int[] countVar = attrSizes.get(qname);
-            if (countVar == null) {
-                attrSizes.put(qname, countVar = new int[2]);
-            }
-            countVar[0] += 1;
-            countVar[1] += size;
-            buf.reset();
-            for (int j = 0; j < size; j++) {
-                buf.write(u1());
-            }
-            if (type == null && size == 0) {
-                y.add(new Element(uname)); // <Bridge>, etc.
-            } else if (type == null) {
-                //System.out.println("Warning:  No attribute type description: "+qname);
-                // write cdata attribute
-                Element a = new Element("Attribute",
-                        new String[]{"Name", refName},
-                        buf.toString(EIGHT_BIT_CHAR_ENCODING));
-                a.addContent(getCPDigest());
-                y.add(a);
-            } else if (type.equals("")) {
-                // ignore this attribute...
-            } else {
-                InputStream in0 = in;
-                int fileSize0 = fileSize;
-                ByteArrayInputStream in1 = new ByteArrayInputStream(buf.toByteArray());
-                boolean ok = false;
-                try {
-                    in = in1;
-                    // parse according to type desc.
-                    Element aval;
-                    if (type.equals("<Code>...")) {
-                        // delve into Code attribute
-                        aval = readCode();
-                    } else if (type.equals("<Frame>...")) {
-                        // delve into StackMap attribute
-                        aval = readStackMap(false);
-                    } else if (type.equals("<FrameX>...")) {
-                        // delve into StackMap attribute
-                        aval = readStackMap(true);
-                    } else if (type.startsWith("[")) {
-                        aval = readAttributeCallables(type);
-                    } else {
-                        aval = readAttribute(type);
-                    }
-                    //System.out.println("attachTo 1 "+y+" <- "+aval);
-                    attachTo(y, aval);
-                    if (false
-                            && in1.available() != 0) {
-                        throw new RuntimeException("extra bytes in " + qname + " :" + in1.available());
-                    }
-                    ok = true;
-                } finally {
-                    in = in0;
-                    fileSize = fileSize0;
-                    if (!ok) {
-                        System.out.println("*** Failed to read " + type);
-                    }
-                }
-            }
-        }
-        if (x.getName() == "Code") {
-            currentCode = prevCurrent;
-        } else {
-            currentMember = prevCurrent;
+
+    protected  void readAttributesFor(ClassFile c, Attributes attrs, Element x) {
+        Element container = new Element();
+        AttributeVisitor av = new AttributeVisitor(this, c);
+        for (Attribute a : attrs) {
+            av.visit(a, container);
         }
         if (!keepOrder) {
-            y.sort();
-            y.sortAttrs();
+            container.sort();
         }
-        //System.out.println("attachTo 2 "+x+" <- "+y);
-        attachTo(x, y);
+        x.addAll(container);
     }
-    private int fileSize = 0;
-    private int paddingSize = 0;
-    private HashMap<String, int[]> attrSizes = new HashMap<String, int[]>();
 
-    private Element formatAttrSizes() {
-        Element e = new Element("Sizes");
-        e.setAttr("fileSize", "" + fileSize);
-        for (Map.Entry<String, int[]> ie : attrSizes.entrySet()) {
-            int[] countVar = ie.getValue();
-            e.add(new Element("AttrSize",
-                    "name", ie.getKey().toString(),
-                    "count", "" + countVar[0],
-                    "size", "" + countVar[1]));
-        }
-        return e;
-    }
+    private int fileSize = 0;
+    private HashMap<String, int[]> attrSizes = new HashMap<>();
 
     private void attachTo(Element x, Object aval0) {
         if (aval0 == null) {
             return;
         }
-        //System.out.println("attachTo "+x+" : "+aval0);
         if (!(aval0 instanceof Element)) {
             x.add(aval0);
             return;
@@ -589,7 +512,6 @@
     }
 
     private void attachAttrTo(Element x, String aname, String aval) {
-        //System.out.println("attachAttrTo "+x+" : "+aname+"="+aval);
         String aval0 = x.getAttr(aname);
         if (aval0 != null) {
             aval = aval0 + " " + aval;
@@ -597,407 +519,1003 @@
         x.setAttr(aname, aval);
     }
 
-    private Element readAttributeCallables(String type) throws IOException {
-        assert (callables == null);
-        callables = getBodies(type);
-        Element res = readAttribute(callables[0]);
-        callables = null;
-        return res;
-    }
-
-    private Element readAttribute(String type) throws IOException {
-        //System.out.println("readAttribute "+type);
-        Element aval = new Element();
-        String nextAttrName = null;
-        for (int len = type.length(), next, i = 0; i < len; i = next) {
-            String value;
-            switch (type.charAt(i)) {
-                case '<':
-                    assert (nextAttrName == null);
-                    next = type.indexOf('>', ++i);
-                    String form = type.substring(i, next++);
-                    if (form.indexOf('=') < 0) {
-                        //  elem_placement = '<' elemname '>'
-                        assert (aval.attrSize() == 0);
-                        assert (aval.isAnonymous());
-                        aval.setName(form.intern());
-                    } else {
-                        //  attr_placement = '<' attrname '=' (value)? '>'
-                        int eqPos = form.indexOf('=');
-                        nextAttrName = form.substring(0, eqPos).intern();
-                        if (eqPos != form.length() - 1) {
-                            value = form.substring(eqPos + 1);
-                            attachAttrTo(aval, nextAttrName, value);
-                            nextAttrName = null;
-                        }
-                        // ...else subsequent type parsing will find the attr value
-                        // and add it as "nextAttrName".
-                    }
-                    continue;
-                case '(':
-                    next = type.indexOf(')', ++i);
-                    int callee = Integer.parseInt(type.substring(i, next++));
-                    attachTo(aval, readAttribute(callables[callee]));
-                    continue;
-                case 'N': // replication = 'N' int '[' type ... ']'
-                {
-                    int count = getInt(type.charAt(i + 1), false);
-                    assert (count >= 0);
-                    next = i + 2;
-                    String type1 = getBody(type, next);
-                    next += type1.length() + 2;  // skip body and brackets
-                    for (int j = 0; j < count; j++) {
-                        attachTo(aval, readAttribute(type1));
-                    }
-                }
-                continue;
-                case 'T': // union = 'T' any_int union_case* '(' ')' '[' body ']'
-                    int tagValue;
-                    if (type.charAt(++i) == 'S') {
-                        tagValue = getInt(type.charAt(++i), true);
-                    } else {
-                        tagValue = getInt(type.charAt(i), false);
-                    }
-                    attachAttrTo(aval, "tag", "" + tagValue);  // always named "tag"
-                    ++i;  // skip the int type char
-                    // union_case = '(' uc_tag (',' uc_tag)* ')' '[' body ']'
-                    // uc_tag = ('-')? digit+
-                    for (boolean foundCase = false;; i = next) {
-                        assert (type.charAt(i) == '(');
-                        next = type.indexOf(')', ++i);
-                        assert (next >= i);
-                        if (type.charAt(next - 1) == '\\'
-                                && type.charAt(next - 2) != '\\') // Skip an escaped paren.
-                        {
-                            next = type.indexOf(')', next + 1);
-                        }
-                        String caseStr = type.substring(i, next++);
-                        String type1 = getBody(type, next);
-                        next += type1.length() + 2;  // skip body and brackets
-                        boolean lastCase = (caseStr.length() == 0);
-                        if (!foundCase
-                                && (lastCase || matchTag(tagValue, caseStr))) {
-                            foundCase = true;
-                            // Execute this body.
-                            attachTo(aval, readAttribute(type1));
-                        }
-                        if (lastCase) {
-                            break;
-                        }
-                    }
-                    continue;
-                case 'B':
-                case 'H':
-                case 'I': // int = oneof "BHI"
-                    next = i + 1;
-                    value = "" + getInt(type.charAt(i), false);
-                    break;
-                case 'K':
-                    assert ("IJFDLQ".indexOf(type.charAt(i + 1)) >= 0);
-                    assert (type.charAt(i + 2) == 'H');  // only H works for now
-                    next = i + 3;
-                    value = cpRef();
-                    break;
-                case 'R':
-                    assert ("CSDFMIU?".indexOf(type.charAt(i + 1)) >= 0);
-                    assert (type.charAt(i + 2) == 'H');  // only H works for now
-                    next = i + 3;
-                    value = cpRef();
-                    break;
-                case 'P':  // bci = 'P' int
-                    next = i + 2;
-                    value = "" + getInt(type.charAt(i + 1), false);
-                    break;
-                case 'S':  // signed_int = 'S' int
-                    next = i + 2;
-                    value = "" + getInt(type.charAt(i + 1), true);
-                    break;
-                case 'F':
-                    next = i + 2;
-                    value = flagString(getInt(type.charAt(i + 1), false), currentMember);
-                    break;
-                default:
-                    throw new RuntimeException("bad attr format '" + type.charAt(i) + "': " + type);
-            }
-            // store the value
-            if (nextAttrName != null) {
-                attachAttrTo(aval, nextAttrName, value);
-                nextAttrName = null;
-            } else {
-                attachTo(aval, value);
-            }
-        }
-        //System.out.println("readAttribute => "+aval);
-        assert (nextAttrName == null);
-        return aval;
-    }
-
-    private int getInt(char ch, boolean signed) throws IOException {
-        if (signed) {
-            switch (ch) {
-                case 'B':
-                    return (byte) u1();
-                case 'H':
-                    return (short) u2();
-                case 'I':
-                    return (int) u4();
-            }
-        } else {
-            switch (ch) {
-                case 'B':
-                    return u1();
-                case 'H':
-                    return u2();
-                case 'I':
-                    return u4();
+    private void readCP(ClassFile c) throws IOException {
+        cpool = new Element("ConstantPool", c.constant_pool.size());
+        ConstantPoolVisitor cpv = new ConstantPoolVisitor(cpool, c,
+                c.constant_pool.size());
+        for (int i = 1 ; i < c.constant_pool.size() ; i++) {
+            try {
+                cpv.visit(c.constant_pool.get(i), i);
+            } catch (InvalidIndex ex) {
+                // can happen periodically when accessing doubles etc. ignore it
+                // ex.printStackTrace();
             }
         }
-        assert ("BHIJ".indexOf(ch) >= 0);
-        return 0;
-    }
-
-    private Element readCode() throws IOException {
-        int stack = u2();
-        int local = u2();
-        int length = u4();
-        StringBuilder sb = new StringBuilder(length);
-        for (int i = 0; i < length; i++) {
-            sb.append((char) u1());
-        }
-        String bytecodes = sb.toString();
-        Element e = new Element("Code",
-                "stack", "" + stack,
-                "local", "" + local);
-        Element bytes = new Element("Bytes", (String[]) null, bytecodes);
-        if (keepBytes) {
-            e.add(bytes);
-        }
-        if (parseBytes) {
-            e.add(parseByteCodes(bytecodes));
-        }
-        for (int len = u2(), i = 0; i < len; i++) {
-            int start = u2();
-            int end = u2();
-            int catsh = u2();
-            String clasz = cpRef();
-            e.add(new Element("Handler",
-                    "start", "" + start,
-                    "end", "" + end,
-                    "catch", "" + catsh,
-                    "class", clasz));
-        }
-        readAttributesFor(e);
-        e.trimToSize();
-        return e;
-    }
-
-    private Element parseByteCodes(String bytecodes) {
-        Element e = InstructionSyntax.parse(bytecodes);
-        for (Element ins : e.elements()) {
-            Number ref = ins.getAttrNumber("ref");
-            if (ref != null && resolveRefs) {
-                int id = ref.intValue();
-                String val = cpName(id);
-                if (ins.getName().startsWith("ldc")) {
-                    // Yuck:  Arb. string cannot be an XML attribute.
-                    ins.add(val);
-                    val = "";
-                    byte tag = (id >= 0 && id < cpTag.length) ? cpTag[id] : 0;
-                    if (tag != 0) {
-                        ins.setAttrLong("tag", tag);
-                    }
-                }
-                if (ins.getName() == "invokeinterface"
-                        && computeInterfaceNum(val) == ins.getAttrLong("num")) {
-                    ins.setAttr("num", null);  // garbage bytes
-                }
-                ins.setAttr("ref", null);
-                ins.setAttr("val", val);
-            }
-        }
-        return e;
-    }
-
-    private Element readStackMap(boolean hasXOption) throws IOException {
-        Element result = new Element();
-        Element bytes = currentCode.findElement("Bytes");
-        assert (bytes != null && bytes.size() == 1);
-        int byteLength = ((String) bytes.get(0)).length();
-        boolean uoffsetIsU4 = (byteLength >= (1 << 16));
-        boolean ulocalvarIsU4 = currentCode.getAttrLong("local") >= (1 << 16);
-        boolean ustackIsU4 = currentCode.getAttrLong("stack") >= (1 << 16);
-        if (hasXOption || uoffsetIsU4 || ulocalvarIsU4 || ustackIsU4) {
-            Element flags = new Element("StackMapFlags");
-            if (hasXOption) {
-                flags.setAttr("hasXOption", "true");
-            }
-            if (uoffsetIsU4) {
-                flags.setAttr("uoffsetIsU4", "true");
-            }
-            if (ulocalvarIsU4) {
-                flags.setAttr("ulocalvarIsU4", "true");
-            }
-            if (ustackIsU4) {
-                flags.setAttr("ustackIsU4", "true");
-            }
-            currentCode.add(flags);
-        }
-        int frame_count = (uoffsetIsU4 ? u4() : u2());
-        for (int i = 0; i < frame_count; i++) {
-            int bci = (uoffsetIsU4 ? u4() : u2());
-            int flags = (hasXOption ? u1() : 0);
-            Element frame = new Element("Frame");
-            result.add(frame);
-            if (flags != 0) {
-                frame.setAttr("flags", "" + flags);
+        thePool = cpv.getPoolList();
+        if (verbose) {
+            for (int i = 0; i < thePool.size(); i++) {
+                System.out.println("[" + i + "]: " + thePool.get(i));
             }
-            frame.setAttr("bci", "" + bci);
-            // Scan local and stack types in this frame:
-            final int LOCALS = 0, STACK = 1;
-            for (int j = LOCALS; j <= STACK; j++) {
-                int typeSize;
-                if (j == LOCALS) {
-                    typeSize = (ulocalvarIsU4 ? u4() : u2());
-                } else { // STACK
-                    typeSize = (ustackIsU4 ? u4() : u2());
-                }
-                Element types = new Element(j == LOCALS ? "Local" : "Stack");
-                for (int k = 0; k < typeSize; k++) {
-                    int tag = u1();
-                    Element type = new Element(itemTagName(tag));
-                    types.add(type);
-                    switch (tag) {
-                        case ITEM_Object:
-                            type.setAttr("class", cpRef());
-                            break;
-                        case ITEM_Uninitialized:
-                        case ITEM_ReturnAddress:
-                            type.setAttr("bci", "" + (uoffsetIsU4 ? u4() : u2()));
-                            break;
-                    }
-                }
-                if (types.size() > 0) {
-                    frame.add(types);
-                }
-            }
-        }
-        return result;
-    }
-
-    private void readCP() throws IOException {
-        int cpLen = u2();
-        cpTag = new byte[cpLen];
-        cpName = new String[cpLen];
-        int cpTem[][] = new int[cpLen][];
-        for (int i = 1; i < cpLen; i++) {
-            cpTag[i] = (byte) u1();
-            switch (cpTag[i]) {
-                case CONSTANT_Utf8:
-                    buf.reset();
-                    for (int len = u2(), j = 0; j < len; j++) {
-                        buf.write(u1());
-                    }
-                    cpName[i] = buf.toString(UTF8_ENCODING);
-                    break;
-                case CONSTANT_Integer:
-                    cpName[i] = String.valueOf((int) u4());
-                    break;
-                case CONSTANT_Float:
-                    cpName[i] = String.valueOf(Float.intBitsToFloat(u4()));
-                    break;
-                case CONSTANT_Long:
-                    cpName[i] = String.valueOf(u8());
-                    i += 1;
-                    break;
-                case CONSTANT_Double:
-                    cpName[i] = String.valueOf(Double.longBitsToDouble(u8()));
-                    i += 1;
-                    break;
-                case CONSTANT_Class:
-                case CONSTANT_String:
-                    cpTem[i] = new int[]{u2()};
-                    break;
-                case CONSTANT_Fieldref:
-                case CONSTANT_Methodref:
-                case CONSTANT_InterfaceMethodref:
-                case CONSTANT_NameAndType:
-                    cpTem[i] = new int[]{u2(), u2()};
-                    break;
-            }
-        }
-        for (int i = 1; i < cpLen; i++) {
-            switch (cpTag[i]) {
-                case CONSTANT_Class:
-                case CONSTANT_String:
-                    cpName[i] = cpName[cpTem[i][0]];
-                    break;
-                case CONSTANT_NameAndType:
-                    cpName[i] = cpName[cpTem[i][0]] + " " + cpName[cpTem[i][1]];
-                    break;
-            }
-        }
-        // do fieldref et al after nameandtype are all resolved
-        for (int i = 1; i < cpLen; i++) {
-            switch (cpTag[i]) {
-                case CONSTANT_Fieldref:
-                case CONSTANT_Methodref:
-                case CONSTANT_InterfaceMethodref:
-                    cpName[i] = cpName[cpTem[i][0]] + " " + cpName[cpTem[i][1]];
-                    break;
-            }
-        }
-        cpool = new Element("ConstantPool", cpName.length);
-        for (int i = 0; i < cpName.length; i++) {
-            if (cpName[i] == null) {
-                continue;
-            }
-            cpool.add(new Element(cpTagName(cpTag[i]),
-                    new String[]{"id", "" + i},
-                    cpName[i]));
         }
         if (keepCP) {
             cfile.add(cpool);
         }
     }
+}
 
-    private String cpRef() throws IOException {
-        int ref = u2();
-        if (resolveRefs) {
-            return cpName(ref);
-        } else {
-            return REF_PREFIX + ref;
+class ConstantPoolVisitor implements ConstantPool.Visitor<String, Integer> {
+    final List<String> slist;
+    final Element xpool;
+    final ClassFile cf;
+    final ConstantPool cfpool;
+    final List<String> bsmlist;
+
+
+    public ConstantPoolVisitor(Element xpool, ClassFile cf, int size) {
+        slist = new ArrayList<>(size);
+        for (int i = 0 ; i < size; i++) {
+            slist.add(null);
+        }
+        this.xpool = xpool;
+        this.cf = cf;
+        this.cfpool = cf.constant_pool;
+        bsmlist = readBSM();
+    }
+
+    public List<String> getPoolList() {
+        return Collections.unmodifiableList(slist);
+    }
+
+    public List<String> getBSMList() {
+        return Collections.unmodifiableList(bsmlist);
+    }
+
+    public String visit(CPInfo c, int index) {
+        return c.accept(this, index);
+    }
+
+    private List<String> readBSM() {
+        BootstrapMethods_attribute bsmAttr =
+                (BootstrapMethods_attribute) cf.getAttribute(Attribute.BootstrapMethods);
+        if (bsmAttr != null) {
+            List<String> out =
+                    new ArrayList<>(bsmAttr.bootstrap_method_specifiers.length);
+            for (BootstrapMethods_attribute.BootstrapMethodSpecifier bsms :
+                    bsmAttr.bootstrap_method_specifiers) {
+                int index = bsms.bootstrap_method_ref;
+                try {
+                    String value = slist.get(index);
+                    String bsmStr = value;
+                    if (value == null) {
+                        value = visit(cfpool.get(index), index);
+                        slist.set(index, value);
+                    }
+                    bsmStr = value;
+                    for (int idx : bsms.bootstrap_arguments) {
+                        value = slist.get(idx);
+                        if (value == null) {
+                            value = visit(cfpool.get(idx), idx);
+                            slist.set(idx, value);
+                        }
+                        bsmStr = bsmStr.concat("," + value);
+                    }
+                    out.add(bsmStr);
+                } catch (InvalidIndex ex) {
+                    ex.printStackTrace();
+                }
+            }
+            return out;
         }
+        return new ArrayList<>(0);
+    }
+
+    @Override
+    public String visitClass(CONSTANT_Class_info c, Integer p) {
+        String value = slist.get(p);
+        if (value == null) {
+            try {
+                value = visit(cfpool.get(c.name_index), c.name_index);
+                slist.set(p, value);
+                xpool.add(new Element("CONSTANT_Class",
+                        new String[]{"id", p.toString()},
+                        value));
+            } catch (ConstantPoolException ex) {
+                ex.printStackTrace();
+            }
+        }
+        return value;
+    }
+
+    @Override
+    public String visitDouble(CONSTANT_Double_info c, Integer p) {
+        String value = slist.get(p);
+        if (value == null) {
+            value = Double.toString(c.value);
+            slist.set(p, value);
+            xpool.add(new Element("CONSTANT_Double",
+                      new String[]{"id", p.toString()},
+                      value));
+        }
+        return value;
+    }
+
+    @Override
+    public String visitFieldref(CONSTANT_Fieldref_info c, Integer p) {
+    String value = slist.get(p);
+        if (value == null) {
+            try {
+                value = visit(cfpool.get(c.class_index), c.class_index);
+                value = value.concat(" " + visit(cfpool.get(c.name_and_type_index),
+                                     c.name_and_type_index));
+                slist.set(p, value);
+                xpool.add(new Element("CONSTANT_Fieldref",
+                          new String[]{"id", p.toString()},
+                          value));
+            } catch (ConstantPoolException ex) {
+                ex.printStackTrace();
+            }
+        }
+        return value;
+    }
+
+    @Override
+    public String visitFloat(CONSTANT_Float_info c, Integer p) {
+        String value = slist.get(p);
+        if (value == null) {
+            value = Float.toString(c.value);
+            slist.set(p, value);
+            xpool.add(new Element("CONSTANT_Float",
+                      new String[]{"id", p.toString()},
+                      value));
+        }
+        return value;
+    }
+
+    @Override
+    public String visitInteger(CONSTANT_Integer_info cnstnt, Integer p) {
+        String value = slist.get(p);
+        if (value == null) {
+            value = Integer.toString(cnstnt.value);
+            slist.set(p, value);
+            xpool.add(new Element("CONSTANT_Integer",
+                      new String[]{"id", p.toString()},
+                      value));
+        }
+        return value;
     }
 
-    private String cpName(int id) {
-        if (id >= 0 && id < cpName.length) {
-            return cpName[id];
-        } else {
-            return "[CP#" + Integer.toHexString(id) + "]";
+    @Override
+    public String visitInterfaceMethodref(CONSTANT_InterfaceMethodref_info c,
+                                          Integer p) {
+        String value = slist.get(p);
+        if (value == null) {
+            try {
+                value = visit(cfpool.get(c.class_index), c.class_index);
+                value = value.concat(" " +
+                                     visit(cfpool.get(c.name_and_type_index),
+                                     c.name_and_type_index));
+                slist.set(p, value);
+                xpool.add(new Element("CONSTANT_InterfaceMethodref",
+                          new String[]{"id", p.toString()},
+                          value));
+
+            } catch (ConstantPoolException ex) {
+                ex.printStackTrace();
+            }
+        }
+        return value;
+    }
+
+    @Override
+    public String visitInvokeDynamic(CONSTANT_InvokeDynamic_info c, Integer p) {
+        String value = slist.get(p);
+        if (value == null) {
+            try {
+                value = bsmlist.get(c.bootstrap_method_attr_index) + " "
+                        + visit(cfpool.get(c.name_and_type_index), c.name_and_type_index);
+                slist.set(p, value);
+                xpool.add(new Element("CONSTANT_InvokeDynamic",
+                          new String[]{"id", p.toString()},
+                          value));
+
+            } catch (ConstantPoolException ex) {
+                ex.printStackTrace();
+            }
+        }
+        return value;
+    }
+
+    @Override
+    public String visitLong(CONSTANT_Long_info c, Integer p) {
+        String value = slist.get(p);
+        if (value == null) {
+            value = Long.toString(c.value);
+            slist.set(p, value);
+            xpool.add(new Element("CONSTANT_Long",
+                      new String[]{"id", p.toString()},
+                      value));
+        }
+        return value;
+    }
+
+    @Override
+    public String visitNameAndType(CONSTANT_NameAndType_info c, Integer p) {
+        String value = slist.get(p);
+        if (value == null) {
+            try {
+                value = visit(cfpool.get(c.name_index), c.name_index);
+                value = value.concat(" " +
+                        visit(cfpool.get(c.type_index), c.type_index));
+                slist.set(p, value);
+                xpool.add(new Element("CONSTANT_NameAndType",
+                          new String[]{"id", p.toString()},
+                          value));
+            } catch (InvalidIndex ex) {
+                ex.printStackTrace();
+            }
+        }
+        return value;
+    }
+
+    @Override
+    public String visitMethodref(CONSTANT_Methodref_info c, Integer p) {
+        String value = slist.get(p);
+        if (value == null) {
+            try {
+                value = visit(cfpool.get(c.class_index), c.class_index);
+                value = value.concat(" " +
+                                     visit(cfpool.get(c.name_and_type_index),
+                                     c.name_and_type_index));
+                slist.set(p, value);
+                xpool.add(new Element("CONSTANT_Methodref",
+                          new String[]{"id", p.toString()},
+                          value));
+
+            } catch (ConstantPoolException ex) {
+                ex.printStackTrace();
+            }
+        }
+        return value;
+    }
+
+    @Override
+    public String visitMethodHandle(CONSTANT_MethodHandle_info c, Integer p) {
+    String value = slist.get(p);
+        if (value == null) {
+            try {
+                value = c.reference_kind.name();
+                value = value.concat(" "
+                        + visit(cfpool.get(c.reference_index), c.reference_index));
+                slist.set(p, value);
+                xpool.add(new Element("CONSTANT_MethodHandle",
+                          new String[]{"id", p.toString()},
+                          value));
+
+            } catch (ConstantPoolException ex) {
+                ex.printStackTrace();
+            }
+        }
+        return value;
+    }
+
+    @Override
+    public String visitMethodType(CONSTANT_MethodType_info c, Integer p) {
+        String value = slist.get(p);
+        if (value == null) {
+            try {
+                value = visit(cfpool.get(c.descriptor_index), c.descriptor_index);
+                slist.set(p, value);
+                xpool.add(new Element("CONSTANT_MethodType",
+                          new String[]{"id", p.toString()},
+                          value));
+            } catch (ConstantPoolException ex) {
+                ex.printStackTrace();
+            }
+        }
+        return value;
+    }
+
+    @Override
+    public String visitString(CONSTANT_String_info c, Integer p) {
+        try {
+
+            String value = slist.get(p);
+            if (value == null) {
+                value = c.getString();
+                slist.set(p, value);
+                xpool.add(new Element("CONSTANT_String",
+                          new String[]{"id", p.toString()},
+                          value));
+            }
+            return value;
+        } catch (ConstantPoolException ex) {
+            throw new RuntimeException("Fatal error", ex);
         }
     }
 
-    private long u8() throws IOException {
-        return ((long) u4() << 32) + (((long) u4() << 32) >>> 32);
-    }
-
-    private int u4() throws IOException {
-        return (u2() << 16) + u2();
-    }
+    @Override
+    public String  visitUtf8(CONSTANT_Utf8_info cnstnt, Integer p) {
+        String value = slist.get(p);
+        if (value == null) {
+            value = cnstnt.value;
+            slist.set(p, value);
+            xpool.add(new Element("CONSTANT_Utf8",
+                      new String[]{"id", p.toString()},
+                      value));
+        }
+        return value;
 
-    private int u2() throws IOException {
-        return (u1() << 8) + u1();
-    }
-
-    private int u1() throws IOException {
-        int x = in.read();
-        if (x < 0) {
-            paddingSize++;
-            return 0;  // error recovery
-        }
-        fileSize++;
-        assert (x == (x & 0xFF));
-        return x;
     }
 }
 
+class AttributeVisitor implements Attribute.Visitor<Element, Element> {
+    final ClassFile cf;
+    final ClassReader x;
+    final AnnotationsElementVisitor aev;
+    final InstructionVisitor iv;
+
+    public AttributeVisitor(ClassReader x, ClassFile cf) {
+        this.x = x;
+        this.cf = cf;
+        iv =  new InstructionVisitor(x, cf);
+        aev = new AnnotationsElementVisitor(x, cf);
+    }
+
+    public void visit(Attribute a, Element parent) {
+        a.accept(this, parent);
+    }
+
+    @Override
+    public Element visitBootstrapMethods(BootstrapMethods_attribute bm, Element p) {
+        Element e = new Element(x.getCpString(bm.attribute_name_index));
+        for (BootstrapMethods_attribute.BootstrapMethodSpecifier bsm : bm.bootstrap_method_specifiers) {
+            Element be = new Element("BootstrapMethodSpecifier");
+            be.setAttr("ref", x.getCpString(bsm.bootstrap_method_ref));
+            if (bsm.bootstrap_arguments.length > 0) {
+                Element bme = new Element("MethodArguments");
+                for (int index : bsm.bootstrap_arguments) {
+                    bme.add(x.getCpString(index));
+                }
+                bme.trimToSize();
+                be.add(bme);
+            }
+            be.trimToSize();
+            e.add(be);
+        }
+        e.trimToSize();
+        if (!x.keepOrder) {
+            e.sort();
+        }
+        p.add(e);
+        return null;
+    }
+
+    @Override
+    public Element visitDefault(DefaultAttribute da, Element p) {
+        Element e = new Element(x.getCpString(da.attribute_name_index));
+        StringBuilder sb = new StringBuilder();
+        for (byte x : da.info) {
+            sb.append("0x").append(Integer.toHexString(x)).append(" ");
+        }
+        e.setAttr("bytes", sb.toString().trim());
+        e.trimToSize();
+        p.add(e);
+        return null;
+    }
+
+    @Override
+    public Element visitAnnotationDefault(AnnotationDefault_attribute ad, Element p) {
+        Element e = new Element(x.getCpString(ad.attribute_name_index));
+        e.setAttr("tag", "" + ad.default_value.tag);
+        Element child = aev.visit(ad.default_value, e);
+        if (child != null) {
+            e.add(child);
+        }
+        e.trimToSize();
+        p.add(e);
+        return null;
+    }
+
+    @Override
+    public Element visitCharacterRangeTable(CharacterRangeTable_attribute crt,
+                                            Element p) {
+        Element e = new Element(x.getCpString(crt.attribute_name_index));
+        for (CharacterRangeTable_attribute.Entry ce : crt.character_range_table) {
+            e.setAttr("start_pc", "" + ce.start_pc);
+            e.setAttr("end_pc", "" + ce.end_pc);
+            e.setAttr("range_start", "" + ce.character_range_start);
+            e.setAttr("range_end", "" + ce.character_range_end);
+            e.setAttr("flags", x.flagString(ce.flags, "Method"));
+        }
+        e.trimToSize();
+        p.add(e);
+        return null;
+    }
+
+    private Element instructions(Element code, Code_attribute c) {
+        Element ielement = new Element("Instructions");
+        for (Instruction ins : c.getInstructions()) {
+            ielement.add(iv.visit(ins));
+        }
+        ielement.trimToSize();
+        return ielement;
+    }
+
+    @Override
+    public Element visitCode(Code_attribute c, Element p) {
+        Element e = null;
+
+        e = new Element(x.getCpString(c.attribute_name_index),
+                "stack", "" + c.max_stack,
+                "local", "" + c.max_locals);
+
+        e.add(instructions(e, c));
+
+        for (Code_attribute.Exception_data edata : c.exception_table) {
+            e.add(new Element("Handler",
+                    "start", "" + edata.start_pc,
+                    "end", "" + edata.end_pc,
+                    "catch", "" + edata.handler_pc,
+                    "class", x.getCpString(edata.catch_type)));
+
+        }
+        this.x.readAttributesFor(cf, c.attributes, e);
+        e.trimToSize();
+        p.add(e);
+        return null;
+    }
+
+    @Override
+    public Element visitCompilationID(CompilationID_attribute cid, Element p) {
+        Element e = new Element(x.getCpString(cid.attribute_name_index),
+                x.getCpString(cid.compilationID_index));
+        p.add(e);
+        return null;
+    }
+
+    @Override
+    public Element visitConstantValue(ConstantValue_attribute cv, Element p) {
+        Element e = new Element(x.getCpString(cv.attribute_name_index));
+        e.add(x.getCpString(cv.constantvalue_index));
+        p.add(e);
+        return null;
+    }
+
+    @Override
+    public Element visitDeprecated(Deprecated_attribute d, Element p) {
+        Element e = new Element(x.getCpString(d.attribute_name_index));
+        p.add(e);
+        return null;
+    }
+
+    @Override
+    public Element visitEnclosingMethod(EnclosingMethod_attribute em, Element p) {
+        Element e = new Element(x.getCpString(em.attribute_name_index));
+        e.setAttr("class", x.getCpString(em.class_index));
+        e.setAttr("desc", x.getCpString(em.method_index));
+        e.trimToSize();
+        p.add(e);
+        return null;
+    }
+
+    @Override
+    public Element visitExceptions(Exceptions_attribute e, Element p) {
+        Element ee = new Element(x.getCpString(e.attribute_name_index));
+        for (int idx : e.exception_index_table) {
+            Element n = new Element("Item");
+            n.setAttr("class", x.getCpString(idx));
+            ee.add(n);
+        }
+        ee.trimToSize();
+        p.add(ee);
+        return null;
+    }
+
+    @Override
+    public Element visitInnerClasses(InnerClasses_attribute ic, Element p) {
+        for (Info info : ic.classes) {
+            Element e = new Element(x.getCpString(ic.attribute_name_index));
+            e.setAttr("class", x.getCpString(info.inner_class_info_index));
+            e.setAttr("outer", x.getCpString(info.outer_class_info_index));
+            e.setAttr("name", x.getCpString(info.inner_name_index));
+            e.setAttr("flags", x.flagString(info.inner_class_access_flags,
+                    "InnerClass"));
+            e.trimToSize();
+            p.add(e);
+        }
+        return null;
+    }
+
+    @Override
+    public Element visitLineNumberTable(LineNumberTable_attribute lnt, Element p) {
+        String name = x.getCpString(lnt.attribute_name_index);
+        for (LineNumberTable_attribute.Entry e : lnt.line_number_table) {
+            Element l = new Element(name);
+            l.setAttr("bci", "" + e.start_pc);
+            l.setAttr("line", "" + e.line_number);
+            l.trimToSize();
+            p.add(l);
+        }
+        return null; // already added to parent
+    }
+
+    @Override
+    public Element visitLocalVariableTable(LocalVariableTable_attribute lvt,
+                                                Element p) {
+        String name = x.getCpString(lvt.attribute_name_index);
+        for (LocalVariableTable_attribute.Entry e : lvt.local_variable_table) {
+            Element l = new Element(name);
+            l.setAttr("bci", "" + e.start_pc);
+            l.setAttr("span", "" + e.length);
+            l.setAttr("name", x.getCpString(e.name_index));
+            l.setAttr("type", x.getCpString(e.descriptor_index));
+            l.setAttr("slot", "" + e.index);
+            l.trimToSize();
+            p.add(l);
+        }
+        return null; // already added to parent
+    }
+
+    @Override
+    public Element visitLocalVariableTypeTable(LocalVariableTypeTable_attribute lvtt,
+                                                    Element p) {
+        String name = x.getCpString(lvtt.attribute_name_index);
+        for (LocalVariableTypeTable_attribute.Entry e : lvtt.local_variable_table) {
+            Element l = new Element(name);
+            l.setAttr("bci", "" + e.start_pc);
+            l.setAttr("span", "" + e.length);
+            l.setAttr("name", x.getCpString(e.name_index));
+            l.setAttr("type", x.getCpString(e.signature_index));
+            l.setAttr("slot", "" + e.index);
+            l.trimToSize();
+            p.add(l);
+        }
+        return null; // already added to parent
+    }
+
+    private void parseAnnotations(Annotation[] ra, Element p) {
+         for (Annotation anno : ra) {
+            Element ea = new Element("Member");
+            ea.setAttr("name", "" + x.getCpString(anno.type_index));
+            for (Annotation.element_value_pair evp : anno.element_value_pairs) {
+                Element evpe = new Element("Element");
+                evpe.setAttr("tag", "" + evp.value.tag);
+                evpe.setAttr("value", x.getCpString(evp.element_name_index));
+                Element child = aev.visit(evp.value, evpe);
+                if (child != null) {
+                    evpe.add(child);
+                }
+                ea.add(evpe);
+            }
+            ea.trimToSize();
+            p.add(ea);
+        }
+    }
+
+    @Override
+    public Element visitRuntimeVisibleAnnotations(RuntimeVisibleAnnotations_attribute rva,
+                                                  Element p) {
+        Element e = new Element(x.getCpString(rva.attribute_name_index));
+        parseAnnotations(rva.annotations, e);
+        e.trimToSize();
+        p.add(e);
+        return null;
+    }
+
+    @Override
+    public Element visitRuntimeInvisibleAnnotations(RuntimeInvisibleAnnotations_attribute ria,
+                                                    Element p) {
+        Element e = new Element(x.getCpString(ria.attribute_name_index));
+        parseAnnotations(ria.annotations, e);
+        e.trimToSize();
+        p.add(e);
+        return null;
+    }
+
+    @Override
+    public Element visitRuntimeVisibleParameterAnnotations(RuntimeVisibleParameterAnnotations_attribute rvpa,
+                                                           Element p) {
+        Element e = new Element(x.getCpString(rvpa.attribute_name_index));
+        for (Annotation[] pa : rvpa.parameter_annotations) {
+           parseAnnotations(pa, e);
+        }
+        p.add(e);
+        return null;
+    }
+
+    @Override
+    public Element visitRuntimeInvisibleParameterAnnotations(RuntimeInvisibleParameterAnnotations_attribute ripa,
+                                                             Element p) {
+        Element e = new Element(x.getCpString(ripa.attribute_name_index));
+        for (Annotation[] pa : ripa.parameter_annotations) {
+            parseAnnotations(pa, e);
+        }
+        p.add(e);
+        return null;
+    }
+
+    @Override
+    public Element visitSignature(Signature_attribute s, Element p) {
+        String aname = x.getCpString(s.attribute_name_index);
+        String sname = x.getCpString(s.signature_index);
+        Element se = new Element(aname);
+        se.add(sname);
+        se.trimToSize();
+        p.add(se);
+        return null;
+    }
+
+    @Override
+    public Element visitSourceDebugExtension(SourceDebugExtension_attribute sde,
+                                                Element p) {
+        String aname = x.getCpString(sde.attribute_name_index);
+        Element se = new Element(aname);
+        se.setAttr("val", sde.getValue());
+        se.trimToSize();
+        p.add(se);
+        return null;
+    }
+
+    @Override
+    public Element visitSourceFile(SourceFile_attribute sf, Element p) {
+        String aname = x.getCpString(sf.attribute_name_index);
+        String sname = x.getCpString(sf.sourcefile_index);
+        Element se = new Element(aname);
+        se.add(sname);
+        se.trimToSize();
+        p.add(se);
+        return null;
+    }
+
+    @Override
+    public Element visitSourceID(SourceID_attribute sid, Element p) {
+        Element e = new Element(x.getCpString(sid.attribute_name_index));
+        e.add(x.getCpString(sid.sourceID_index));
+        e.trimToSize();
+        p.add(e);
+        return null;
+    }
+
+    @Override
+    public Element visitStackMap(StackMap_attribute sm, Element p) {
+        throw new UnsupportedOperationException("Not supported yet.");
+    }
+
+    @Override
+    public Element visitStackMapTable(StackMapTable_attribute smt, Element p) {
+        Element stackmap = new Element(x.getCpString(smt.attribute_name_index));
+        for (StackMapTable_attribute.stack_map_frame f : smt.entries) {
+           StackMapVisitor smv = new StackMapVisitor(x, cf, stackmap);
+           stackmap.add(smv.visit(f));
+        }
+        stackmap.trimToSize();
+        p.add(stackmap);
+        return null;
+    }
+
+    @Override
+    public Element visitSynthetic(Synthetic_attribute s, Element p) {
+        Element e = new Element(x.getCpString(s.attribute_name_index));
+        e.trimToSize();
+        p.add(e);
+        return null;
+    }
+}
+
+class StackMapVisitor implements StackMapTable_attribute.stack_map_frame.Visitor<Element, Void> {
+
+    final ClassFile cf;
+    final ClassReader x;
+    final Element parent;
+
+    public StackMapVisitor(ClassReader x, ClassFile cf, Element parent) {
+        this.x = x;
+        this.cf = cf;
+        this.parent = parent;
+    }
+
+    public Element visit(StackMapTable_attribute.stack_map_frame frame) {
+        return frame.accept(this, null);
+    }
+
+    @Override
+    public Element visit_same_frame(same_frame sm_frm, Void p) {
+        Element e = new Element("SameFrame");
+        e.setAttr("tag", "" + sm_frm.frame_type);
+        return e;
+    }
+
+    @Override
+    public Element visit_same_locals_1_stack_item_frame(same_locals_1_stack_item_frame s, Void p) {
+        Element e = new Element("SameLocals1StackItemFrame");
+        e.setAttr("tag", "" + s.frame_type);
+        e.addAll(getVerificationTypeInfo("Stack", s.stack));
+        e.trimToSize();
+        return e;
+    }
+
+    @Override
+    public Element visit_same_locals_1_stack_item_frame_extended(same_locals_1_stack_item_frame_extended s, Void p) {
+        Element e = new Element("SameLocals1StackItemFrameExtended");
+        e.setAttr("tag", "" + s.frame_type);
+        e.addAll(getVerificationTypeInfo("Stack", s.stack));
+        e.trimToSize();
+        return e;
+    }
+
+    @Override
+    public Element visit_chop_frame(chop_frame c, Void p) {
+        Element e = new Element("Chop" + (251 - c.frame_type));
+        e.setAttr("tag", "" + c.frame_type);
+        e.setAttr("offset", "" + c.offset_delta);
+        return e;
+    }
+
+    @Override
+    public Element visit_same_frame_extended(same_frame_extended s, Void p) {
+        Element e = new Element("SameFrameExtended");
+        e.setAttr("tag", "" + s.frame_type);
+        e.setAttr("offset", "" + s.offset_delta);
+        return e;
+    }
+
+    @Override
+    public Element visit_append_frame(append_frame a, Void p) {
+       Element e = new Element("AppendFrame" + (a.frame_type - 251));
+       e.setAttr("tag", "" + a.frame_type);
+       e.addAll(getVerificationTypeInfo("Local", a.locals));
+       e.trimToSize();
+       return e;
+    }
+
+    @Override
+    public Element visit_full_frame(full_frame fl_frm, Void p) {
+         Element e = new Element("FullFrame");
+         e.setAttr("tag", "" + fl_frm.frame_type);
+         e.addAll(getVerificationTypeInfo("Local", fl_frm.locals));
+         e.trimToSize();
+         return e;
+    }
+
+    private Element getVerificationTypeInfo(String kind,
+            StackMapTable_attribute.verification_type_info velems[]) {
+        Element container = new Element(velems.length);
+        for (StackMapTable_attribute.verification_type_info v : velems) {
+            Element ve = null;
+            int offset = 0;
+            int index = 0;
+            switch (v.tag) {
+                case StackMapTable_attribute.verification_type_info.ITEM_Top:
+                    ve = new Element("ITEM_Top");
+                    break;
+                case StackMapTable_attribute.verification_type_info.ITEM_Integer:
+                    ve = new Element("ITEM_Integer");
+                    break;
+                case StackMapTable_attribute.verification_type_info.ITEM_Float:
+                    ve = new Element("ITEM_Float");
+                    break;
+                case StackMapTable_attribute.verification_type_info.ITEM_Long:
+                    ve = new Element("ITEM_Long");
+                    break;
+                case StackMapTable_attribute.verification_type_info.ITEM_Double:
+                    ve = new Element("ITEM_Double");
+                    break;
+                case StackMapTable_attribute.verification_type_info.ITEM_Null:
+                    ve = new Element("ITEM_Null");
+                    break;
+                case StackMapTable_attribute.verification_type_info.ITEM_Uninitialized:
+                    ve = new Element("ITEM_Uninitialized");
+                    offset = ((StackMapTable_attribute.Uninitialized_variable_info) v).offset;
+                    ve.setAttr("offset", "" + offset);
+                    break;
+                case StackMapTable_attribute.verification_type_info.ITEM_UninitializedThis:
+                    ve = new Element("ITEM_UnitializedtThis");
+                    break;
+                case StackMapTable_attribute.verification_type_info.ITEM_Object:
+                    ve = new Element("ITEM_Object");
+                    index = ((StackMapTable_attribute.Object_variable_info) v).cpool_index;
+                    ve.setAttr("class", x.getCpString(index));
+                    break;
+                default:
+                    ve = new Element("Unknown");
+            }
+            Element kindE = new Element(kind);
+            kindE.setAttr("tag", "" + v.tag);
+            container.add(kindE);
+            kindE.add(ve);
+        }
+        container.trimToSize();
+        return container;
+    }
+}
+
+class InstructionVisitor implements Instruction.KindVisitor<Element, Void> {
+
+    final ClassReader x;
+    final ClassFile cf;
+
+    public InstructionVisitor(ClassReader x, ClassFile cf) {
+        this.x = x;
+        this.cf = cf;
+    }
+
+    public Element visit(Instruction i) {
+        Element ie =  i.accept(this, null);
+        ie.trimToSize();
+        return ie;
+    }
+
+    @Override
+    public Element visitNoOperands(Instruction i, Void p) {
+        Opcode o = i.getOpcode();
+        Element e = new Element(i.getMnemonic());
+        if (o.opcode > 0xab && o.opcode <= 0xb1) {
+            e.setAttr("pc", "" + i.getPC());
+        }
+        return e;
+    }
+
+    @Override
+    public Element visitArrayType(Instruction i, TypeKind tk, Void p) {
+        Element ie = new Element(i.getMnemonic());
+        ie.setAttr("num", "" + tk.value);
+        ie.setAttr("val", tk.name);
+        return ie;
+    }
+
+    @Override
+    public Element visitBranch(Instruction i, int i1, Void p) {
+        Element ie = new Element(i.getMnemonic());
+        ie.setAttr("lab", "" + (i.getPC() + i1));
+        return ie;
+    }
+
+    @Override
+    public Element visitConstantPoolRef(Instruction i, int i1, Void p) {
+        Element ie = new Element(i.getMnemonic());
+        ie.setAttr("ref", x.getCpString(i1));
+        return ie;
+    }
+
+    @Override
+    public Element visitConstantPoolRefAndValue(Instruction i, int i1, int i2, Void p) {
+        // workaround for a potential bug in classfile
+        Element ie = new Element(i.getMnemonic());
+        if (i.getOpcode().equals(Opcode.IINC_W)) {
+            ie.setAttr("loc", "" + i1);
+            ie.setAttr("num", "" + i2);
+        } else {
+            ie.setAttr("ref", x.getCpString(i1));
+            ie.setAttr("val", "" + i2);
+        }
+        return ie;
+    }
+
+    @Override
+    public Element visitLocal(Instruction i, int i1, Void p) {
+        Element ie = new Element(i.getMnemonic());
+        ie.setAttr("loc", "" + i1);
+        return ie;
+    }
+
+    @Override
+    public Element visitLocalAndValue(Instruction i, int i1, int i2, Void p) {
+        Element ie = new Element(i.getMnemonic());
+        ie.setAttr("loc", "" + i1);
+        ie.setAttr("num", "" + i2);
+        return ie;
+    }
+
+    @Override
+    public Element visitLookupSwitch(Instruction i, int i1, int i2, int[] ints,
+                                     int[] ints1, Void p) {
+        Element ie = new Element(i.getMnemonic());
+        int pc = i.getPC();
+        ie.setAttr("lab", "" + (pc + i1));
+        for (int k = 0 ; k < i2 ; k++) {
+            Element c = new Element("Case");
+            c.setAttr("num", "" + (ints[k]));
+            c.setAttr("lab", "" + (pc + ints1[k]));
+            c.trimToSize();
+            ie.add(c);
+        }
+        return ie;
+    }
+
+    @Override
+    public Element visitTableSwitch(Instruction i, int i1, int i2, int i3,
+                                    int[] ints, Void p) {
+        Element ie = new Element(i.getMnemonic());
+        int pc = i.getPC();
+        ie.setAttr("lab", "" + (pc + i1));
+        for (int k : ints) {
+            Element c = new Element("Case");
+            c.setAttr("num", "" + (k + i2));
+            c.setAttr("lab", "" + (pc + k));
+            c.trimToSize();
+            ie.add(c);
+        }
+        return ie;
+    }
+
+    @Override
+    public Element visitValue(Instruction i, int i1, Void p) {
+        Element ie = new Element(i.getMnemonic());
+        ie.setAttr("num", "" + i1);
+        return ie;
+    }
+
+    @Override
+    public Element visitUnknown(Instruction i, Void p) {
+        Element e = new Element(i.getMnemonic());
+        e.setAttr("pc", "" + i.getPC());
+        e.setAttr("opcode", "" + i.getOpcode().opcode);
+        return e;
+    }
+}
+
+class AnnotationsElementVisitor implements Annotation.element_value.Visitor<Element, Element> {
+    final ClassReader x;
+    final ClassFile cf;
+
+    public AnnotationsElementVisitor(ClassReader x, ClassFile cf) {
+        this.x = x;
+        this.cf = cf;
+    }
+
+    public Element visit(Annotation.element_value v, Element p) {
+        return v.accept(this, p);
+    }
+
+    @Override
+    public Element visitPrimitive(Primitive_element_value e, Element p) {
+        Element el = new Element("String");
+        el.setAttr("val", x.getCpString(e.const_value_index));
+        el.trimToSize();
+        return el;
+    }
+
+    @Override
+    public Element visitEnum(Enum_element_value e, Element p) {
+        Element el = new Element("Enum");
+        el.setAttr("name", x.getCpString(e.const_name_index));
+        el.setAttr("type", x.getCpString(e.type_name_index));
+        el.trimToSize();
+        return el;
+    }
+
+    @Override
+    public Element visitClass(Class_element_value c, Element p) {
+        Element el = new Element("Class");
+        el.setAttr("name", x.getCpString(c.class_info_index));
+        el.trimToSize();
+        return el;
+    }
+
+    @Override
+    public Element visitAnnotation(Annotation_element_value a, Element p) {
+        Element el = new Element("Annotation");
+        Annotation anno = a.annotation_value;
+        for (Annotation.element_value_pair evp : anno.element_value_pairs) {
+            Element child = visit(evp.value, el);
+            if (child != null) {
+                el.add(child);
+            }
+        }
+        el.trimToSize();
+        return el;
+    }
+
+    @Override
+    public Element visitArray(Array_element_value a, Element p) {
+     Element el = new Element("Array");
+        for (Annotation.element_value v : a.values) {
+           Element child = visit(v, el);
+           if (child != null) {
+               el.add(child);
+           }
+        }
+        el.trimToSize();
+        return el;
+    }
+}
--- a/jdk/test/tools/pack200/pack200-verifier/src/xmlkit/ClassSyntax.java	Wed Jul 05 18:09:43 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,518 +0,0 @@
-/*
- * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package xmlkit; // -*- mode: java; indent-tabs-mode: nil -*-
-import xmlkit.XMLKit.*;
-
-import java.util.*;
-import java.security.MessageDigest;
-import java.nio.ByteBuffer;
-import xmlkit.XMLKit.Element;
-/*
- * @author jrose
- */
-public abstract class ClassSyntax {
-
-    public interface GetCPIndex {
-
-        int getCPIndex(int tag, String name);  // cp finder
-    }
-    public static final int CONSTANT_Utf8 = 1,
-            CONSTANT_Integer = 3,
-            CONSTANT_Float = 4,
-            CONSTANT_Long = 5,
-            CONSTANT_Double = 6,
-            CONSTANT_Class = 7,
-            CONSTANT_String = 8,
-            CONSTANT_Fieldref = 9,
-            CONSTANT_Methodref = 10,
-            CONSTANT_InterfaceMethodref = 11,
-            CONSTANT_NameAndType = 12;
-    private static final String[] cpTagName = {
-        /* 0:  */null,
-        /* 1:  */ "Utf8",
-        /* 2:  */ null,
-        /* 3:  */ "Integer",
-        /* 4:  */ "Float",
-        /* 5:  */ "Long",
-        /* 6:  */ "Double",
-        /* 7:  */ "Class",
-        /* 8:  */ "String",
-        /* 9:  */ "Fieldref",
-        /* 10: */ "Methodref",
-        /* 11: */ "InterfaceMethodref",
-        /* 12: */ "NameAndType",
-        null
-    };
-    private static final Set<String> cpTagNames;
-
-    static {
-        Set<String> set = new HashSet<String>(Arrays.asList(cpTagName));
-        set.remove(null);
-        cpTagNames = Collections.unmodifiableSet(set);
-    }
-    public static final int ITEM_Top = 0, // replicates by [1..4,1..4]
-            ITEM_Integer = 1, // (ditto)
-            ITEM_Float = 2,
-            ITEM_Double = 3,
-            ITEM_Long = 4,
-            ITEM_Null = 5,
-            ITEM_UninitializedThis = 6,
-            ITEM_Object = 7,
-            ITEM_Uninitialized = 8,
-            ITEM_ReturnAddress = 9,
-            ITEM_LIMIT = 10;
-    private static final String[] itemTagName = {
-        "Top",
-        "Integer",
-        "Float",
-        "Double",
-        "Long",
-        "Null",
-        "UninitializedThis",
-        "Object",
-        "Uninitialized",
-        "ReturnAddress",};
-    private static final Set<String> itemTagNames;
-
-    static {
-        Set<String> set = new HashSet<String>(Arrays.asList(itemTagName));
-        set.remove(null);
-        itemTagNames = Collections.unmodifiableSet(set);
-    }
-    protected static final HashMap<String, String> attrTypesBacking;
-    protected static final Map<String, String> attrTypesInit;
-
-    static {
-        HashMap<String, String> at = new HashMap<String, String>();
-
-        //at.put("*.Deprecated", "<deprecated=true>");
-        //at.put("*.Synthetic", "<synthetic=true>");
-        ////at.put("Field.ConstantValue", "<constantValue=>KQH");
-        //at.put("Class.SourceFile", "<sourceFile=>RUH");
-        at.put("Method.Bridge", "<Bridge>");
-        at.put("Method.Varargs", "<Varargs>");
-        at.put("Class.Enum", "<Enum>");
-        at.put("*.Signature", "<Signature>RSH");
-        //at.put("*.Deprecated", "<Deprecated>");
-        //at.put("*.Synthetic", "<Synthetic>");
-        at.put("Field.ConstantValue", "<ConstantValue>KQH");
-        at.put("Class.SourceFile", "<SourceFile>RUH");
-        at.put("Class.InnerClasses", "NH[<InnerClass><class=>RCH<outer=>RCH<name=>RUH<flags=>FH]");
-        at.put("Code.LineNumberTable", "NH[<LineNumber><bci=>PH<line=>H]");
-        at.put("Code.LocalVariableTable", "NH[<LocalVariable><bci=>PH<span=>H<name=>RUH<type=>RSH<slot=>H]");
-        at.put("Code.LocalVariableTypeTable", "NH[<LocalVariableType><bci=>PH<span=>H<name=>RUH<type=>RSH<slot=>H]");
-        at.put("Method.Exceptions", "NH[<Exception><name=>RCH]");
-        at.put("Method.Code", "<Code>...");
-        at.put("Code.StackMapTable", "<Frame>...");
-        //at.put("Code.StkMapX", "<FrameX>...");
-        if (true) {
-            at.put("Code.StackMapTable",
-                    "[NH[<Frame>(1)]]"
-                    + "[TB"
-                    + "(64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79"
-                    + ",80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95"
-                    + ",96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111"
-                    + ",112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127"
-                    + ")[<SameLocals1StackItemFrame>(4)]"
-                    + "(247)[<SameLocals1StackItemExtended>H(4)]"
-                    + "(248)[<Chop3>H]"
-                    + "(249)[<Chop2>H]"
-                    + "(250)[<Chop1>H]"
-                    + "(251)[<SameFrameExtended>H]"
-                    + "(252)[<Append1>H(4)]"
-                    + "(253)[<Append2>H(4)(4)]"
-                    + "(254)[<Append3>H(4)(4)(4)]"
-                    + "(255)[<FullFrame>H(2)(3)]"
-                    + "()[<SameFrame>]]"
-                    + "[NH[<Local>(4)]]"
-                    + "[NH[<Stack>(4)]]"
-                    + "[TB"
-                    + ("(0)[<Top>]"
-                    + "(1)[<ItemInteger>](2)[<ItemFloat>](3)[<ItemDouble>](4)[<ItemLong>]"
-                    + "(5)[<ItemNull>](6)[<ItemUninitializedThis>]"
-                    + "(7)[<ItemObject><class=>RCH]"
-                    + "(8)[<ItemUninitialized><bci=>PH]"
-                    + "()[<ItemUnknown>]]"));
-        }
-
-        at.put("Class.EnclosingMethod", "<EnclosingMethod><class=>RCH<desc=>RDH");//RDNH
-
-        // Layouts of metadata attrs:
-        String vpf = "[<RuntimeVisibleAnnotation>";
-        String ipf = "[<RuntimeInvisibleAnnotation>";
-        String apf = "[<Annotation>";
-        String mdanno2 = ""
-                + "<type=>RSHNH[<Member><name=>RUH(3)]]"
-                + ("[TB"
-                + "(\\B,\\C,\\I,\\S,\\Z)[<value=>KIH]"
-                + "(\\D)[<value=>KDH]"
-                + "(\\F)[<value=>KFH]"
-                + "(\\J)[<value=>KJH]"
-                + "(\\c)[<class=>RSH]"
-                + "(\\e)[<type=>RSH<name=>RUH]"
-                + "(\\s)[<String>RUH]"
-                + "(\\@)[(2)]"
-                + "(\\[)[NH[<Element>(3)]]"
-                + "()[]"
-                + "]");
-        String visanno = "[NH[(2)]][(1)]" + vpf + mdanno2;
-        String invanno = "[NH[(2)]][(1)]" + ipf + mdanno2;
-        String vparamanno = ""
-                + "[NB[<RuntimeVisibleParameterAnnotation>(1)]][NH[(2)]]"
-                + apf + mdanno2;
-        String iparamanno = ""
-                + "[NB[<RuntimeInvisibleParameterAnnotation>(1)]][NH[(2)]]"
-                + apf + mdanno2;
-        String mdannodef = "[<AnnotationDefault>(3)][(1)]" + apf + mdanno2;
-        String[] mdplaces = {"Class", "Field", "Method"};
-        for (String place : mdplaces) {
-            at.put(place + ".RuntimeVisibleAnnotations", visanno);
-            at.put(place + ".RuntimeInvisibleAnnotations", invanno);
-        }
-        at.put("Method.RuntimeVisibleParameterAnnotations", vparamanno);
-        at.put("Method.RuntimeInvisibleParameterAnnotations", iparamanno);
-        at.put("Method.AnnotationDefault", mdannodef);
-
-        attrTypesBacking = at;
-        attrTypesInit = Collections.unmodifiableMap(at);
-    }
-
-    ;
-    private static final String[] jcovAttrTypes = {
-        "Code.CoverageTable=NH[<Coverage><bci=>PH<type=>H<line=>I<pos=>I]",
-        "Code.CharacterRangeTable=NH[<CharacterRange><bci=>PH<endbci=>POH<from=>I<to=>I<flag=>H]",
-        "Class.SourceID=<SourceID><id=>RUH",
-        "Class.CompilationID=<CompilationID><id=>RUH"
-    };
-    protected static final String[][] modifierNames = {
-        {"public"},
-        {"private"},
-        {"protected"},
-        {"static"},
-        {"final"},
-        {"synchronized"},
-        {null, "volatile", "bridge"},
-        {null, "transient", "varargs"},
-        {null, null, "native"},
-        {"interface"},
-        {"abstract"},
-        {"strictfp"},
-        {"synthetic"},
-        {"annotation"},
-        {"enum"},};
-    protected static final String EIGHT_BIT_CHAR_ENCODING = "ISO8859_1";
-    protected static final String UTF8_ENCODING = "UTF8";
-    // What XML tags are used by this syntax, apart from attributes?
-    protected static final Set<String> nonAttrTags;
-
-    static {
-        HashSet<String> tagSet = new HashSet<String>();
-        Collections.addAll(tagSet, new String[]{
-                    "ConstantPool",// the CP
-                    "Class", // the class
-                    "Interface", // implemented interfaces
-                    "Method", // methods
-                    "Field", // fields
-                    "Handler", // exception handler pseudo-attribute
-                    "Attribute", // unparsed attribute
-                    "Bytes", // bytecodes
-                    "Instructions" // bytecodes, parsed
-                });
-        nonAttrTags = Collections.unmodifiableSet(tagSet);
-    }
-
-    // Accessors.
-    public static Set<String> nonAttrTags() {
-        return nonAttrTags;
-    }
-
-    public static String cpTagName(int t) {
-        t &= 0xFF;
-        String ts = null;
-        if (t < cpTagName.length) {
-            ts = cpTagName[t];
-        }
-        if (ts != null) {
-            return ts;
-        }
-        return ("UnknownTag" + (int) t).intern();
-    }
-
-    public static int cpTagValue(String name) {
-        for (int t = 0; t < cpTagName.length; t++) {
-            if (name.equals(cpTagName[t])) {
-                return t;
-            }
-        }
-        return 0;
-    }
-
-    public static String itemTagName(int t) {
-        t &= 0xFF;
-        String ts = null;
-        if (t < itemTagName.length) {
-            ts = itemTagName[t];
-        }
-        if (ts != null) {
-            return ts;
-        }
-        return ("UnknownItem" + (int) t).intern();
-    }
-
-    public static int itemTagValue(String name) {
-        for (int t = 0; t < itemTagName.length; t++) {
-            if (name.equals(itemTagName[t])) {
-                return t;
-            }
-        }
-        return -1;
-    }
-
-    public void addJcovAttrTypes() {
-        addAttrTypes(jcovAttrTypes);
-    }
-    // Public methods for declaring attribute types.
-    protected Map<String, String> attrTypes = attrTypesInit;
-
-    public void addAttrType(String opt) {
-        int eqpos = opt.indexOf('=');
-        addAttrType(opt.substring(0, eqpos), opt.substring(eqpos + 1));
-    }
-
-    public void addAttrTypes(String[] opts) {
-        for (String opt : opts) {
-            addAttrType(opt);
-        }
-    }
-
-    private void checkAttr(String attr) {
-        if (!attr.startsWith("Class.")
-                && !attr.startsWith("Field.")
-                && !attr.startsWith("Method.")
-                && !attr.startsWith("Code.")
-                && !attr.startsWith("*.")) {
-            throw new IllegalArgumentException("attr name must start with 'Class.', etc.");
-        }
-        String uattr = attr.substring(attr.indexOf('.') + 1);
-        if (nonAttrTags.contains(uattr)) {
-            throw new IllegalArgumentException("attr name must not be one of " + nonAttrTags);
-        }
-    }
-
-    private void checkAttrs(Map<String, String> at) {
-        for (String attr : at.keySet()) {
-            checkAttr(attr);
-        }
-    }
-
-    private void modAttrs() {
-        if (attrTypes == attrTypesInit) {
-            // Make modifiable.
-            attrTypes = new HashMap<String, String>(attrTypesBacking);
-        }
-    }
-
-    public void addAttrType(String attr, String fmt) {
-        checkAttr(attr);
-        modAttrs();
-        attrTypes.put(attr, fmt);
-    }
-
-    public void addAttrTypes(Map<String, String> at) {
-        checkAttrs(at);
-        modAttrs();
-        attrTypes.putAll(at);
-    }
-
-    public Map<String, String> getAttrTypes() {
-        if (attrTypes == attrTypesInit) {
-            return attrTypes;
-        }
-        return Collections.unmodifiableMap(attrTypes);
-    }
-
-    public void setAttrTypes(Map<String, String> at) {
-        checkAttrs(at);
-        modAttrs();
-        attrTypes.keySet().retainAll(at.keySet());
-        attrTypes.putAll(at);
-    }
-
-    // attr format helpers
-    protected static boolean matchTag(int tagValue, String caseStr) {
-        //System.out.println("matchTag "+tagValue+" in "+caseStr);
-        for (int pos = 0, max = caseStr.length(), comma;
-                pos < max;
-                pos = comma + 1) {
-            int caseValue;
-            if (caseStr.charAt(pos) == '\\') {
-                caseValue = caseStr.charAt(pos + 1);
-                comma = pos + 2;
-                assert (comma == max || caseStr.charAt(comma) == ',');
-            } else {
-                comma = caseStr.indexOf(',', pos);
-                if (comma < 0) {
-                    comma = max;
-                }
-                caseValue = Integer.parseInt(caseStr.substring(pos, comma));
-            }
-            if (tagValue == caseValue) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    protected static String[] getBodies(String type) {
-        ArrayList<String> bodies = new ArrayList<String>();
-        for (int i = 0; i < type.length();) {
-            String body = getBody(type, i);
-            bodies.add(body);
-            i += body.length() + 2;  // skip body and brackets
-        }
-        return bodies.toArray(new String[bodies.size()]);
-    }
-
-    protected static String getBody(String type, int i) {
-        assert (type.charAt(i) == '[');
-        int next = ++i;  // skip bracket
-        for (int depth = 1; depth > 0; next++) {
-            switch (type.charAt(next)) {
-                case '[':
-                    depth++;
-                    break;
-                case ']':
-                    depth--;
-                    break;
-                case '(':
-                    next = type.indexOf(')', next);
-                    break;
-                case '<':
-                    next = type.indexOf('>', next);
-                    break;
-            }
-            assert (next > 0);
-        }
-        --next;  // get before bracket
-        assert (type.charAt(next) == ']');
-        return type.substring(i, next);
-    }
-
-    public Element makeCPDigest(int length) {
-        MessageDigest md;
-        try {
-            md = MessageDigest.getInstance("MD5");
-        } catch (java.security.NoSuchAlgorithmException ee) {
-            throw new Error(ee);
-        }
-        int items = 0;
-        for (Element e : cpool.elements()) {
-            if (items == length) {
-                break;
-            }
-            if (cpTagNames.contains(e.getName())) {
-                items += 1;
-                md.update((byte) cpTagValue(e.getName()));
-                try {
-                    md.update(e.getText().toString().getBytes(UTF8_ENCODING));
-                } catch (java.io.UnsupportedEncodingException ee) {
-                    throw new Error(ee);
-                }
-            }
-        }
-        ByteBuffer bb = ByteBuffer.wrap(md.digest());
-        String l0 = Long.toHexString(bb.getLong(0));
-        String l1 = Long.toHexString(bb.getLong(8));
-        while (l0.length() < 16) {
-            l0 = "0" + l0;
-        }
-        while (l1.length() < 16) {
-            l1 = "0" + l1;
-        }
-        return new Element("Digest",
-                "length", "" + items,
-                "bytes", l0 + l1);
-    }
-
-    public Element getCPDigest(int length) {
-        if (length == -1) {
-            length = cpool.countAll(XMLKit.elementFilter(cpTagNames));
-        }
-        for (Element md : cpool.findAllElements("Digest").elements()) {
-            if (md.getAttrLong("length") == length) {
-                return md;
-            }
-        }
-        Element md = makeCPDigest(length);
-        cpool.add(md);
-        return md;
-    }
-
-    public Element getCPDigest() {
-        return getCPDigest(-1);
-    }
-
-    public boolean checkCPDigest(Element md) {
-        return md.equals(getCPDigest((int) md.getAttrLong("length")));
-    }
-
-    public static int computeInterfaceNum(String intMethRef) {
-        intMethRef = intMethRef.substring(1 + intMethRef.lastIndexOf(' '));
-        if (!intMethRef.startsWith("(")) {
-            return -1;
-        }
-        int signum = 1;  // start with one for "this"
-        scanSig:
-        for (int i = 1; i < intMethRef.length(); i++) {
-            char ch = intMethRef.charAt(i);
-            signum++;
-            switch (ch) {
-                case ')':
-                    --signum;
-                    break scanSig;
-                case 'L':
-                    i = intMethRef.indexOf(';', i);
-                    break;
-                case '[':
-                    while (ch == '[') {
-                        ch = intMethRef.charAt(++i);
-                    }
-                    if (ch == 'L') {
-                        i = intMethRef.indexOf(';', i);
-                    }
-                    break;
-            }
-        }
-        int num = (signum << 8) | 0;
-        //System.out.println("computeInterfaceNum "+intMethRef+" => "+num);
-        return num;
-    }
-    // Protected state for representing the class file.
-    protected Element cfile;          // <ClassFile ...>
-    protected Element cpool;          // <ConstantPool ...>
-    protected Element klass;          // <Class ...>
-    protected Element currentMember;  // varies during scans
-    protected Element currentCode;    // varies during scans
-}
--- a/jdk/test/tools/pack200/pack200-verifier/src/xmlkit/ClassWriter.java	Wed Jul 05 18:09:43 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,818 +0,0 @@
-/*
- * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package xmlkit; // -*- mode: java; indent-tabs-mode: nil -*-
-
-import java.util.*;
-import java.lang.reflect.*;
-import java.io.*;
-import xmlkit.XMLKit.Element;
-/*
- * @author jrose
- */
-public class ClassWriter extends ClassSyntax implements ClassSyntax.GetCPIndex {
-
-    private static final CommandLineParser CLP = new CommandLineParser(""
-            + "-source:     +>  = \n"
-            + "-dest:       +>  = \n"
-            + "-encoding:   +>  = \n"
-            + "-parseBytes      $ \n"
-            + "-               *? \n"
-            + "\n");
-
-    public static void main(String[] ava) throws IOException {
-        ArrayList<String> av = new ArrayList<String>(Arrays.asList(ava));
-        HashMap<String, String> props = new HashMap<String, String>();
-        props.put("-encoding:", "UTF8");  // default
-        CLP.parse(av, props);
-        File source = asFile(props.get("-source:"));
-        File dest = asFile(props.get("-dest:"));
-        String encoding = props.get("-encoding:");
-        boolean parseBytes = props.containsKey("-parseBytes");
-        boolean destMade = false;
-
-        for (String a : av) {
-            File f;
-            File inf = new File(source, a);
-            System.out.println("Reading " + inf);
-            Element e;
-            if (inf.getName().endsWith(".class")) {
-                ClassReader cr = new ClassReader();
-                cr.parseBytes = parseBytes;
-                e = cr.readFrom(inf);
-                f = new File(a);
-            } else if (inf.getName().endsWith(".xml")) {
-                InputStream in = new FileInputStream(inf);
-                Reader inw = ClassReader.makeReader(in, encoding);
-                e = XMLKit.readFrom(inw);
-                e.findAllInTree(XMLKit.and(XMLKit.elementFilter(nonAttrTags()),
-                        XMLKit.methodFilter(Element.method("trimText"))));
-                //System.out.println(e);
-                inw.close();
-                f = new File(a.substring(0, a.length() - ".xml".length()) + ".class");
-            } else {
-                System.out.println("Warning: unknown input " + a);
-                continue;
-            }
-            // Now write it:
-            if (!destMade) {
-                destMade = true;
-                if (dest == null) {
-                    dest = File.createTempFile("TestOut", ".dir", new File("."));
-                    dest.delete();
-                    System.out.println("Writing results to " + dest);
-                }
-                if (!(dest.isDirectory() || dest.mkdir())) {
-                    throw new RuntimeException("Cannot create " + dest);
-                }
-            }
-            File outf = new File(dest, f.isAbsolute() ? f.getName() : f.getPath());
-            outf.getParentFile().mkdirs();
-            new ClassWriter(e).writeTo(outf);
-        }
-    }
-
-    private static File asFile(String str) {
-        return (str == null) ? null : new File(str);
-    }
-
-    public void writeTo(File file) throws IOException {
-        OutputStream out = null;
-        try {
-            out = new BufferedOutputStream(new FileOutputStream(file));
-            writeTo(out);
-        } finally {
-            if (out != null) {
-                out.close();
-            }
-        }
-    }
-    protected String[] callables;     // varies
-    protected int cpoolSize = 0;
-    protected HashMap<String, String> attrTypesByTag;
-    protected OutputStream out;
-    protected HashMap<String, int[]> cpMap = new HashMap<String, int[]>();
-    protected ArrayList<ByteArrayOutputStream> attrBufs = new ArrayList<ByteArrayOutputStream>();
-
-    private void setupAttrTypes() {
-        attrTypesByTag = new HashMap<String, String>();
-        for (String key : attrTypes.keySet()) {
-            String pfx = key.substring(0, key.indexOf('.') + 1);
-            String val = attrTypes.get(key);
-            int pos = val.indexOf('<');
-            if (pos >= 0) {
-                String tag = val.substring(pos + 1, val.indexOf('>', pos));
-                attrTypesByTag.put(pfx + tag, key);
-            }
-        }
-        //System.out.println("attrTypesByTag: "+attrTypesByTag);
-    }
-
-    protected ByteArrayOutputStream getAttrBuf() {
-        int nab = attrBufs.size();
-        if (nab == 0) {
-            return new ByteArrayOutputStream(1024);
-        }
-        ByteArrayOutputStream ab = attrBufs.get(nab - 1);
-        attrBufs.remove(nab - 1);
-        return ab;
-    }
-
-    protected void putAttrBuf(ByteArrayOutputStream ab) {
-        ab.reset();
-        attrBufs.add(ab);
-    }
-
-    public ClassWriter(Element root) {
-        this(root, null);
-    }
-
-    public ClassWriter(Element root, ClassSyntax cr) {
-        if (cr != null) {
-            attrTypes = cr.attrTypes;
-        }
-        setupAttrTypes();
-        if (root.getName() == "ClassFile") {
-            cfile = root;
-            cpool = root.findElement("ConstantPool");
-            klass = root.findElement("Class");
-        } else if (root.getName() == "Class") {
-            cfile = new Element("ClassFile",
-                    new String[]{
-                        "magic", String.valueOf(0xCAFEBABE),
-                        "minver", "0", "majver", "46",});
-            cpool = new Element("ConstantPool");
-            klass = root;
-        } else {
-            throw new IllegalArgumentException("bad element type " + root.getName());
-        }
-        if (cpool == null) {
-            cpool = new Element("ConstantPool");
-        }
-
-        int cpLen = 1 + cpool.size();
-        for (Element c : cpool.elements()) {
-            int id = (int) c.getAttrLong("id");
-            int tag = cpTagValue(c.getName());
-            setCPIndex(tag, c.getText().toString(), id);
-            switch (tag) {
-                case CONSTANT_Long:
-                case CONSTANT_Double:
-                    cpLen += 1;
-            }
-        }
-        cpoolSize = cpLen;
-    }
-
-    public int findCPIndex(int tag, String name) {
-        if (name == null) {
-            return 0;
-        }
-        int[] ids = cpMap.get(name.toString());
-        return (ids == null) ? 0 : ids[tag];
-    }
-
-    public int getCPIndex(int tag, String name) {
-        //System.out.println("getCPIndex "+cpTagName(tag)+" "+name);
-        if (name == null) {
-            return 0;
-        }
-        int id = findCPIndex(tag, name);
-        if (id == 0) {
-            id = cpoolSize;
-            cpoolSize += 1;
-            setCPIndex(tag, name, id);
-            cpool.add(new Element(cpTagName(tag),
-                    new String[]{"id", "" + id},
-                    new Object[]{name}));
-            int pos;
-            switch (tag) {
-                case CONSTANT_Long:
-                case CONSTANT_Double:
-                    cpoolSize += 1;
-                    break;
-                case CONSTANT_Class:
-                case CONSTANT_String:
-                    getCPIndex(CONSTANT_Utf8, name);
-                    break;
-                case CONSTANT_Fieldref:
-                case CONSTANT_Methodref:
-                case CONSTANT_InterfaceMethodref:
-                    pos = name.indexOf(' ');
-                    getCPIndex(CONSTANT_Class, name.substring(0, pos));
-                    getCPIndex(CONSTANT_NameAndType, name.substring(pos + 1));
-                    break;
-                case CONSTANT_NameAndType:
-                    pos = name.indexOf(' ');
-                    getCPIndex(CONSTANT_Utf8, name.substring(0, pos));
-                    getCPIndex(CONSTANT_Utf8, name.substring(pos + 1));
-                    break;
-            }
-        }
-        return id;
-    }
-
-    public void setCPIndex(int tag, String name, int id) {
-        //System.out.println("setCPIndex id="+id+" tag="+tag+" name="+name);
-        int[] ids = cpMap.get(name);
-        if (ids == null) {
-            cpMap.put(name, ids = new int[13]);
-        }
-        if (ids[tag] != 0 && ids[tag] != id) {
-            System.out.println("Warning: Duplicate CP entries for " + ids[tag] + " and " + id);
-        }
-        //assert(ids[tag] == 0 || ids[tag] == id);
-        ids[tag] = id;
-    }
-
-    public int parseFlags(String flagString) {
-        int flags = 0;
-        int i = -1;
-        for (String[] names : modifierNames) {
-            ++i;
-            for (String name : names) {
-                if (name == null) {
-                    continue;
-                }
-                int pos = flagString.indexOf(name);
-                if (pos >= 0) {
-                    flags |= (1 << i);
-                }
-            }
-        }
-        return flags;
-    }
-
-    public void writeTo(OutputStream realOut) throws IOException {
-        OutputStream headOut = realOut;
-        ByteArrayOutputStream tailOut = new ByteArrayOutputStream();
-
-        // write the body of the class file first
-        this.out = tailOut;
-        writeClass();
-
-        // write the file header last
-        this.out = headOut;
-        u4((int) cfile.getAttrLong("magic"));
-        u2((int) cfile.getAttrLong("minver"));
-        u2((int) cfile.getAttrLong("majver"));
-        writeCP();
-
-        // recopy the file tail
-        this.out = null;
-        tailOut.writeTo(realOut);
-    }
-
-    void writeClass() throws IOException {
-        int flags = parseFlags(klass.getAttr("flags"));
-        flags ^= Modifier.SYNCHRONIZED;
-        u2(flags);
-        cpRef(CONSTANT_Class, klass.getAttr("name"));
-        cpRef(CONSTANT_Class, klass.getAttr("super"));
-        Element interfaces = klass.findAllElements("Interface");
-        u2(interfaces.size());
-        for (Element e : interfaces.elements()) {
-            cpRef(CONSTANT_Class, e.getAttr("name"));
-        }
-        for (int isMethod = 0; isMethod <= 1; isMethod++) {
-            Element members = klass.findAllElements(isMethod != 0 ? "Method" : "Field");
-            u2(members.size());
-            for (Element m : members.elements()) {
-                writeMember(m, isMethod != 0);
-            }
-        }
-        writeAttributesFor(klass);
-    }
-
-    private void writeMember(Element member, boolean isMethod) throws IOException {
-        //System.out.println("writeMember "+member);
-        u2(parseFlags(member.getAttr("flags")));
-        cpRef(CONSTANT_Utf8, member.getAttr("name"));
-        cpRef(CONSTANT_Utf8, member.getAttr("type"));
-        writeAttributesFor(member);
-    }
-
-    protected void writeAttributesFor(Element x) throws IOException {
-        LinkedHashSet<String> attrNames = new LinkedHashSet<String>();
-        for (Element e : x.elements()) {
-            attrNames.add(e.getName());  // uniquifying
-        }
-        attrNames.removeAll(nonAttrTags());
-        u2(attrNames.size());
-        if (attrNames.isEmpty()) {
-            return;
-        }
-        Element prevCurrent;
-        if (x.getName() == "Code") {
-            prevCurrent = currentCode;
-            currentCode = x;
-        } else {
-            prevCurrent = currentMember;
-            currentMember = x;
-        }
-        OutputStream realOut = this.out;
-        for (String utag : attrNames) {
-            String qtag = x.getName() + "." + utag;
-            String wtag = "*." + utag;
-            String key = attrTypesByTag.get(qtag);
-            if (key == null) {
-                key = attrTypesByTag.get(wtag);
-            }
-            String type = attrTypes.get(key);
-            //System.out.println("tag "+qtag+" => key "+key+"; type "+type);
-            Element attrs = x.findAllElements(utag);
-            ByteArrayOutputStream attrBuf = getAttrBuf();
-            if (type == null) {
-                if (attrs.size() != 1 || !attrs.get(0).equals(new Element(utag))) {
-                    System.out.println("Warning:  No attribute type description: " + qtag);
-                }
-                key = wtag;
-            } else {
-                try {
-                    this.out = attrBuf;
-                    // unparse according to type desc.
-                    if (type.equals("<Code>...")) {
-                        writeCode((Element) attrs.get(0));  // assume only 1
-                    } else if (type.equals("<Frame>...")) {
-                        writeStackMap(attrs, false);
-                    } else if (type.equals("<FrameX>...")) {
-                        writeStackMap(attrs, true);
-                    } else if (type.startsWith("[")) {
-                        writeAttributeRecursive(attrs, type);
-                    } else {
-                        writeAttribute(attrs, type);
-                    }
-                } finally {
-                    //System.out.println("Attr Bytes = \""+attrBuf.toString(EIGHT_BIT_CHAR_ENCODING).replace('"', (char)('"'|0x80))+"\"");
-                    this.out = realOut;
-                }
-            }
-            cpRef(CONSTANT_Utf8, key.substring(key.indexOf('.') + 1));
-            u4(attrBuf.size());
-            attrBuf.writeTo(out);
-            putAttrBuf(attrBuf);
-        }
-        if (x.getName() == "Code") {
-            currentCode = prevCurrent;
-        } else {
-            currentMember = prevCurrent;
-        }
-    }
-
-    private void writeAttributeRecursive(Element aval, String type) throws IOException {
-        assert (callables == null);
-        callables = getBodies(type);
-        writeAttribute(aval, callables[0]);
-        callables = null;
-    }
-
-    private void writeAttribute(Element aval, String type) throws IOException {
-        //System.out.println("writeAttribute "+aval+"  using "+type);
-        String nextAttrName = null;
-        boolean afterElemHead = false;
-        for (int len = type.length(), next, i = 0; i < len; i = next) {
-            int value;
-            char intKind;
-            int tag;
-            int sigChar;
-            String attrValue;
-            switch (type.charAt(i)) {
-                case '<':
-                    assert (nextAttrName == null);
-                    next = type.indexOf('>', i);
-                    String form = type.substring(i + 1, next++);
-                    if (form.indexOf('=') < 0) {
-                        //  elem_placement = '<' elemname '>'
-                        if (aval.isAnonymous()) {
-                            assert (aval.size() == 1);
-                            aval = (Element) aval.get(0);
-                        }
-                        assert (aval.getName().equals(form)) : aval + " // " + form;
-                        afterElemHead = true;
-                    } else {
-                        //  attr_placement = '(' attrname '=' (value)? ')'
-                        int eqPos = form.indexOf('=');
-                        assert (eqPos >= 0);
-                        nextAttrName = form.substring(0, eqPos).intern();
-                        if (eqPos != form.length() - 1) {
-                            // value is implicit, not placed in file
-                            nextAttrName = null;
-                        }
-                        afterElemHead = false;
-                    }
-                    continue;
-                case '(':
-                    next = type.indexOf(')', ++i);
-                    int callee = Integer.parseInt(type.substring(i, next++));
-                    writeAttribute(aval, callables[callee]);
-                    continue;
-                case 'N': // replication = 'N' int '[' type ... ']'
-                {
-                    assert (nextAttrName == null);
-                    afterElemHead = false;
-                    char countType = type.charAt(i + 1);
-                    next = i + 2;
-                    String type1 = getBody(type, next);
-                    Element elems = aval;
-                    if (type1.startsWith("<")) {
-                        // Select only matching members of aval.
-                        String elemName = type1.substring(1, type1.indexOf('>'));
-                        elems = aval.findAllElements(elemName);
-                    }
-                    putInt(elems.size(), countType);
-                    next += type1.length() + 2;  // skip body and brackets
-                    for (Element elem : elems.elements()) {
-                        writeAttribute(elem, type1);
-                    }
-                }
-                continue;
-                case 'T': // union = 'T' any_int union_case* '(' ')' '[' body ']'
-                    // write the value
-                    value = (int) aval.getAttrLong("tag");
-                    assert (aval.getAttr("tag") != null) : aval;
-                    intKind = type.charAt(++i);
-                    if (intKind == 'S') {
-                        intKind = type.charAt(++i);
-                    }
-                    putInt(value, intKind);
-                    nextAttrName = null;
-                    afterElemHead = false;
-                    ++i;  // skip the int type char
-                    // union_case = '(' ('-')? digit+ ')' '[' body ']'
-                    for (boolean foundCase = false;;) {
-                        assert (type.charAt(i) == '(');
-                        next = type.indexOf(')', ++i);
-                        assert (next >= i);
-                        String caseStr = type.substring(i, next++);
-                        String type1 = getBody(type, next);
-                        next += type1.length() + 2;  // skip body and brackets
-                        boolean lastCase = (caseStr.length() == 0);
-                        if (!foundCase
-                                && (lastCase || matchTag(value, caseStr))) {
-                            foundCase = true;
-                            // Execute this body.
-                            writeAttribute(aval, type1);
-                        }
-                        if (lastCase) {
-                            break;
-                        }
-                    }
-                    continue;
-                case 'B':
-                case 'H':
-                case 'I': // int = oneof "BHI"
-                    value = (int) aval.getAttrLong(nextAttrName);
-                    intKind = type.charAt(i);
-                    next = i + 1;
-                    break;
-                case 'K':
-                    sigChar = type.charAt(i + 1);
-                    if (sigChar == 'Q') {
-                        assert (currentMember.getName() == "Field");
-                        assert (aval.getName() == "ConstantValue");
-                        String sig = currentMember.getAttr("type");
-                        sigChar = sig.charAt(0);
-                        switch (sigChar) {
-                            case 'Z':
-                            case 'B':
-                            case 'C':
-                            case 'S':
-                                sigChar = 'I';
-                                break;
-                        }
-                    }
-                    switch (sigChar) {
-                        case 'I':
-                            tag = CONSTANT_Integer;
-                            break;
-                        case 'J':
-                            tag = CONSTANT_Long;
-                            break;
-                        case 'F':
-                            tag = CONSTANT_Float;
-                            break;
-                        case 'D':
-                            tag = CONSTANT_Double;
-                            break;
-                        case 'L':
-                            tag = CONSTANT_String;
-                            break;
-                        default:
-                            assert (false);
-                            tag = 0;
-                    }
-                    assert (type.charAt(i + 2) == 'H');  // only H works for now
-                    next = i + 3;
-                    assert (afterElemHead || nextAttrName != null);
-                    //System.out.println("get attr "+nextAttrName+" in "+aval);
-                    if (nextAttrName != null) {
-                        attrValue = aval.getAttr(nextAttrName);
-                        assert (attrValue != null);
-                    } else {
-                        assert (aval.isText()) : aval;
-                        attrValue = aval.getText().toString();
-                    }
-                    value = getCPIndex(tag, attrValue);
-                    intKind = 'H'; //type.charAt(i+2);
-                    break;
-                case 'R':
-                    sigChar = type.charAt(i + 1);
-                    switch (sigChar) {
-                        case 'C':
-                            tag = CONSTANT_Class;
-                            break;
-                        case 'S':
-                            tag = CONSTANT_Utf8;
-                            break;
-                        case 'D':
-                            tag = CONSTANT_Class;
-                            break;
-                        case 'F':
-                            tag = CONSTANT_Fieldref;
-                            break;
-                        case 'M':
-                            tag = CONSTANT_Methodref;
-                            break;
-                        case 'I':
-                            tag = CONSTANT_InterfaceMethodref;
-                            break;
-                        case 'U':
-                            tag = CONSTANT_Utf8;
-                            break;
-                        //case 'Q': tag = CONSTANT_Class; break;
-                        default:
-                            assert (false);
-                            tag = 0;
-                    }
-                    assert (type.charAt(i + 2) == 'H');  // only H works for now
-                    next = i + 3;
-                    assert (afterElemHead || nextAttrName != null);
-                    //System.out.println("get attr "+nextAttrName+" in "+aval);
-                    if (nextAttrName != null) {
-                        attrValue = aval.getAttr(nextAttrName);
-                    } else if (aval.hasText()) {
-                        attrValue = aval.getText().toString();
-                    } else {
-                        attrValue = null;
-                    }
-                    value = getCPIndex(tag, attrValue);
-                    intKind = 'H'; //type.charAt(i+2);
-                    break;
-                case 'P':  // bci = 'P' int
-                case 'S':  // signed_int = 'S' int
-                    next = i + 2;
-                    value = (int) aval.getAttrLong(nextAttrName);
-                    intKind = type.charAt(i + 1);
-                    break;
-                case 'F':
-                    next = i + 2;
-                    value = parseFlags(aval.getAttr(nextAttrName));
-                    intKind = type.charAt(i + 1);
-                    break;
-                default:
-                    throw new RuntimeException("bad attr format '" + type.charAt(i) + "': " + type);
-            }
-            // write the value
-            putInt(value, intKind);
-            nextAttrName = null;
-            afterElemHead = false;
-        }
-        assert (nextAttrName == null);
-    }
-
-    private void putInt(int x, char ch) throws IOException {
-        switch (ch) {
-            case 'B':
-                u1(x);
-                break;
-            case 'H':
-                u2(x);
-                break;
-            case 'I':
-                u4(x);
-                break;
-        }
-        assert ("BHI".indexOf(ch) >= 0);
-    }
-
-    private void writeCode(Element code) throws IOException {
-        //System.out.println("writeCode "+code);
-        //Element m = new Element(currentMember); m.remove(code);
-        //System.out.println("       in "+m);
-        int stack = (int) code.getAttrLong("stack");
-        int local = (int) code.getAttrLong("local");
-        Element bytes = code.findElement("Bytes");
-        Element insns = code.findElement("Instructions");
-        String bytecodes;
-        if (insns == null) {
-            bytecodes = bytes.getText().toString();
-        } else {
-            bytecodes = InstructionSyntax.assemble(insns, this);
-            // Cache the assembled bytecodes:
-            bytes = new Element("Bytes", (String[]) null, bytecodes);
-            code.add(0, bytes);
-        }
-        u2(stack);
-        u2(local);
-        int length = bytecodes.length();
-        u4(length);
-        for (int i = 0; i < length; i++) {
-            u1((byte) bytecodes.charAt(i));
-        }
-        Element handlers = code.findAllElements("Handler");
-        u2(handlers.size());
-        for (Element handler : handlers.elements()) {
-            int start = (int) handler.getAttrLong("start");
-            int end = (int) handler.getAttrLong("end");
-            int catsh = (int) handler.getAttrLong("catch");
-            u2(start);
-            u2(end);
-            u2(catsh);
-            cpRef(CONSTANT_Class, handler.getAttr("class"));
-        }
-        writeAttributesFor(code);
-    }
-
-    protected void writeStackMap(Element attrs, boolean hasXOption) throws IOException {
-        Element bytes = currentCode.findElement("Bytes");
-        assert (bytes != null && bytes.size() == 1);
-        int byteLength = ((String) bytes.get(0)).length();
-        boolean uoffsetIsU4 = (byteLength >= (1 << 16));
-        boolean ulocalvarIsU4 = currentCode.getAttrLong("local") >= (1 << 16);
-        boolean ustackIsU4 = currentCode.getAttrLong("stack") >= (1 << 16);
-        if (uoffsetIsU4) {
-            u4(attrs.size());
-        } else {
-            u2(attrs.size());
-        }
-        for (Element frame : attrs.elements()) {
-            int bci = (int) frame.getAttrLong("bci");
-            if (uoffsetIsU4) {
-                u4(bci);
-            } else {
-                u2(bci);
-            }
-            if (hasXOption) {
-                u1((int) frame.getAttrLong("flags"));
-            }
-            // Scan local and stack types in this frame:
-            final int LOCALS = 0, STACK = 1;
-            for (int j = LOCALS; j <= STACK; j++) {
-                Element types = frame.findElement(j == LOCALS ? "Local" : "Stack");
-                int typeSize = (types == null) ? 0 : types.size();
-                if (j == LOCALS) {
-                    if (ulocalvarIsU4) {
-                        u4(typeSize);
-                    } else {
-                        u2(typeSize);
-                    }
-                } else { // STACK
-                    if (ustackIsU4) {
-                        u4(typeSize);
-                    } else {
-                        u2(typeSize);
-                    }
-                }
-                if (types == null) {
-                    continue;
-                }
-                for (Element type : types.elements()) {
-                    int tag = itemTagValue(type.getName());
-                    u1(tag);
-                    switch (tag) {
-                        case ITEM_Object:
-                            cpRef(CONSTANT_Class, type.getAttr("class"));
-                            break;
-                        case ITEM_Uninitialized:
-                        case ITEM_ReturnAddress: {
-                            int offset = (int) type.getAttrLong("bci");
-                            if (uoffsetIsU4) {
-                                u4(offset);
-                            } else {
-                                u2(offset);
-                            }
-                        }
-                        break;
-                    }
-                }
-            }
-        }
-    }
-
-    public void writeCP() throws IOException {
-        int cpLen = cpoolSize;
-        u2(cpLen);
-        ByteArrayOutputStream buf = getAttrBuf();
-        for (Element c : cpool.elements()) {
-            if (!c.isText()) {
-                System.out.println("## !isText " + c);
-            }
-            int id = (int) c.getAttrLong("id");
-            int tag = cpTagValue(c.getName());
-            String name = c.getText().toString();
-            int pos;
-            u1(tag);
-            switch (tag) {
-                case CONSTANT_Utf8: {
-                    int done = 0;
-                    buf.reset();
-                    int nameLen = name.length();
-                    while (done < nameLen) {
-                        int next = name.indexOf((char) 0, done);
-                        if (next < 0) {
-                            next = nameLen;
-                        }
-                        if (done < next) {
-                            buf.write(name.substring(done, next).getBytes(UTF8_ENCODING));
-                        }
-                        if (next < nameLen) {
-                            buf.write(0300);
-                            buf.write(0200);
-                            next++;
-                        }
-                        done = next;
-                    }
-                    u2(buf.size());
-                    buf.writeTo(out);
-                }
-                break;
-                case CONSTANT_Integer:
-                    u4(Integer.parseInt(name));
-                    break;
-                case CONSTANT_Float:
-                    u4(Float.floatToIntBits(Float.parseFloat(name)));
-                    break;
-                case CONSTANT_Long:
-                    u8(Long.parseLong(name));
-                    //i += 1;  // no need:  extra cp slot is implicit
-                    break;
-                case CONSTANT_Double:
-                    u8(Double.doubleToLongBits(Double.parseDouble(name)));
-                    //i += 1;  // no need:  extra cp slot is implicit
-                    break;
-                case CONSTANT_Class:
-                case CONSTANT_String:
-                    u2(getCPIndex(CONSTANT_Utf8, name));
-                    break;
-                case CONSTANT_Fieldref:
-                case CONSTANT_Methodref:
-                case CONSTANT_InterfaceMethodref:
-                    pos = name.indexOf(' ');
-                    u2(getCPIndex(CONSTANT_Class, name.substring(0, pos)));
-                    u2(getCPIndex(CONSTANT_NameAndType, name.substring(pos + 1)));
-                    break;
-                case CONSTANT_NameAndType:
-                    pos = name.indexOf(' ');
-                    u2(getCPIndex(CONSTANT_Utf8, name.substring(0, pos)));
-                    u2(getCPIndex(CONSTANT_Utf8, name.substring(pos + 1)));
-                    break;
-            }
-        }
-        putAttrBuf(buf);
-    }
-
-    public void cpRef(int tag, String name) throws IOException {
-        u2(getCPIndex(tag, name));
-    }
-
-    public void u8(long x) throws IOException {
-        u4((int) (x >>> 32));
-        u4((int) (x >>> 0));
-    }
-
-    public void u4(int x) throws IOException {
-        u2(x >>> 16);
-        u2(x >>> 0);
-    }
-
-    public void u2(int x) throws IOException {
-        u1(x >>> 8);
-        u1(x >>> 0);
-    }
-
-    public void u1(int x) throws IOException {
-        out.write(x & 0xFF);
-    }
-}
-
--- a/jdk/test/tools/pack200/pack200-verifier/src/xmlkit/InstructionAssembler.java	Wed Jul 05 18:09:43 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,464 +0,0 @@
-/*
- * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package xmlkit; // -*- mode: java; indent-tabs-mode: nil -*-
-
-import xmlkit.XMLKit.Element;
-import java.util.HashMap;
-/*
- * @author jrose
- */
-abstract class InstructionAssembler extends InstructionSyntax {
-
-    InstructionAssembler() {
-    }
-
-    public static String assemble(Element instructions, String pcAttrName,
-            ClassSyntax.GetCPIndex getCPI) {
-        int insCount = instructions.size();
-        Element[] insElems = new Element[insCount];
-        int[] elemToIndexMap;
-        int[] insLocs;
-        byte[] ops = new byte[insCount];
-        int[] operands = new int[insCount];
-        boolean[] isWide = new boolean[insCount];
-        int[] branches;
-        int[] branchInsLocs;
-        HashMap<String, String> labels = new HashMap<String, String>();
-
-        final int WIDE = 0xc4;
-        final int GOTO = 0xa7;
-        final int GOTO_W = 0xc8;
-        final int GOTO_LEN = 3;
-        final int GOTO_W_LEN = 5;
-        assert ("wide".equals(bcNames[WIDE]));
-        assert ("goto".equals(bcNames[GOTO]));
-        assert ("goto_w".equals(bcNames[GOTO_W]));
-        assert (bcFormats[GOTO].length() == GOTO_LEN);
-        assert (bcFormats[GOTO_W].length() == GOTO_W_LEN);
-
-        // Unpack instructions into temp. arrays, and find branches and labels.
-        {
-            elemToIndexMap = (pcAttrName != null) ? new int[insCount] : null;
-            int[] buffer = operands;
-            int id = 0;
-            int branchCount = 0;
-            for (int i = 0; i < insCount; i++) {
-                Element ins = (Element) instructions.get(i);
-                if (elemToIndexMap != null) {
-                    elemToIndexMap[i] = (ins.getAttr(pcAttrName) != null ? id : -1);
-                }
-                String lab = ins.getAttr("pc");
-                if (lab != null) {
-                    labels.put(lab, String.valueOf(id));
-                }
-                int op = opCode(ins.getName());
-                if (op < 0) {
-                    assert (ins.getAttr(pcAttrName) != null
-                            || ins.getName().equals("label"));
-                    continue;  // delete PC holder element
-                }
-                if (op == WIDE) { //0xc4
-                    isWide[id] = true;  // force wide format
-                    continue;
-                }
-                if (bcFormats[op].indexOf('o') >= 0) {
-                    buffer[branchCount++] = id;
-                }
-                if (bcFormats[op] == bcWideFormats[op]) {
-                    isWide[id] = false;
-                }
-                insElems[id] = ins;
-                ops[id] = (byte) op;
-                id++;
-            }
-            insCount = id;  // maybe we deleted some wide prefixes, etc.
-            branches = new int[branchCount + 1];
-            System.arraycopy(buffer, 0, branches, 0, branchCount);
-            branches[branchCount] = -1;  // sentinel
-        }
-
-        // Compute instruction sizes.  These sizes are final,
-        // except for branch instructions, which may need lengthening.
-        // Some instructions (ldc, bipush, iload, iinc) are automagically widened.
-        insLocs = new int[insCount + 1];
-        int loc = 0;
-        for (int bn = 0, id = 0; id < insCount; id++) {
-            insLocs[id] = loc;
-            Element ins = insElems[id];
-            int op = ops[id] & 0xFF;
-            String format = opFormat(op, isWide[id]);
-            // Make sure operands fit within the given format.
-            for (int j = 1, jlimit = format.length(); j < jlimit; j++) {
-                char fc = format.charAt(j);
-                int x = 0;
-                switch (fc) {
-                    case 'l':
-                        x = (int) ins.getAttrLong("loc");
-                        assert (x >= 0);
-                        if (x > 0xFF && !isWide[id]) {
-                            isWide[id] = true;
-                            format = opFormat(op, isWide[id]);
-                        }
-                        assert (x <= 0xFFFF);
-                        break;
-                    case 'k':
-                        char fc2 = format.charAt(Math.min(j + 1, format.length() - 1));
-                        x = getCPIndex(ins, fc2, getCPI);
-                        if (x > 0xFF && j == jlimit - 1) {
-                            assert (op == 0x12); //ldc
-                            ops[id] = (byte) (op = 0x13); //ldc_w
-                            format = opFormat(op);
-                        }
-                        assert (x <= 0xFFFF);
-                        j++;  // skip type-of-constant marker
-                        break;
-                    case 'x':
-                        x = (int) ins.getAttrLong("num");
-                        assert (x >= 0 && x <= ((j == jlimit - 1) ? 0xFF : 0xFFFF));
-                        break;
-                    case 's':
-                        x = (int) ins.getAttrLong("num");
-                        if (x != (byte) x && j == jlimit - 1) {
-                            switch (op) {
-                                case 0x10: //bipush
-                                    ops[id] = (byte) (op = 0x11); //sipush
-                                    break;
-                                case 0x84: //iinc
-                                    isWide[id] = true;
-                                    format = opFormat(op, isWide[id]);
-                                    break;
-                                default:
-                                    assert (false);  // cannot lengthen
-                            }
-                        }
-                        // unsign the value now, to make later steps clearer
-                        if (j == jlimit - 1) {
-                            assert (x == (byte) x);
-                            x = x & 0xFF;
-                        } else {
-                            assert (x == (short) x);
-                            x = x & 0xFFFF;
-                        }
-                        break;
-                    case 'o':
-                        assert (branches[bn] == id);
-                        bn++;
-                        // make local copies of the branches, and fix up labels
-                        insElems[id] = ins = new Element(ins);
-                        String newLab = labels.get(ins.getAttr("lab"));
-                        assert (newLab != null);
-                        ins.setAttr("lab", newLab);
-                        int prevCas = 0;
-                        int k = 0;
-                        for (Element cas : ins.elements()) {
-                            assert (cas.getName().equals("Case"));
-                            ins.set(k++, cas = new Element(cas));
-                            newLab = labels.get(cas.getAttr("lab"));
-                            assert (newLab != null);
-                            cas.setAttr("lab", newLab);
-                            int thisCas = (int) cas.getAttrLong("num");
-                            assert (op == 0xab
-                                    || op == 0xaa && (k == 0 || thisCas == prevCas + 1));
-                            prevCas = thisCas;
-                        }
-                        break;
-                    case 't':
-                        // switch table is represented as Switch.Case sub-elements
-                        break;
-                    default:
-                        assert (false);
-                }
-                operands[id] = x;  // record operand (last if there are 2)
-                // skip redundant chars
-                while (j + 1 < jlimit && format.charAt(j + 1) == fc) {
-                    ++j;
-                }
-            }
-
-            switch (op) {
-                case 0xaa: //tableswitch
-                    loc = switchBase(loc);
-                    loc += 4 * (3 + ins.size());
-                    break;
-                case 0xab: //lookupswitch
-                    loc = switchBase(loc);
-                    loc += 4 * (2 + 2 * ins.size());
-                    break;
-                default:
-                    if (isWide[id]) {
-                        loc++;  // 'wide' opcode prefix
-                    }
-                    loc += format.length();
-                    break;
-            }
-        }
-        insLocs[insCount] = loc;
-
-        // compute branch offsets, and see if any branches need expansion
-        for (int maxTries = 9, tries = 0;; ++tries) {
-            boolean overflowing = false;
-            boolean[] branchExpansions = null;
-            for (int bn = 0; bn < branches.length - 1; bn++) {
-                int id = branches[bn];
-                Element ins = insElems[id];
-                int insSize = insLocs[id + 1] - insLocs[id];
-                int origin = insLocs[id];
-                int target = insLocs[(int) ins.getAttrLong("lab")];
-                int offset = target - origin;
-                operands[id] = offset;
-                //System.out.println("branch id="+id+" len="+insSize+" to="+target+" offset="+offset);
-                assert (insSize == GOTO_LEN || insSize == GOTO_W_LEN || ins.getName().indexOf("switch") > 0);
-                boolean thisOverflow = (insSize == GOTO_LEN && (offset != (short) offset));
-                if (thisOverflow && !overflowing) {
-                    overflowing = true;
-                    branchExpansions = new boolean[branches.length];
-                }
-                if (thisOverflow || tries == maxTries - 1) {
-                    // lengthen the branch
-                    assert (!(thisOverflow && isWide[id]));
-                    isWide[id] = true;
-                    branchExpansions[bn] = true;
-                }
-            }
-            if (!overflowing) {
-                break;  // done, usually on first try
-            }
-            assert (tries <= maxTries);
-
-            // Walk over all instructions, expanding branches and updating locations.
-            int fixup = 0;
-            for (int bn = 0, id = 0; id < insCount; id++) {
-                insLocs[id] += fixup;
-                if (branches[bn] == id) {
-                    int op = ops[id] & 0xFF;
-                    int wop;
-                    boolean invert;
-                    if (branchExpansions[bn]) {
-                        switch (op) {
-                            case GOTO: //0xa7
-                                wop = GOTO_W; //0xc8
-                                invert = false;
-                                break;
-                            case 0xa8: //jsr
-                                wop = 0xc9; //jsr_w
-                                invert = false;
-                                break;
-                            default:
-                                wop = invertBranchOp(op);
-                                invert = true;
-                                break;
-                        }
-                        assert (op != wop);
-                        ops[id] = (byte) wop;
-                        isWide[id] = invert;
-                        if (invert) {
-                            fixup += GOTO_W_LEN;  //branch around a wide goto
-                        } else {
-                            fixup += (GOTO_W_LEN - GOTO_LEN);
-                        }
-                        // done expanding:  ops and isWide reflect the decision
-                    }
-                    bn++;
-                }
-            }
-            insLocs[insCount] += fixup;
-        }
-        // we know the layout now
-
-        // notify the caller of offsets, if requested
-        if (elemToIndexMap != null) {
-            for (int i = 0; i < elemToIndexMap.length; i++) {
-                int id = elemToIndexMap[i];
-                if (id >= 0) {
-                    Element ins = (Element) instructions.get(i);
-                    ins.setAttr(pcAttrName, "" + insLocs[id]);
-                }
-            }
-            elemToIndexMap = null;  // release the pointer
-        }
-
-        // output the bytes
-        StringBuffer sbuf = new StringBuffer(insLocs[insCount]);
-        for (int bn = 0, id = 0; id < insCount; id++) {
-            //System.out.println("output id="+id+" loc="+insLocs[id]+" len="+(insLocs[id+1]-insLocs[id])+" #sbuf="+sbuf.length());
-            assert (sbuf.length() == insLocs[id]);
-            Element ins;
-            int pc = insLocs[id];
-            int nextpc = insLocs[id + 1];
-            int op = ops[id] & 0xFF;
-            int opnd = operands[id];
-            String format;
-            if (branches[bn] == id) {
-                bn++;
-                sbuf.append((char) op);
-                if (isWide[id]) {
-                    // emit <ifop lab=1f> <goto_w target> <label pc=1f>
-                    int target = pc + opnd;
-                    putInt(sbuf, nextpc - pc, -2);
-                    assert (sbuf.length() == pc + GOTO_LEN);
-                    sbuf.append((char) GOTO_W);
-                    putInt(sbuf, target - (pc + GOTO_LEN), 4);
-                } else if (op == 0xaa || //tableswitch
-                        op == 0xab) {  //lookupswitch
-                    ins = insElems[id];
-                    for (int pad = switchBase(pc) - (pc + 1); pad > 0; pad--) {
-                        sbuf.append((char) 0);
-                    }
-                    assert (pc + opnd == insLocs[(int) ins.getAttrLong("lab")]);
-                    putInt(sbuf, opnd, 4); // default label
-                    if (op == 0xaa) {  //tableswitch
-                        Element cas0 = (Element) ins.get(0);
-                        int lowCase = (int) cas0.getAttrLong("num");
-                        Element casN = (Element) ins.get(ins.size() - 1);
-                        int highCase = (int) casN.getAttrLong("num");
-                        assert (highCase - lowCase + 1 == ins.size());
-                        putInt(sbuf, lowCase, 4);
-                        putInt(sbuf, highCase, 4);
-                        int caseForAssert = lowCase;
-                        for (Element cas : ins.elements()) {
-                            int target = insLocs[(int) cas.getAttrLong("lab")];
-                            assert (cas.getAttrLong("num") == caseForAssert++);
-                            putInt(sbuf, target - pc, 4);
-                        }
-                    } else {  //lookupswitch
-                        int caseCount = ins.size();
-                        putInt(sbuf, caseCount, 4);
-                        for (Element cas : ins.elements()) {
-                            int target = insLocs[(int) cas.getAttrLong("lab")];
-                            putInt(sbuf, (int) cas.getAttrLong("num"), 4);
-                            putInt(sbuf, target - pc, 4);
-                        }
-                    }
-                    assert (nextpc == sbuf.length());
-                } else {
-                    putInt(sbuf, opnd, -(nextpc - (pc + 1)));
-                }
-            } else if (nextpc == pc + 1) {
-                // a single-byte instruction
-                sbuf.append((char) op);
-            } else {
-                // picky stuff
-                boolean wide = isWide[id];
-                if (wide) {
-                    sbuf.append((char) WIDE);
-                    pc++;
-                }
-                sbuf.append((char) op);
-                int opnd1;
-                int opnd2 = opnd;
-                switch (op) {
-                    case 0x84:  //iinc
-                        ins = insElems[id];
-                        opnd1 = (int) ins.getAttrLong("loc");
-                        if (isWide[id]) {
-                            putInt(sbuf, opnd1, 2);
-                            putInt(sbuf, opnd2, 2);
-                        } else {
-                            putInt(sbuf, opnd1, 1);
-                            putInt(sbuf, opnd2, 1);
-                        }
-                        break;
-                    case 0xc5: //multianewarray
-                        ins = insElems[id];
-                        opnd1 = getCPIndex(ins, 'c', getCPI);
-                        putInt(sbuf, opnd1, 2);
-                        putInt(sbuf, opnd2, 1);
-                        break;
-                    case 0xb9: //invokeinterface
-                        ins = insElems[id];
-                        opnd1 = getCPIndex(ins, 'n', getCPI);
-                        putInt(sbuf, opnd1, 2);
-                        opnd2 = (int) ins.getAttrLong("num");
-                        if (opnd2 == 0) {
-                            opnd2 = ClassSyntax.computeInterfaceNum(ins.getAttr("val"));
-                        }
-                        putInt(sbuf, opnd2, 2);
-                        break;
-                    default:
-                        // put the single operand and be done
-                        putInt(sbuf, opnd, nextpc - (pc + 1));
-                        break;
-                }
-            }
-        }
-        assert (sbuf.length() == insLocs[insCount]);
-
-        return sbuf.toString();
-    }
-
-    static int getCPIndex(Element ins, char ctype,
-            ClassSyntax.GetCPIndex getCPI) {
-        int x = (int) ins.getAttrLong("ref");
-        if (x == 0 && getCPI != null) {
-            String val = ins.getAttr("val");
-            if (val == null || val.equals("")) {
-                val = ins.getText().toString();
-            }
-            byte tag;
-            switch (ctype) {
-                case 'k':
-                    tag = (byte) ins.getAttrLong("tag");
-                    break;
-                case 'c':
-                    tag = ClassSyntax.CONSTANT_Class;
-                    break;
-                case 'f':
-                    tag = ClassSyntax.CONSTANT_Fieldref;
-                    break;
-                case 'm':
-                    tag = ClassSyntax.CONSTANT_Methodref;
-                    break;
-                case 'n':
-                    tag = ClassSyntax.CONSTANT_InterfaceMethodref;
-                    break;
-                default:
-                    throw new Error("bad ctype " + ctype + " in " + ins);
-            }
-            x = getCPI.getCPIndex(tag, val);
-            //System.out.println("getCPIndex "+ins+" => "+tag+"/"+val+" => "+x);
-        } else {
-            assert (x > 0);
-        }
-        return x;
-    }
-
-    static void putInt(StringBuffer sbuf, int x, int len) {
-        //System.out.println("putInt x="+x+" len="+len);
-        boolean isSigned = false;
-        if (len < 0) {
-            len = -len;
-            isSigned = true;
-        }
-        assert (len == 1 || len == 2 || len == 4);
-        int insig = ((4 - len) * 8);  // how many insignificant bits?
-        int sx = x << insig;
-        ;
-        assert (x == (isSigned ? (sx >> insig) : (sx >>> insig)));
-        for (int i = 0; i < len; i++) {
-            sbuf.append((char) (sx >>> 24));
-            sx <<= 8;
-        }
-    }
-}
--- a/jdk/test/tools/pack200/pack200-verifier/src/xmlkit/InstructionSyntax.java	Wed Jul 05 18:09:43 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,483 +0,0 @@
-/*
- * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package xmlkit; // -*- mode: java; indent-tabs-mode: nil -*-
-
-import xmlkit.XMLKit.Element;
-import java.util.HashMap;
-import java.util.Map;
-/*
- * @author jrose
- */
-public abstract class InstructionSyntax {
-
-    InstructionSyntax() {
-    }
-    static final String[] bcNames;
-    static final String[] bcFormats;
-    static final String[] bcWideFormats;
-    static final HashMap<String, Integer> bcCodes;
-    static final HashMap<String, Element> abbrevs;
-    static final HashMap<Element, String> rabbrevs;
-
-    static {
-        TokenList tl = new TokenList(
-                " nop aconst_null iconst_m1 iconst_0 iconst_1 iconst_2 iconst_3"
-                + " iconst_4 iconst_5 lconst_0 lconst_1 fconst_0 fconst_1 fconst_2"
-                + " dconst_0 dconst_1 bipush/s sipush/ss ldc/k ldc_w/kk ldc2_w/kk"
-                + " iload/wl lload/wl fload/wl dload/wl aload/wl iload_0 iload_1"
-                + " iload_2 iload_3 lload_0 lload_1 lload_2 lload_3 fload_0 fload_1"
-                + " fload_2 fload_3 dload_0 dload_1 dload_2 dload_3 aload_0 aload_1"
-                + " aload_2 aload_3 iaload laload faload daload aaload baload caload"
-                + " saload istore/wl lstore/wl fstore/wl dstore/wl astore/wl"
-                + " istore_0 istore_1 istore_2 istore_3 lstore_0 lstore_1 lstore_2"
-                + " lstore_3 fstore_0 fstore_1 fstore_2 fstore_3 dstore_0 dstore_1"
-                + " dstore_2 dstore_3 astore_0 astore_1 astore_2 astore_3 iastore"
-                + " lastore fastore dastore aastore bastore castore sastore pop pop2"
-                + " dup dup_x1 dup_x2 dup2 dup2_x1 dup2_x2 swap iadd ladd fadd dadd"
-                + " isub lsub fsub dsub imul lmul fmul dmul idiv ldiv fdiv ddiv irem"
-                + " lrem frem drem ineg lneg fneg dneg ishl lshl ishr lshr iushr"
-                + " lushr iand land ior lor ixor lxor iinc/wls i2l i2f i2d l2i l2f"
-                + " l2d f2i f2l f2d d2i d2l d2f i2b i2c i2s lcmp fcmpl fcmpg dcmpl"
-                + " dcmpg ifeq/oo ifne/oo iflt/oo ifge/oo ifgt/oo ifle/oo"
-                + " if_icmpeq/oo if_icmpne/oo if_icmplt/oo if_icmpge/oo if_icmpgt/oo"
-                + " if_icmple/oo if_acmpeq/oo if_acmpne/oo goto/oo jsr/oo ret/wl"
-                + " tableswitch/oooot lookupswitch/oooot ireturn lreturn freturn dreturn areturn"
-                + " return getstatic/kf putstatic/kf getfield/kf putfield/kf"
-                + " invokevirtual/km invokespecial/km invokestatic/km"
-                + " invokeinterface/knxx xxxunusedxxx new/kc newarray/x anewarray/kc"
-                + " arraylength athrow checkcast/kc instanceof/kc monitorenter"
-                + " monitorexit wide multianewarray/kcx ifnull/oo ifnonnull/oo"
-                + " goto_w/oooo jsr_w/oooo");
-        assert (tl.size() == 202);  // this many instructions!
-        HashMap<String, Integer> map = new HashMap<String, Integer>(tl.size());
-        String[] names = tl.toArray(new String[tl.size()]);
-        String[] formats = new String[names.length];
-        String[] wideFormats = new String[names.length];
-        StringBuilder sbuf = new StringBuilder();
-        sbuf.append('i');  // all op formats begin with "i"
-        int i = 0;
-        for (String ins : names) {
-            assert (ins == ins.trim());  // no whitespace
-            int sfx = ins.indexOf('/');
-            String format = "i";
-            String wideFormat = null;
-            if (sfx >= 0) {
-                format = ins.substring(sfx + 1);
-                ins = ins.substring(0, sfx);
-                if (format.charAt(0) == 'w') {
-                    format = format.substring(1);
-                    sbuf.setLength(1);
-                    for (int j = 0; j < format.length(); j++) {
-                        // double everything except the initial 'i'
-                        sbuf.append(format.charAt(j));
-                        sbuf.append(format.charAt(j));
-                    }
-                    wideFormat = sbuf.toString().intern();
-                }
-                sbuf.setLength(1);
-                sbuf.append(format);
-                format = sbuf.toString().intern();
-            }
-            ins = ins.intern();
-            names[i] = ins;
-            formats[i] = format;
-            wideFormats[i] = (wideFormat != null) ? wideFormat : format;
-            //System.out.println(ins+" "+format+" "+wideFormat);
-            map.put(ins, i++);
-        }
-        //map = Collections.unmodifiableMap(map);
-
-        HashMap<String, Element> abb = new HashMap<String, Element>(tl.size() / 2);
-        abb.put("iconst_m1", new Element("bipush", "num", "-1"));
-        for (String ins : names) {
-            int sfx = ins.indexOf('_');
-            if (sfx >= 0 && Character.isDigit(ins.charAt(sfx + 1))) {
-                String pfx = ins.substring(0, sfx).intern();
-                String num = ins.substring(sfx + 1);
-                String att = pfx.endsWith("const") ? "num" : "loc";
-                Element exp = new Element(pfx, att, num).deepFreeze();
-                abb.put(ins, exp);
-            }
-        }
-        //abb = Collections.unmodifiableMap(abb);
-        HashMap<Element, String> rabb = new HashMap<Element, String>(tl.size() / 2);
-        for (Map.Entry<String, Element> e : abb.entrySet()) {
-            rabb.put(e.getValue(), e.getKey());
-        }
-        //rabb = Collections.unmodifiableMap(rabb);
-
-
-        bcNames = names;
-        bcFormats = formats;
-        bcWideFormats = wideFormats;
-        bcCodes = map;
-        abbrevs = abb;
-        rabbrevs = rabb;
-    }
-
-    public static String opName(int op) {
-        if (op >= 0 && op < bcNames.length) {
-            return bcNames[op];
-        }
-        return "unknown#" + op;
-    }
-
-    public static String opFormat(int op) {
-        return opFormat(op, false);
-    }
-
-    public static String opFormat(int op, boolean isWide) {
-        if (op >= 0 && op < bcFormats.length) {
-            return (isWide ? bcWideFormats[op] : bcFormats[op]);
-        }
-        return "?";
-    }
-
-    public static int opCode(String opName) {
-        Integer op = (Integer) bcCodes.get(opName);
-        if (op != null) {
-            return op.intValue();
-        }
-        return -1;
-    }
-
-    public static Element expandAbbrev(String opName) {
-        return abbrevs.get(opName);
-    }
-
-    public static String findAbbrev(Element op) {
-        return rabbrevs.get(op);
-    }
-
-    public static int invertBranchOp(int op) {
-        assert (opFormat(op).indexOf('o') >= 0);
-        final int IFMIN = 0x99;
-        final int IFMAX = 0xa6;
-        final int IFMIN2 = 0xc6;
-        final int IFMAX2 = 0xc7;
-        assert (bcNames[IFMIN] == "ifeq");
-        assert (bcNames[IFMAX] == "if_acmpne");
-        assert (bcNames[IFMIN2] == "ifnonnull");
-        assert (bcNames[IFMAX2] == "ifnull");
-        int rop;
-        if (op >= IFMIN && op <= IFMAX) {
-            rop = IFMIN + ((op - IFMIN) ^ 1);
-        } else if (op >= IFMIN2 && op <= IFMAX2) {
-            rop = IFMIN2 + ((op - IFMIN2) ^ 1);
-        } else {
-            assert (false);
-            rop = op;
-        }
-        assert (opFormat(rop).indexOf('o') >= 0);
-        return rop;
-    }
-
-    public static Element parse(String bytes) {
-        Element e = new Element("Instructions", bytes.length());
-        boolean willBeWide;
-        boolean isWide = false;
-        Element[] tempMap = new Element[bytes.length()];
-        for (int pc = 0, nextpc; pc < bytes.length(); pc = nextpc) {
-            int op = bytes.charAt(pc);
-            Element i = new Element(opName(op));
-
-            nextpc = pc + 1;
-            int locarg = 0;
-            int cparg = 0;
-            int intarg = 0;
-            int labelarg = 0;
-
-            willBeWide = false;
-            switch (op) {
-                case 0xc4: //wide
-                    willBeWide = true;
-                    break;
-                case 0x10: //bipush
-                    intarg = nextpc++;
-                    intarg *= -1;  //mark signed
-                    break;
-                case 0x11: //sipush
-                    intarg = nextpc;
-                    nextpc += 2;
-                    intarg *= -1;  //mark signed
-                    break;
-                case 0x12: //ldc
-                    cparg = nextpc++;
-                    break;
-                case 0x13: //ldc_w
-                case 0x14: //ldc2_w
-                case 0xb2: //getstatic
-                case 0xb3: //putstatic
-                case 0xb4: //getfield
-                case 0xb5: //putfield
-                case 0xb6: //invokevirtual
-                case 0xb7: //invokespecial
-                case 0xb8: //invokestatic
-                case 0xbb: //new
-                case 0xbd: //anewarray
-                case 0xc0: //checkcast
-                case 0xc1: //instanceof
-                    cparg = nextpc;
-                    nextpc += 2;
-                    break;
-                case 0xb9: //invokeinterface
-                    cparg = nextpc;
-                    nextpc += 2;
-                    intarg = nextpc;
-                    nextpc += 2;
-                    break;
-                case 0xc5: //multianewarray
-                    cparg = nextpc;
-                    nextpc += 2;
-                    intarg = nextpc++;
-                    break;
-                case 0x15: //iload
-                case 0x16: //lload
-                case 0x17: //fload
-                case 0x18: //dload
-                case 0x19: //aload
-                case 0x36: //istore
-                case 0x37: //lstore
-                case 0x38: //fstore
-                case 0x39: //dstore
-                case 0x3a: //astore
-                case 0xa9: //ret
-                    locarg = nextpc++;
-                    if (isWide) {
-                        nextpc++;
-                    }
-                    break;
-                case 0x84: //iinc
-                    locarg = nextpc++;
-                    if (isWide) {
-                        nextpc++;
-                    }
-                    intarg = nextpc++;
-                    if (isWide) {
-                        nextpc++;
-                    }
-                    intarg *= -1;  //mark signed
-                    break;
-                case 0x99: //ifeq
-                case 0x9a: //ifne
-                case 0x9b: //iflt
-                case 0x9c: //ifge
-                case 0x9d: //ifgt
-                case 0x9e: //ifle
-                case 0x9f: //if_icmpeq
-                case 0xa0: //if_icmpne
-                case 0xa1: //if_icmplt
-                case 0xa2: //if_icmpge
-                case 0xa3: //if_icmpgt
-                case 0xa4: //if_icmple
-                case 0xa5: //if_acmpeq
-                case 0xa6: //if_acmpne
-                case 0xa7: //goto
-                case 0xa8: //jsr
-                    labelarg = nextpc;
-                    nextpc += 2;
-                    break;
-                case 0xbc: //newarray
-                    intarg = nextpc++;
-                    break;
-                case 0xc6: //ifnull
-                case 0xc7: //ifnonnull
-                    labelarg = nextpc;
-                    nextpc += 2;
-                    break;
-                case 0xc8: //goto_w
-                case 0xc9: //jsr_w
-                    labelarg = nextpc;
-                    nextpc += 4;
-                    break;
-
-                // save the best for last:
-                case 0xaa: //tableswitch
-                    nextpc = parseSwitch(bytes, pc, true, i);
-                    break;
-                case 0xab: //lookupswitch
-                    nextpc = parseSwitch(bytes, pc, false, i);
-                    break;
-            }
-
-            String format = null;
-            assert ((format = opFormat(op, isWide)) != null);
-            //System.out.println("pc="+pc+" len="+(nextpc - pc)+" w="+isWide+" op="+op+" name="+opName(op)+" format="+format);
-            assert ((nextpc - pc) == format.length() || format.indexOf('t') >= 0);
-
-            // Parse out instruction fields.
-            if (locarg != 0) {
-                int len = nextpc - locarg;
-                if (intarg != 0) {
-                    len /= 2;  // split
-                }
-                i.setAttr("loc", "" + getInt(bytes, locarg, len));
-                assert ('l' == format.charAt(locarg - pc + 0));
-                assert ('l' == format.charAt(locarg - pc + len - 1));
-            }
-            if (cparg != 0) {
-                int len = nextpc - cparg;
-                if (len > 2) {
-                    len = 2;
-                }
-                i.setAttr("ref", "" + getInt(bytes, cparg, len));
-                assert ('k' == format.charAt(cparg - pc + 0));
-            }
-            if (intarg != 0) {
-                boolean isSigned = (intarg < 0);
-                if (isSigned) {
-                    intarg *= -1;
-                }
-                int len = nextpc - intarg;
-                i.setAttr("num", "" + getInt(bytes, intarg, isSigned ? -len : len));
-                assert ((isSigned ? 's' : 'x') == format.charAt(intarg - pc + 0));
-                assert ((isSigned ? 's' : 'x') == format.charAt(intarg - pc + len - 1));
-            }
-            if (labelarg != 0) {
-                int len = nextpc - labelarg;
-                int offset = getInt(bytes, labelarg, -len);
-                int target = pc + offset;
-                i.setAttr("lab", "" + target);
-                assert ('o' == format.charAt(labelarg - pc + 0));
-                assert ('o' == format.charAt(labelarg - pc + len - 1));
-            }
-
-            e.add(i);
-            tempMap[pc] = i;
-            isWide = willBeWide;
-        }
-
-        // Mark targets of branches.
-        for (Element i : e.elements()) {
-            for (int j = -1; j < i.size(); j++) {
-                Element c = (j < 0) ? i : (Element) i.get(j);
-                Number targetNum = c.getAttrNumber("lab");
-                if (targetNum != null) {
-                    int target = targetNum.intValue();
-                    Element ti = null;
-                    if (target >= 0 && target < tempMap.length) {
-                        ti = tempMap[target];
-                    }
-                    if (ti != null) {
-                        ti.setAttr("pc", "" + target);
-                    } else {
-                        c.setAttr("lab.error", "");
-                    }
-                }
-            }
-        }
-
-        // Shrink to fit:
-        for (Element i : e.elements()) {
-            i.trimToSize();
-        }
-        e.trimToSize();
-
-        /*
-        String assem = assemble(e);
-        if (!assem.equals(bytes)) {
-        System.out.println("Bytes: "+bytes);
-        System.out.println("Insns: "+e);
-        System.out.println("Assem: "+parse(assem));
-        }
-         */
-
-        return e;
-    }
-
-    static int switchBase(int pc) {
-        int apc = pc + 1;
-        apc += (-apc) & 3;
-        return apc;
-    }
-
-    static int parseSwitch(String s, int pc, boolean isTable, Element i) {
-        int apc = switchBase(pc);
-        int defLabel = pc + getInt(s, apc + 4 * 0, 4);
-        i.setAttr("lab", "" + defLabel);
-        if (isTable) {
-            int lowCase = getInt(s, apc + 4 * 1, 4);
-            int highCase = getInt(s, apc + 4 * 2, 4);
-            int caseCount = highCase - lowCase + 1;
-            for (int n = 0; n < caseCount; n++) {
-                Element c = new Element("Case", 4);
-                int caseVal = lowCase + n;
-                int caseLab = getInt(s, apc + 4 * (3 + n), 4) + pc;
-                c.setAttr("num", "" + caseVal);
-                c.setAttr("lab", "" + caseLab);
-                assert (c.getExtraCapacity() == 0);
-                i.add(c);
-            }
-            return apc + 4 * (3 + caseCount);
-        } else {
-            int caseCount = getInt(s, apc + 4 * 1, 4);
-            for (int n = 0; n < caseCount; n++) {
-                Element c = new Element("Case", 4);
-                int caseVal = getInt(s, apc + 4 * (2 + (2 * n) + 0), 4);
-                int caseLab = getInt(s, apc + 4 * (2 + (2 * n) + 1), 4) + pc;
-                c.setAttr("num", "" + caseVal);
-                c.setAttr("lab", "" + caseLab);
-                assert (c.getExtraCapacity() == 0);
-                i.add(c);
-            }
-            return apc + 4 * (2 + 2 * caseCount);
-        }
-    }
-
-    static int getInt(String s, int pc, int len) {
-        //System.out.println("getInt s["+s.length()+"] pc="+pc+" len="+len);
-        int result = s.charAt(pc);
-        if (len < 0) {
-            len = -len;
-            result = (byte) result;
-        }
-        if (!(len == 1 || len == 2 || len == 4)) {
-            System.out.println("len=" + len);
-        }
-        assert (len == 1 || len == 2 || len == 4);
-        for (int i = 1; i < len; i++) {
-            result <<= 8;
-            result += s.charAt(pc + i) & 0xFF;
-        }
-        return result;
-    }
-
-    public static String assemble(Element instructions) {
-        return InstructionAssembler.assemble(instructions, null, null);
-    }
-
-    public static String assemble(Element instructions, String pcAttrName) {
-        return InstructionAssembler.assemble(instructions, pcAttrName, null);
-    }
-
-    public static String assemble(Element instructions, ClassSyntax.GetCPIndex getCPI) {
-        return InstructionAssembler.assemble(instructions, null, getCPI);
-    }
-
-    public static String assemble(Element instructions, String pcAttrName,
-            ClassSyntax.GetCPIndex getCPI) {
-        return InstructionAssembler.assemble(instructions, pcAttrName, getCPI);
-    }
-}
--- a/langtools/.hgtags	Wed Jul 05 18:09:43 2017 +0200
+++ b/langtools/.hgtags	Wed Jul 05 18:10:27 2017 +0200
@@ -158,3 +158,4 @@
 6b105afbb77ca9600a99eade31f686d070c70581 jdk8-b34
 defd666a786334465496c8901fa302b779c7e045 jdk8-b35
 94bbaa67686f44a124cd16fd9f1e8a6a3f684d2d jdk8-b36
+5891b38985e8b2502296fc29e726b527d03116d2 jdk8-b37