Merge
authorduke
Wed, 05 Jul 2017 17:04:56 +0200
changeset 4541 0fe45e7e4acc
parent 4540 ae0f40f891d4 (current diff)
parent 4539 1d6644fce2ed (diff)
child 4543 c2c8c97ad733
Merge
jdk/src/share/classes/sun/dyn/util/BytecodeSignature.java
--- a/.hgtags-top-repo	Thu Dec 17 14:10:20 2009 -0800
+++ b/.hgtags-top-repo	Wed Jul 05 17:04:56 2017 +0200
@@ -52,3 +52,4 @@
 d1516b9f23954b29b8e76e6f4efc467c08c78133 jdk7-b75
 c8b63075403d53a208104a8a6ea5072c1cb66aab jdk7-b76
 1f17ca8353babb13f4908c1f87d11508232518c8 jdk7-b77
+ab4ae8f4514693a9fe17ca2fec0239d8f8450d2c jdk7-b78
--- a/hotspot/.hgtags	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/.hgtags	Wed Jul 05 17:04:56 2017 +0200
@@ -52,3 +52,4 @@
 d8dd291a362acb656026a9c0a9da48501505a1e7 jdk7-b75
 9174bb32e934965288121f75394874eeb1fcb649 jdk7-b76
 455105fc81d941482f8f8056afaa7aa0949c9300 jdk7-b77
+e703499b4b51e3af756ae77c3d5e8b3058a14e4e jdk7-b78
--- a/hotspot/make/hotspot_version	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/make/hotspot_version	Wed Jul 05 17:04:56 2017 +0200
@@ -35,7 +35,7 @@
 
 HS_MAJOR_VER=17
 HS_MINOR_VER=0
-HS_BUILD_NUMBER=05
+HS_BUILD_NUMBER=06
 
 JDK_MAJOR_VER=1
 JDK_MINOR_VER=7
--- a/hotspot/make/linux/makefiles/debug.make	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/make/linux/makefiles/debug.make	Wed Jul 05 17:04:56 2017 +0200
@@ -38,7 +38,7 @@
  "Please use 'make jvmg' to build debug JVM.                            \n" \
  "----------------------------------------------------------------------\n")
 
-G_SUFFIX =
+G_SUFFIX = _g
 VERSION = debug
 SYSDEFS += -DASSERT -DDEBUG
 PICFLAGS = DEFAULT
--- a/hotspot/make/linux/makefiles/fastdebug.make	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/make/linux/makefiles/fastdebug.make	Wed Jul 05 17:04:56 2017 +0200
@@ -58,7 +58,7 @@
 # Linker mapfile
 MAPFILE = $(GAMMADIR)/make/linux/makefiles/mapfile-vers-debug
 
-G_SUFFIX =
+G_SUFFIX = _g
 VERSION = optimized
 SYSDEFS += -DASSERT -DFASTDEBUG
 PICFLAGS = DEFAULT
--- a/hotspot/make/linux/makefiles/jsig.make	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/make/linux/makefiles/jsig.make	Wed Jul 05 17:04:56 2017 +0200
@@ -25,9 +25,12 @@
 # Rules to build signal interposition library, used by vm.make
 
 # libjsig[_g].so: signal interposition library
-JSIG = jsig$(G_SUFFIX)
+JSIG = jsig
 LIBJSIG = lib$(JSIG).so
 
+JSIG_G    = $(JSIG)$(G_SUFFIX)
+LIBJSIG_G = lib$(JSIG_G).so
+
 JSIGSRCDIR = $(GAMMADIR)/src/os/$(Platform_os_family)/vm
 
 DEST_JSIG  = $(JDK_LIBDIR)/$(LIBJSIG)
@@ -50,6 +53,7 @@
 	@echo Making signal interposition lib...
 	$(QUIETLY) $(CC) $(SYMFLAG) $(ARCHFLAG) $(SHARED_FLAG) $(PICFLAG) \
                          $(LFLAGS_JSIG) $(JSIG_DEBUG_CFLAGS) -o $@ $< -ldl
+	$(QUIETLY) [ -f $(LIBJSIG_G) ] || { ln -s $@ $(LIBJSIG_G); }
 
 install_jsig: $(LIBJSIG)
 	@echo "Copying $(LIBJSIG) to $(DEST_JSIG)"
--- a/hotspot/make/linux/makefiles/jvmg.make	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/make/linux/makefiles/jvmg.make	Wed Jul 05 17:04:56 2017 +0200
@@ -35,7 +35,7 @@
 # Linker mapfile
 MAPFILE = $(GAMMADIR)/make/linux/makefiles/mapfile-vers-debug
 
-G_SUFFIX =
+G_SUFFIX = _g
 VERSION = debug
 SYSDEFS += -DASSERT -DDEBUG
 PICFLAGS = DEFAULT
--- a/hotspot/make/linux/makefiles/launcher.make	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/make/linux/makefiles/launcher.make	Wed Jul 05 17:04:56 2017 +0200
@@ -25,7 +25,9 @@
 # Rules to build gamma launcher, used by vm.make
 
 # gamma[_g]: launcher
-LAUNCHER = gamma$(G_SUFFIX)
+
+LAUNCHER   = gamma
+LAUNCHER_G = $(LAUNCHER)$(G_SUFFIX)
 
 LAUNCHERDIR   = $(GAMMADIR)/src/os/$(Platform_os_family)/launcher
 LAUNCHERFLAGS = $(ARCHFLAG) \
@@ -70,4 +72,5 @@
 	    $(LINK_LAUNCHER/PRE_HOOK) \
 	    $(LINK_LAUNCHER) $(LFLAGS_LAUNCHER) -o $@ $(LAUNCHER.o) $(LIBS_LAUNCHER); \
 	    $(LINK_LAUNCHER/POST_HOOK) \
+	    [ -f $(LAUNCHER_G) ] || { ln -s $@ $(LAUNCHER_G); }; \
         }
--- a/hotspot/make/linux/makefiles/saproc.make	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/make/linux/makefiles/saproc.make	Wed Jul 05 17:04:56 2017 +0200
@@ -25,9 +25,13 @@
 # Rules to build serviceability agent library, used by vm.make
 
 # libsaproc[_g].so: serviceability agent
-SAPROC = saproc$(G_SUFFIX)
+
+SAPROC = saproc
 LIBSAPROC = lib$(SAPROC).so
 
+SAPROC_G = $(SAPROC)$(G_SUFFIX)
+LIBSAPROC_G = lib$(SAPROC_G).so
+
 AGENT_DIR = $(GAMMADIR)/agent
 
 SASRCDIR = $(AGENT_DIR)/src/os/$(Platform_os_family)
@@ -75,6 +79,7 @@
 	           $(SA_DEBUG_CFLAGS)                                   \
 	           -o $@                                                \
 	           -lthread_db
+	$(QUIETLY) [ -f $(LIBSAPROC_G) ] || { ln -s $@ $(LIBSAPROC_G); }
 
 install_saproc: checkAndBuildSA
 	$(QUIETLY) if [ -e $(LIBSAPROC) ] ; then             \
--- a/hotspot/make/linux/makefiles/vm.make	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/make/linux/makefiles/vm.make	Wed Jul 05 17:04:56 2017 +0200
@@ -113,8 +113,9 @@
 #----------------------------------------------------------------------
 # JVM
 
-JVM    = jvm$(G_SUFFIX)
-LIBJVM = lib$(JVM).so
+JVM      = jvm
+LIBJVM   = lib$(JVM).so
+LIBJVM_G = lib$(JVM)$(G_SUFFIX).so
 
 JVM_OBJ_FILES = $(Obj_Files)
 
@@ -201,6 +202,7 @@
 		       $(LFLAGS_VM) -o $@ $(LIBJVM.o) $(LIBS_VM);       \
 	    $(LINK_LIB.CC/POST_HOOK)                                    \
 	    rm -f $@.1; ln -s $@ $@.1;                                  \
+	    [ -f $(LIBJVM_G) ] || { ln -s $@ $(LIBJVM_G); ln -s $@.1 $(LIBJVM_G).1; }; \
 	    if [ -x /usr/sbin/selinuxenabled ] ; then                   \
 	      /usr/sbin/selinuxenabled;                                 \
               if [ $$? = 0 ] ; then					\
--- a/hotspot/make/solaris/makefiles/debug.make	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/make/solaris/makefiles/debug.make	Wed Jul 05 17:04:56 2017 +0200
@@ -54,7 +54,7 @@
  "Please use 'gnumake jvmg' to build debug JVM.                            \n" \
  "-------------------------------------------------------------------------\n")
 
-G_SUFFIX =
+G_SUFFIX = _g
 VERSION = debug
 SYSDEFS += -DASSERT -DDEBUG
 PICFLAGS = DEFAULT
--- a/hotspot/make/solaris/makefiles/dtrace.make	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/make/solaris/makefiles/dtrace.make	Wed Jul 05 17:04:56 2017 +0200
@@ -24,8 +24,8 @@
 
 # Rules to build jvm_db/dtrace, used by vm.make
 
-# we build libjvm_dtrace/libjvm_db/dtrace for COMPILER1 and COMPILER2
-# but not for CORE configuration
+# We build libjvm_dtrace/libjvm_db/dtrace for COMPILER1 and COMPILER2
+# but not for CORE or KERNEL configurations.
 
 ifneq ("${TYPE}", "CORE")
 ifneq ("${TYPE}", "KERNEL")
@@ -37,12 +37,13 @@
 
 else
 
-
 JVM_DB = libjvm_db
-LIBJVM_DB = libjvm$(G_SUFFIX)_db.so
+LIBJVM_DB = libjvm_db.so
+LIBJVM_DB_G = libjvm$(G_SUFFIX)_db.so
 
 JVM_DTRACE = jvm_dtrace
-LIBJVM_DTRACE = libjvm$(G_SUFFIX)_dtrace.so
+LIBJVM_DTRACE = libjvm_dtrace.so
+LIBJVM_DTRACE_G = libjvm$(G_SUFFIX)_dtrace.so
 
 JVMOFFS = JvmOffsets
 JVMOFFS.o = $(JVMOFFS).o
@@ -77,7 +78,7 @@
 LFLAGS_JVM_DTRACE += -D_REENTRANT $(PICFLAG)
 else
 LFLAGS_JVM_DB += -mt $(PICFLAG) -xnolib
-LFLAGS_JVM_DTRACE += -mt $(PICFLAG) -xnolib
+LFLAGS_JVM_DTRACE += -mt $(PICFLAG) -xnolib -ldl
 endif
 
 ISA = $(subst i386,i486,$(shell isainfo -n))
@@ -86,18 +87,24 @@
 ifneq ("${ISA}","${BUILDARCH}")
 
 XLIBJVM_DB = 64/$(LIBJVM_DB)
+XLIBJVM_DB_G = 64/$(LIBJVM_DB_G)
 XLIBJVM_DTRACE = 64/$(LIBJVM_DTRACE)
+XLIBJVM_DTRACE_G = 64/$(LIBJVM_DTRACE_G)
 
 $(XLIBJVM_DB): $(DTRACE_SRCDIR)/$(JVM_DB).c $(JVMOFFS).h $(LIBJVM_DB_MAPFILE)
 	@echo Making $@
 	$(QUIETLY) mkdir -p 64/ ; \
 	$(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); }
+
 $(XLIBJVM_DTRACE): $(DTRACE_SRCDIR)/$(JVM_DTRACE).c $(DTRACE_SRCDIR)/$(JVM_DTRACE).h $(LIBJVM_DTRACE_MAPFILE)
 	@echo Making $@
 	$(QUIETLY) mkdir -p 64/ ; \
 	$(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); }
+
 endif # ifneq ("${ISA}","${BUILDARCH}")
 
 ifdef USE_GCC
@@ -142,11 +149,13 @@
 	@echo Making $@
 	$(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); }
 
 $(LIBJVM_DTRACE): $(DTRACE_SRCDIR)/$(JVM_DTRACE).c $(XLIBJVM_DTRACE) $(DTRACE_SRCDIR)/$(JVM_DTRACE).h $(LIBJVM_DTRACE_MAPFILE)
 	@echo Making $@
 	$(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); }
 
 $(DTRACE).d: $(DTRACE_SRCDIR)/hotspot.d $(DTRACE_SRCDIR)/hotspot_jni.d \
              $(DTRACE_SRCDIR)/hs_private.d $(DTRACE_SRCDIR)/jhelper.d
--- a/hotspot/make/solaris/makefiles/fastdebug.make	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/make/solaris/makefiles/fastdebug.make	Wed Jul 05 17:04:56 2017 +0200
@@ -90,7 +90,6 @@
 # for this method for now. (fix this when dtrace bug 6258412 is fixed)
 OPT_CFLAGS/ciEnv.o = $(OPT_CFLAGS) -xinline=no%__1cFciEnvbFpost_compiled_method_load_event6MpnHnmethod__v_
 
-
 # (OPT_CFLAGS/SLOWER is also available, to alter compilation of buggy files)
 
 # If you set HOTSPARC_GENERIC=yes, you disable all OPT_CFLAGS settings
@@ -115,8 +114,7 @@
 # and mustn't be otherwise.
 MAPFILE_DTRACE = $(GAMMADIR)/make/solaris/makefiles/mapfile-vers-$(TYPE)
 
-
-G_SUFFIX =
+G_SUFFIX = _g
 VERSION = optimized
 SYSDEFS += -DASSERT -DFASTDEBUG -DCHECK_UNHANDLED_OOPS
 PICFLAGS = DEFAULT
--- a/hotspot/make/solaris/makefiles/jsig.make	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/make/solaris/makefiles/jsig.make	Wed Jul 05 17:04:56 2017 +0200
@@ -25,8 +25,11 @@
 # Rules to build signal interposition library, used by vm.make
 
 # libjsig[_g].so: signal interposition library
-JSIG = jsig$(G_SUFFIX)
-LIBJSIG = lib$(JSIG).so
+JSIG      = jsig
+LIBJSIG   = lib$(JSIG).so
+
+JSIG_G    = $(JSIG)$(G_SUFFIX)
+LIBJSIG_G = lib$(JSIG_G).so
 
 JSIGSRCDIR = $(GAMMADIR)/src/os/$(Platform_os_family)/vm
 
@@ -46,6 +49,7 @@
 	@echo Making signal interposition lib...
 	$(QUIETLY) $(CC) $(SYMFLAG) $(ARCHFLAG) $(SHARED_FLAG) $(PICFLAG) \
                          $(LFLAGS_JSIG) -o $@ $< -ldl
+	[ -f $(LIBJSIG_G) ] || { ln -s $@ $(LIBJSIG_G); }
 
 install_jsig: $(LIBJSIG)
 	@echo "Copying $(LIBJSIG) to $(DEST_JSIG)"
--- a/hotspot/make/solaris/makefiles/jvmg.make	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/make/solaris/makefiles/jvmg.make	Wed Jul 05 17:04:56 2017 +0200
@@ -51,7 +51,7 @@
 # and mustn't be otherwise.
 MAPFILE_DTRACE = $(GAMMADIR)/make/solaris/makefiles/mapfile-vers-$(TYPE)
 
-G_SUFFIX =
+G_SUFFIX = _g
 VERSION = debug
 SYSDEFS += -DASSERT -DDEBUG
 PICFLAGS = DEFAULT
--- a/hotspot/make/solaris/makefiles/launcher.make	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/make/solaris/makefiles/launcher.make	Wed Jul 05 17:04:56 2017 +0200
@@ -25,7 +25,8 @@
 # Rules to build gamma launcher, used by vm.make
 
 # gamma[_g]: launcher
-LAUNCHER = gamma$(G_SUFFIX)
+LAUNCHER   = gamma
+LAUNCHER_G = $(LAUNCHER)$(G_SUFFIX)
 
 LAUNCHERDIR   = $(GAMMADIR)/src/os/$(Platform_os_family)/launcher
 LAUNCHERFLAGS = $(ARCHFLAG) \
@@ -88,5 +89,6 @@
 	    $(LINK_LAUNCHER/PRE_HOOK) \
 	    $(LINK_LAUNCHER) $(LFLAGS_LAUNCHER) -o $@ $(LAUNCHER.o) $(LIBS_LAUNCHER); \
 	    $(LINK_LAUNCHER/POST_HOOK) \
+	    [ -f $(LAUNCHER_G) ] || { ln -s $@ $(LAUNCHER_G); }; \
 	    ;; \
 	esac
--- a/hotspot/make/solaris/makefiles/saproc.make	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/make/solaris/makefiles/saproc.make	Wed Jul 05 17:04:56 2017 +0200
@@ -25,9 +25,13 @@
 # Rules to build serviceability agent library, used by vm.make
 
 # libsaproc[_g].so: serviceability agent
-SAPROC = saproc$(G_SUFFIX)
+
+SAPROC = saproc
 LIBSAPROC = lib$(SAPROC).so
 
+SAPROC_G = $(SAPROC)$(G_SUFFIX)
+LIBSAPROC_G = lib$(SAPROC_G).so
+
 AGENT_DIR = $(GAMMADIR)/agent
 
 SASRCDIR = $(AGENT_DIR)/src/os/$(Platform_os_family)/proc
@@ -69,6 +73,7 @@
 	           $(SA_LFLAGS)                                         \
 	           -o $@                                                \
 	           -ldl -ldemangle -lthread -lc
+	[ -f $(LIBSAPROC_G) ] || { ln -s $@ $(LIBSAPROC_G); }
 
 install_saproc: checkAndBuildSA
 	$(QUIETLY) if [ -f $(LIBSAPROC) ] ; then             \
--- a/hotspot/make/solaris/makefiles/sparcWorks.make	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/make/solaris/makefiles/sparcWorks.make	Wed Jul 05 17:04:56 2017 +0200
@@ -281,8 +281,6 @@
 OPT_CFLAGS=-xO4 $(EXTRA_OPT_CFLAGS)
 endif
 
-CFLAGS += $(GAMMADIR)/src/os_cpu/solaris_sparc/vm/solaris_sparc.il
-
 endif # sparc
 
 ifeq ("${Platform_arch_model}", "x86_32")
@@ -293,13 +291,14 @@
 # [phh] Is this still true for 6.1?
 OPT_CFLAGS+=-xO3
 
-CFLAGS += $(GAMMADIR)/src/os_cpu/solaris_x86/vm/solaris_x86_32.il
-
 endif # 32bit x86
 
 # no more exceptions
 CFLAGS/NOEX=-noex
 
+# Inline functions
+CFLAGS += $(GAMMADIR)/src/os_cpu/solaris_${Platform_arch}/vm/solaris_${Platform_arch_model}.il
+
 # Reduce code bloat by reverting back to 5.0 behavior for static initializers
 CFLAGS += -Qoption ccfe -one_static_init
 
@@ -312,6 +311,15 @@
 PICFLAG/BETTER  = $(PICFLAG/DEFAULT)
 PICFLAG/BYFILE  = $(PICFLAG/$@)$(PICFLAG/DEFAULT$(PICFLAG/$@))
 
+# Use $(MAPFLAG:FILENAME=real_file_name) to specify a map file.
+MAPFLAG = -M FILENAME
+
+# Use $(SONAMEFLAG:SONAME=soname) to specify the intrinsic name of a shared obj
+SONAMEFLAG = -h SONAME
+
+# Build shared library
+SHARED_FLAG = -G
+
 # Would be better if these weren't needed, since we link with CC, but
 # at present removing them causes run-time errors
 LFLAGS += -library=Crun
--- a/hotspot/make/solaris/makefiles/vm.make	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/make/solaris/makefiles/vm.make	Wed Jul 05 17:04:56 2017 +0200
@@ -108,11 +108,16 @@
 #   older libm before libCrun, just to make sure it's found and used first.
 LIBS += -lsocket -lsched -ldl $(LIBM) -lCrun -lthread -ldoor -lc
 else
+ifeq ($(COMPILER_REV_NUMERIC), 502)
+# SC6.1 has it's own libm.so: specifying anything else provokes a name conflict.
+LIBS += -ldl -lthread -lsocket -lm -lsched -ldoor
+else
 LIBS += -ldl -lthread -lsocket $(LIBM) -lsched -ldoor
-endif
+endif # 502
+endif # 505
 else
 LIBS += -lsocket -lsched -ldl $(LIBM) -lthread -lc
-endif
+endif # sparcWorks
 
 # By default, link the *.o into the library, not the executable.
 LINK_INTO$(LINK_INTO) = LIBJVM
@@ -126,8 +131,9 @@
 #----------------------------------------------------------------------
 # JVM
 
-JVM    = jvm$(G_SUFFIX)
-LIBJVM = lib$(JVM).so
+JVM      = jvm
+LIBJVM   = lib$(JVM).so
+LIBJVM_G = lib$(JVM)$(G_SUFFIX).so
 
 JVM_OBJ_FILES = $(Obj_Files) $(DTRACE_OBJS)
 
@@ -173,11 +179,12 @@
 	-sbfast|-xsbfast) \
 	    ;; \
 	*) \
-	    echo Linking vm...;                                                  \
-	    $(LINK_LIB.CC/PRE_HOOK)                                              \
-	    $(LINK_VM) $(LFLAGS_VM) -o $@ $(LIBJVM.o) $(LIBS_VM);                \
-	    $(LINK_LIB.CC/POST_HOOK)                                             \
-	    rm -f $@.1; ln -s $@ $@.1;                                           \
+	    echo Linking vm...; \
+	    $(LINK_LIB.CC/PRE_HOOK) \
+	    $(LINK_VM) $(LFLAGS_VM) -o $@ $(LIBJVM.o) $(LIBS_VM); \
+	    $(LINK_LIB.CC/POST_HOOK) \
+	    rm -f $@.1; ln -s $@ $@.1; \
+	    [ -f $(LIBJVM_G) ] || { ln -s $@ $(LIBJVM_G); ln -s $@.1 $(LIBJVM_G).1; }; \
 	    ;; \
 	esac
 
--- a/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp	Wed Jul 05 17:04:56 2017 +0200
@@ -189,14 +189,17 @@
   Register OSR_buf = osrBufferPointer()->as_register();
   { assert(frame::interpreter_frame_monitor_size() == BasicObjectLock::size(), "adjust code below");
     int monitor_offset = BytesPerWord * method()->max_locals() +
-      (BasicObjectLock::size() * BytesPerWord) * (number_of_locks - 1);
+      (2 * BytesPerWord) * (number_of_locks - 1);
+    // SharedRuntime::OSR_migration_begin() packs BasicObjectLocks in
+    // the OSR buffer using 2 word entries: first the lock and then
+    // the oop.
     for (int i = 0; i < number_of_locks; i++) {
-      int slot_offset = monitor_offset - ((i * BasicObjectLock::size()) * BytesPerWord);
+      int slot_offset = monitor_offset - ((i * 2) * BytesPerWord);
 #ifdef ASSERT
       // verify the interpreter's monitor has a non-null object
       {
         Label L;
-        __ ld_ptr(OSR_buf, slot_offset + BasicObjectLock::obj_offset_in_bytes(), O7);
+        __ ld_ptr(OSR_buf, slot_offset + 1*BytesPerWord, O7);
         __ cmp(G0, O7);
         __ br(Assembler::notEqual, false, Assembler::pt, L);
         __ delayed()->nop();
@@ -205,9 +208,9 @@
       }
 #endif // ASSERT
       // Copy the lock field into the compiled activation.
-      __ ld_ptr(OSR_buf, slot_offset + BasicObjectLock::lock_offset_in_bytes(), O7);
+      __ ld_ptr(OSR_buf, slot_offset + 0, O7);
       __ st_ptr(O7, frame_map()->address_for_monitor_lock(i));
-      __ ld_ptr(OSR_buf, slot_offset + BasicObjectLock::obj_offset_in_bytes(), O7);
+      __ ld_ptr(OSR_buf, slot_offset + 1*BytesPerWord, O7);
       __ st_ptr(O7, frame_map()->address_for_monitor_object(i));
     }
   }
@@ -953,9 +956,11 @@
         } else {
 #ifdef _LP64
           assert(base != to_reg->as_register_lo(), "can't handle this");
+          assert(O7 != to_reg->as_register_lo(), "can't handle this");
           __ ld(base, offset + hi_word_offset_in_bytes, to_reg->as_register_lo());
+          __ lduw(base, offset + lo_word_offset_in_bytes, O7); // in case O7 is base or offset, use it last
           __ sllx(to_reg->as_register_lo(), 32, to_reg->as_register_lo());
-          __ ld(base, offset + lo_word_offset_in_bytes, to_reg->as_register_lo());
+          __ or3(to_reg->as_register_lo(), O7, to_reg->as_register_lo());
 #else
           if (base == to_reg->as_register_lo()) {
             __ ld(base, offset + hi_word_offset_in_bytes, to_reg->as_register_hi());
@@ -976,8 +981,8 @@
           FloatRegister reg = to_reg->as_double_reg();
           // split unaligned loads
           if (unaligned || PatchALot) {
-            __ ldf(FloatRegisterImpl::S, base, offset + BytesPerWord, reg->successor());
-            __ ldf(FloatRegisterImpl::S, base, offset,                reg);
+            __ ldf(FloatRegisterImpl::S, base, offset + 4, reg->successor());
+            __ ldf(FloatRegisterImpl::S, base, offset,     reg);
           } else {
             __ ldf(FloatRegisterImpl::D, base, offset, to_reg->as_double_reg());
           }
@@ -2200,6 +2205,7 @@
   Register len     = O2;
 
   __ add(src, arrayOopDesc::base_offset_in_bytes(basic_type), src_ptr);
+  LP64_ONLY(__ sra(src_pos, 0, src_pos);) //higher 32bits must be null
   if (shift == 0) {
     __ add(src_ptr, src_pos, src_ptr);
   } else {
@@ -2208,6 +2214,7 @@
   }
 
   __ add(dst, arrayOopDesc::base_offset_in_bytes(basic_type), dst_ptr);
+  LP64_ONLY(__ sra(dst_pos, 0, dst_pos);) //higher 32bits must be null
   if (shift == 0) {
     __ add(dst_ptr, dst_pos, dst_ptr);
   } else {
--- a/hotspot/src/cpu/sparc/vm/c1_LIRGenerator_sparc.cpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/cpu/sparc/vm/c1_LIRGenerator_sparc.cpp	Wed Jul 05 17:04:56 2017 +0200
@@ -144,17 +144,17 @@
   if (index->is_register()) {
     // apply the shift and accumulate the displacement
     if (shift > 0) {
-      LIR_Opr tmp = new_register(T_INT);
+      LIR_Opr tmp = new_pointer_register();
       __ shift_left(index, shift, tmp);
       index = tmp;
     }
     if (disp != 0) {
-      LIR_Opr tmp = new_register(T_INT);
+      LIR_Opr tmp = new_pointer_register();
       if (Assembler::is_simm13(disp)) {
-        __ add(tmp, LIR_OprFact::intConst(disp), tmp);
+        __ add(tmp, LIR_OprFact::intptrConst(disp), tmp);
         index = tmp;
       } else {
-        __ move(LIR_OprFact::intConst(disp), tmp);
+        __ move(LIR_OprFact::intptrConst(disp), tmp);
         __ add(tmp, index, tmp);
         index = tmp;
       }
@@ -162,8 +162,8 @@
     }
   } else if (disp != 0 && !Assembler::is_simm13(disp)) {
     // index is illegal so replace it with the displacement loaded into a register
-    index = new_register(T_INT);
-    __ move(LIR_OprFact::intConst(disp), index);
+    index = new_pointer_register();
+    __ move(LIR_OprFact::intptrConst(disp), index);
     disp = 0;
   }
 
--- a/hotspot/src/cpu/sparc/vm/c1_globals_sparc.hpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/cpu/sparc/vm/c1_globals_sparc.hpp	Wed Jul 05 17:04:56 2017 +0200
@@ -22,10 +22,9 @@
  *
  */
 
-//
 // Sets the default values for platform dependent flags used by the client compiler.
 // (see c1_globals.hpp)
-//
+
 #ifndef TIERED
 define_pd_global(bool, BackgroundCompilation,        true );
 define_pd_global(bool, CICompileOSR,                 true );
@@ -48,27 +47,24 @@
 define_pd_global(bool, UseTLAB,                      true );
 define_pd_global(bool, ProfileInterpreter,           false);
 define_pd_global(intx, FreqInlineSize,               325  );
-define_pd_global(intx, NewRatio,                     8    ); // Design center runs on 1.3.1
 define_pd_global(bool, ResizeTLAB,                   true );
 define_pd_global(intx, ReservedCodeCacheSize,        32*M );
 define_pd_global(intx, CodeCacheExpansionSize,       32*K );
 define_pd_global(uintx,CodeCacheMinBlockLength,      1);
-define_pd_global(uintx, PermSize,                    12*M );
-define_pd_global(uintx, MaxPermSize,                 64*M );
-define_pd_global(bool, NeverActAsServerClassMachine, true);
+define_pd_global(uintx,PermSize,                     12*M );
+define_pd_global(uintx,MaxPermSize,                  64*M );
+define_pd_global(bool, NeverActAsServerClassMachine, true );
 define_pd_global(intx, NewSizeThreadIncrease,        16*K );
-define_pd_global(uintx, DefaultMaxRAM,               1*G);
+define_pd_global(uint64_t,MaxRAM,                    1ULL*G);
 define_pd_global(intx, InitialCodeCacheSize,         160*K);
-#endif // TIERED
+#endif // !TIERED
 
 define_pd_global(bool, UseTypeProfile,               false);
 define_pd_global(bool, RoundFPResults,               false);
 
-
-define_pd_global(bool, LIRFillDelaySlots,            true);
+define_pd_global(bool, LIRFillDelaySlots,            true );
 define_pd_global(bool, OptimizeSinglePrecision,      false);
-define_pd_global(bool, CSEArrayLength,               true);
+define_pd_global(bool, CSEArrayLength,               true );
 define_pd_global(bool, TwoOperandLIRForm,            false);
 
-
-define_pd_global(intx, SafepointPollOffset, 0);
+define_pd_global(intx, SafepointPollOffset,          0    );
--- a/hotspot/src/cpu/sparc/vm/c2_globals_sparc.hpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/cpu/sparc/vm/c2_globals_sparc.hpp	Wed Jul 05 17:04:56 2017 +0200
@@ -59,7 +59,6 @@
 define_pd_global(intx, FreqInlineSize,               175);
 define_pd_global(intx, INTPRESSURE,                  48);  // large register set
 define_pd_global(intx, InteriorEntryAlignment,       16);  // = CodeEntryAlignment
-define_pd_global(intx, NewRatio,                     2);
 define_pd_global(intx, NewSizeThreadIncrease, ScaleForWordSize(4*K));
 // The default setting 16/16 seems to work best.
 // (For _228_jack 16/16 is 2% better than 4/4, 16/4, 32/32, 32/16, or 16/32.)
@@ -83,25 +82,25 @@
 // sequence of instructions to load a 64 bit pointer.
 //
 // InitialCodeCacheSize derived from specjbb2000 run.
-define_pd_global(intx, InitialCodeCacheSize,     2048*K); // Integral multiple of CodeCacheExpansionSize
-define_pd_global(intx, ReservedCodeCacheSize,    48*M);
-define_pd_global(intx, CodeCacheExpansionSize,   64*K);
+define_pd_global(intx, InitialCodeCacheSize,         2048*K); // Integral multiple of CodeCacheExpansionSize
+define_pd_global(intx, ReservedCodeCacheSize,        48*M);
+define_pd_global(intx, CodeCacheExpansionSize,       64*K);
 
 // Ergonomics related flags
-define_pd_global(uintx, DefaultMaxRAM,           32*G);
+define_pd_global(uint64_t,MaxRAM,                    128ULL*G);
 #else
 // InitialCodeCacheSize derived from specjbb2000 run.
-define_pd_global(intx, InitialCodeCacheSize,     1536*K); // Integral multiple of CodeCacheExpansionSize
-define_pd_global(intx, ReservedCodeCacheSize,    32*M);
-define_pd_global(intx, CodeCacheExpansionSize,   32*K);
+define_pd_global(intx, InitialCodeCacheSize,         1536*K); // Integral multiple of CodeCacheExpansionSize
+define_pd_global(intx, ReservedCodeCacheSize,        32*M);
+define_pd_global(intx, CodeCacheExpansionSize,       32*K);
 // Ergonomics related flags
-define_pd_global(uintx, DefaultMaxRAM,           1*G);
+define_pd_global(uint64_t,MaxRAM,                    4ULL*G);
 #endif
-define_pd_global(uintx,CodeCacheMinBlockLength,  4);
+define_pd_global(uintx,CodeCacheMinBlockLength,      4);
 
 // Heap related flags
-define_pd_global(uintx, PermSize,    ScaleForWordSize(16*M));
-define_pd_global(uintx, MaxPermSize, ScaleForWordSize(64*M));
+define_pd_global(uintx,PermSize,    ScaleForWordSize(16*M));
+define_pd_global(uintx,MaxPermSize, ScaleForWordSize(64*M));
 
 // Ergonomics related flags
 define_pd_global(bool, NeverActAsServerClassMachine, false);
--- a/hotspot/src/cpu/sparc/vm/globals_sparc.hpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/cpu/sparc/vm/globals_sparc.hpp	Wed Jul 05 17:04:56 2017 +0200
@@ -22,10 +22,8 @@
  *
  */
 
-//
 // Sets the default values for platform dependent flags used by the runtime system.
 // (see globals.hpp)
-//
 
 // For sparc we do not do call backs when a thread is in the interpreter, because the
 // interpreter dispatch needs at least two instructions - first to load the dispatch address
@@ -41,26 +39,23 @@
 define_pd_global(bool, ImplicitNullChecks,          true);  // Generate code for implicit null checks
 define_pd_global(bool, UncommonNullCast,            true);  // Uncommon-trap NULLs past to check cast
 
-define_pd_global(intx,  CodeEntryAlignment,    32);
-define_pd_global(uintx, TLABSize,              0);
-define_pd_global(uintx, NewSize, ScaleForWordSize((2048 * K) + (2 * (64 * K))));
-define_pd_global(intx,  SurvivorRatio,         8);
-define_pd_global(intx,  InlineFrequencyCount,  50);  // we can use more inlining on the SPARC
-define_pd_global(intx,  InlineSmallCode,       1500);
+define_pd_global(intx, CodeEntryAlignment,    32);
+define_pd_global(intx, InlineFrequencyCount,  50);  // we can use more inlining on the SPARC
+define_pd_global(intx, InlineSmallCode,       1500);
 #ifdef _LP64
 // Stack slots are 2X larger in LP64 than in the 32 bit VM.
-define_pd_global(intx,  ThreadStackSize,       1024);
-define_pd_global(intx,  VMThreadStackSize,     1024);
+define_pd_global(intx, ThreadStackSize,       1024);
+define_pd_global(intx, VMThreadStackSize,     1024);
 #else
-define_pd_global(intx,  ThreadStackSize,       512);
-define_pd_global(intx,  VMThreadStackSize,     512);
+define_pd_global(intx, ThreadStackSize,       512);
+define_pd_global(intx, VMThreadStackSize,     512);
 #endif
 
 define_pd_global(intx, StackYellowPages, 2);
 define_pd_global(intx, StackRedPages, 1);
 define_pd_global(intx, StackShadowPages, 3 DEBUG_ONLY(+1));
 
-define_pd_global(intx,  PreInflateSpin,        40);  // Determined by running design center
+define_pd_global(intx, PreInflateSpin,       40);  // Determined by running design center
 
 define_pd_global(bool, RewriteBytecodes,     true);
 define_pd_global(bool, RewriteFrequentPairs, true);
--- a/hotspot/src/cpu/sparc/vm/templateInterpreter_sparc.cpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/cpu/sparc/vm/templateInterpreter_sparc.cpp	Wed Jul 05 17:04:56 2017 +0200
@@ -150,8 +150,7 @@
 }
 
 
-address TemplateInterpreterGenerator::generate_return_entry_for(TosState state, int step, bool unbox) {
-  assert(!unbox, "NYI");//6815692//
+address TemplateInterpreterGenerator::generate_return_entry_for(TosState state, int step) {
   address compiled_entry = __ pc();
   Label cont;
 
--- a/hotspot/src/cpu/x86/vm/assembler_x86.cpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/cpu/x86/vm/assembler_x86.cpp	Wed Jul 05 17:04:56 2017 +0200
@@ -2251,6 +2251,7 @@
   emit_byte(0x9D);
 }
 
+#ifndef _LP64 // no 32bit push/pop on amd64
 void Assembler::popl(Address dst) {
   // NOTE: this will adjust stack by 8byte on 64bits
   InstructionMark im(this);
@@ -2258,6 +2259,7 @@
   emit_byte(0x8F);
   emit_operand(rax, dst);
 }
+#endif
 
 void Assembler::prefetch_prefix(Address src) {
   prefix(src);
@@ -2428,6 +2430,7 @@
   emit_byte(0x9C);
 }
 
+#ifndef _LP64 // no 32bit push/pop on amd64
 void Assembler::pushl(Address src) {
   // Note this will push 64bit on 64bit
   InstructionMark im(this);
@@ -2435,6 +2438,7 @@
   emit_byte(0xFF);
   emit_operand(rsi, src);
 }
+#endif
 
 void Assembler::pxor(XMMRegister dst, Address src) {
   NOT_LP64(assert(VM_Version::supports_sse2(), ""));
@@ -5591,7 +5595,12 @@
 }
 
 void MacroAssembler::andpd(XMMRegister dst, AddressLiteral src) {
-  andpd(dst, as_Address(src));
+  if (reachable(src)) {
+    andpd(dst, as_Address(src));
+  } else {
+    lea(rscratch1, src);
+    andpd(dst, Address(rscratch1, 0));
+  }
 }
 
 void MacroAssembler::andptr(Register dst, int32_t imm32) {
@@ -6078,11 +6087,21 @@
 }
 
 void MacroAssembler::comisd(XMMRegister dst, AddressLiteral src) {
-  comisd(dst, as_Address(src));
+  if (reachable(src)) {
+    comisd(dst, as_Address(src));
+  } else {
+    lea(rscratch1, src);
+    comisd(dst, Address(rscratch1, 0));
+  }
 }
 
 void MacroAssembler::comiss(XMMRegister dst, AddressLiteral src) {
-  comiss(dst, as_Address(src));
+  if (reachable(src)) {
+    comiss(dst, as_Address(src));
+  } else {
+    lea(rscratch1, src);
+    comiss(dst, Address(rscratch1, 0));
+  }
 }
 
 
@@ -7647,7 +7666,7 @@
 
 #ifdef ASSERT
   Label L;
-  testl(tmp, tmp);
+  testptr(tmp, tmp);
   jccb(Assembler::notZero, L);
   hlt();
   bind(L);
--- a/hotspot/src/cpu/x86/vm/assembler_x86.hpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/cpu/x86/vm/assembler_x86.hpp	Wed Jul 05 17:04:56 2017 +0200
@@ -1244,7 +1244,9 @@
   void pcmpestri(XMMRegister xmm1, XMMRegister xmm2, int imm8);
   void pcmpestri(XMMRegister xmm1, Address src, int imm8);
 
+#ifndef _LP64 // no 32bit push/pop on amd64
   void popl(Address dst);
+#endif
 
 #ifdef _LP64
   void popq(Address dst);
@@ -1285,7 +1287,9 @@
   // Interleave Low Bytes
   void punpcklbw(XMMRegister dst, XMMRegister src);
 
+#ifndef _LP64 // no 32bit push/pop on amd64
   void pushl(Address src);
+#endif
 
   void pushq(Address src);
 
--- a/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp	Wed Jul 05 17:04:56 2017 +0200
@@ -301,22 +301,25 @@
   Register OSR_buf = osrBufferPointer()->as_pointer_register();
   { assert(frame::interpreter_frame_monitor_size() == BasicObjectLock::size(), "adjust code below");
     int monitor_offset = BytesPerWord * method()->max_locals() +
-      (BasicObjectLock::size() * BytesPerWord) * (number_of_locks - 1);
+      (2 * BytesPerWord) * (number_of_locks - 1);
+    // SharedRuntime::OSR_migration_begin() packs BasicObjectLocks in
+    // the OSR buffer using 2 word entries: first the lock and then
+    // the oop.
     for (int i = 0; i < number_of_locks; i++) {
-      int slot_offset = monitor_offset - ((i * BasicObjectLock::size()) * BytesPerWord);
+      int slot_offset = monitor_offset - ((i * 2) * BytesPerWord);
 #ifdef ASSERT
       // verify the interpreter's monitor has a non-null object
       {
         Label L;
-        __ cmpptr(Address(OSR_buf, slot_offset + BasicObjectLock::obj_offset_in_bytes()), (int32_t)NULL_WORD);
+        __ cmpptr(Address(OSR_buf, slot_offset + 1*BytesPerWord), (int32_t)NULL_WORD);
         __ jcc(Assembler::notZero, L);
         __ stop("locked object is NULL");
         __ bind(L);
       }
 #endif
-      __ movptr(rbx, Address(OSR_buf, slot_offset + BasicObjectLock::lock_offset_in_bytes()));
+      __ movptr(rbx, Address(OSR_buf, slot_offset + 0));
       __ movptr(frame_map()->address_for_monitor_lock(i), rbx);
-      __ movptr(rbx, Address(OSR_buf, slot_offset + BasicObjectLock::obj_offset_in_bytes()));
+      __ movptr(rbx, Address(OSR_buf, slot_offset + 1*BytesPerWord));
       __ movptr(frame_map()->address_for_monitor_object(i), rbx);
     }
   }
@@ -785,7 +788,13 @@
           ShouldNotReachHere();
           __ movoop(as_Address(addr, noreg), c->as_jobject());
         } else {
+#ifdef _LP64
+          __ movoop(rscratch1, c->as_jobject());
+          null_check_here = code_offset();
+          __ movptr(as_Address_lo(addr), rscratch1);
+#else
           __ movoop(as_Address(addr), c->as_jobject());
+#endif
         }
       }
       break;
@@ -1118,8 +1127,14 @@
       __ pushptr(frame_map()->address_for_slot(src ->single_stack_ix()));
       __ popptr (frame_map()->address_for_slot(dest->single_stack_ix()));
     } else {
+#ifndef _LP64
       __ pushl(frame_map()->address_for_slot(src ->single_stack_ix()));
       __ popl (frame_map()->address_for_slot(dest->single_stack_ix()));
+#else
+      //no pushl on 64bits
+      __ movl(rscratch1, frame_map()->address_for_slot(src ->single_stack_ix()));
+      __ movl(frame_map()->address_for_slot(dest->single_stack_ix()), rscratch1);
+#endif
     }
 
   } else if (src->is_double_stack()) {
@@ -3136,8 +3151,10 @@
 
 #ifdef _LP64
   assert_different_registers(c_rarg0, dst, dst_pos, length);
+  __ movl2ptr(src_pos, src_pos); //higher 32bits must be null
   __ lea(c_rarg0, Address(src, src_pos, scale, arrayOopDesc::base_offset_in_bytes(basic_type)));
   assert_different_registers(c_rarg1, length);
+  __ movl2ptr(dst_pos, dst_pos); //higher 32bits must be null
   __ lea(c_rarg1, Address(dst, dst_pos, scale, arrayOopDesc::base_offset_in_bytes(basic_type)));
   __ mov(c_rarg2, length);
 
--- a/hotspot/src/cpu/x86/vm/c1_LIRGenerator_x86.cpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/cpu/x86/vm/c1_LIRGenerator_x86.cpp	Wed Jul 05 17:04:56 2017 +0200
@@ -755,8 +755,19 @@
   }
 
   LIR_Opr addr = new_pointer_register();
-  __ move(obj.result(), addr);
-  __ add(addr, offset.result(), addr);
+  LIR_Address* a;
+  if(offset.result()->is_constant()) {
+    a = new LIR_Address(obj.result(),
+                        NOT_LP64(offset.result()->as_constant_ptr()->as_jint()) LP64_ONLY((int)offset.result()->as_constant_ptr()->as_jlong()),
+                        as_BasicType(type));
+  } else {
+    a = new LIR_Address(obj.result(),
+                        offset.result(),
+                        LIR_Address::times_1,
+                        0,
+                        as_BasicType(type));
+  }
+  __ leal(LIR_OprFact::address(a), addr);
 
   if (type == objectType) {  // Write-barrier needed for Object fields.
     // Do the pre-write barrier, if any.
--- a/hotspot/src/cpu/x86/vm/c1_globals_x86.hpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/cpu/x86/vm/c1_globals_x86.hpp	Wed Jul 05 17:04:56 2017 +0200
@@ -22,10 +22,8 @@
  *
  */
 
-//
 // Sets the default values for platform dependent flags used by the client compiler.
 // (see c1_globals.hpp)
-//
 
 #ifndef TIERED
 define_pd_global(bool, BackgroundCompilation,        true );
@@ -48,27 +46,24 @@
 
 define_pd_global(intx, OnStackReplacePercentage,     933  );
 define_pd_global(intx, FreqInlineSize,               325  );
-define_pd_global(intx, NewRatio,                     12   );
 define_pd_global(intx, NewSizeThreadIncrease,        4*K  );
 define_pd_global(intx, InitialCodeCacheSize,         160*K);
 define_pd_global(intx, ReservedCodeCacheSize,        32*M );
 define_pd_global(bool, ProfileInterpreter,           false);
 define_pd_global(intx, CodeCacheExpansionSize,       32*K );
 define_pd_global(uintx,CodeCacheMinBlockLength,      1);
-define_pd_global(uintx, PermSize,                    12*M );
-define_pd_global(uintx, MaxPermSize,                 64*M );
-define_pd_global(bool, NeverActAsServerClassMachine, true);
-define_pd_global(uintx, DefaultMaxRAM,               1*G);
+define_pd_global(uintx,PermSize,                     12*M );
+define_pd_global(uintx,MaxPermSize,                  64*M );
+define_pd_global(bool, NeverActAsServerClassMachine, true );
+define_pd_global(uint64_t,MaxRAM,                    1ULL*G);
 define_pd_global(bool, CICompileOSR,                 true );
-#endif // TIERED
+#endif // !TIERED
 define_pd_global(bool, UseTypeProfile,               false);
 define_pd_global(bool, RoundFPResults,               true );
 
-
 define_pd_global(bool, LIRFillDelaySlots,            false);
-define_pd_global(bool, OptimizeSinglePrecision,      true);
+define_pd_global(bool, OptimizeSinglePrecision,      true );
 define_pd_global(bool, CSEArrayLength,               false);
-define_pd_global(bool, TwoOperandLIRForm,            true);
+define_pd_global(bool, TwoOperandLIRForm,            true );
 
-
-define_pd_global(intx, SafepointPollOffset, 256);
+define_pd_global(intx, SafepointPollOffset,          256  );
--- a/hotspot/src/cpu/x86/vm/c2_globals_x86.hpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/cpu/x86/vm/c2_globals_x86.hpp	Wed Jul 05 17:04:56 2017 +0200
@@ -22,7 +22,6 @@
  *
  */
 
-//
 // Sets the default values for platform dependent flags used by the server compiler.
 // (see c2_globals.hpp).  Alpha-sorted.
 
@@ -46,8 +45,8 @@
 define_pd_global(intx, CompileThreshold,             10000);
 #endif // TIERED
 define_pd_global(intx, Tier2CompileThreshold,        10000);
-define_pd_global(intx, Tier3CompileThreshold,        20000 );
-define_pd_global(intx, Tier4CompileThreshold,        40000 );
+define_pd_global(intx, Tier3CompileThreshold,        20000);
+define_pd_global(intx, Tier4CompileThreshold,        40000);
 
 define_pd_global(intx, BackEdgeThreshold,            100000);
 define_pd_global(intx, Tier2BackEdgeThreshold,       100000);
@@ -61,7 +60,6 @@
 #ifdef AMD64
 define_pd_global(intx, INTPRESSURE,                  13);
 define_pd_global(intx, InteriorEntryAlignment,       16);
-define_pd_global(intx, NewRatio,                     2);
 define_pd_global(intx, NewSizeThreadIncrease, ScaleForWordSize(4*K));
 define_pd_global(intx, LoopUnrollLimit,              60);
 // InitialCodeCacheSize derived from specjbb2000 run.
@@ -69,19 +67,18 @@
 define_pd_global(intx, CodeCacheExpansionSize,       64*K);
 
 // Ergonomics related flags
-define_pd_global(uintx, DefaultMaxRAM, 32*G);
+define_pd_global(uint64_t,MaxRAM,                    128ULL*G);
 #else
 define_pd_global(intx, INTPRESSURE,                  6);
 define_pd_global(intx, InteriorEntryAlignment,       4);
-define_pd_global(intx, NewRatio,                     8); // Design center runs on 1.3.1
 define_pd_global(intx, NewSizeThreadIncrease,        4*K);
-define_pd_global(intx, LoopUnrollLimit,              50); // Design center runs on 1.3.1
+define_pd_global(intx, LoopUnrollLimit,              50);     // Design center runs on 1.3.1
 // InitialCodeCacheSize derived from specjbb2000 run.
 define_pd_global(intx, InitialCodeCacheSize,         2304*K); // Integral multiple of CodeCacheExpansionSize
 define_pd_global(intx, CodeCacheExpansionSize,       32*K);
 
 // Ergonomics related flags
-define_pd_global(uintx, DefaultMaxRAM, 1*G);
+define_pd_global(uint64_t,MaxRAM,                    4ULL*G);
 #endif // AMD64
 define_pd_global(intx, OptoLoopAlignment,            16);
 define_pd_global(intx, RegisterCostAreaRatio,        16000);
@@ -97,8 +94,8 @@
 define_pd_global(uintx,CodeCacheMinBlockLength,      4);
 
 // Heap related flags
-define_pd_global(uintx, PermSize,    ScaleForWordSize(16*M));
-define_pd_global(uintx, MaxPermSize, ScaleForWordSize(64*M));
+define_pd_global(uintx,PermSize,    ScaleForWordSize(16*M));
+define_pd_global(uintx,MaxPermSize, ScaleForWordSize(64*M));
 
 // Ergonomics related flags
 define_pd_global(bool, NeverActAsServerClassMachine, false);
--- a/hotspot/src/cpu/x86/vm/globals_x86.hpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/cpu/x86/vm/globals_x86.hpp	Wed Jul 05 17:04:56 2017 +0200
@@ -22,17 +22,16 @@
  *
  */
 
-//
 // Sets the default values for platform dependent flags used by the runtime system.
 // (see globals.hpp)
-//
 
-define_pd_global(bool,  ConvertSleepToYield,      true);
-define_pd_global(bool,  ShareVtableStubs,         true);
-define_pd_global(bool,  CountInterpCalls,         true);
+define_pd_global(bool, ConvertSleepToYield,      true);
+define_pd_global(bool, ShareVtableStubs,         true);
+define_pd_global(bool, CountInterpCalls,         true);
+define_pd_global(bool, NeedsDeoptSuspend,        false); // only register window machines need this
 
-define_pd_global(bool, ImplicitNullChecks,          true);  // Generate code for implicit null checks
-define_pd_global(bool, UncommonNullCast,            true);  // Uncommon-trap NULLs past to check cast
+define_pd_global(bool, ImplicitNullChecks,       true);  // Generate code for implicit null checks
+define_pd_global(bool, UncommonNullCast,         true);  // Uncommon-trap NULLs past to check cast
 
 // See 4827828 for this change. There is no globals_core_i486.hpp. I can't
 // assign a different value for C2 without touching a number of files. Use
@@ -42,29 +41,24 @@
 // the uep and the vep doesn't get real alignment but just slops on by
 // only assured that the entry instruction meets the 5 byte size requirement.
 #ifdef COMPILER2
-define_pd_global(intx,  CodeEntryAlignment,       32);
+define_pd_global(intx, CodeEntryAlignment,       32);
 #else
-define_pd_global(intx,  CodeEntryAlignment,       16);
+define_pd_global(intx, CodeEntryAlignment,       16);
 #endif // COMPILER2
+define_pd_global(intx, InlineFrequencyCount,     100);
+define_pd_global(intx, InlineSmallCode,          1000);
 
-define_pd_global(bool, NeedsDeoptSuspend,           false); // only register window machines need this
-
-define_pd_global(uintx, TLABSize,                 0);
+define_pd_global(intx, StackYellowPages, 2);
+define_pd_global(intx, StackRedPages, 1);
 #ifdef AMD64
-define_pd_global(uintx, NewSize, ScaleForWordSize(2048 * K));
 // Very large C++ stack frames using solaris-amd64 optimized builds
 // due to lack of optimization caused by C++ compiler bugs
 define_pd_global(intx, StackShadowPages, SOLARIS_ONLY(20) NOT_SOLARIS(6) DEBUG_ONLY(+2));
 #else
-define_pd_global(uintx, NewSize,                  1024 * K);
 define_pd_global(intx, StackShadowPages, 3 DEBUG_ONLY(+1));
 #endif // AMD64
-define_pd_global(intx,  InlineFrequencyCount,     100);
-define_pd_global(intx,  InlineSmallCode,          1000);
-define_pd_global(intx,  PreInflateSpin,           10);
 
-define_pd_global(intx, StackYellowPages, 2);
-define_pd_global(intx, StackRedPages, 1);
+define_pd_global(intx, PreInflateSpin,           10);
 
 define_pd_global(bool, RewriteBytecodes,     true);
 define_pd_global(bool, RewriteFrequentPairs, true);
--- a/hotspot/src/cpu/x86/vm/interp_masm_x86_32.cpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/cpu/x86/vm/interp_masm_x86_32.cpp	Wed Jul 05 17:04:56 2017 +0200
@@ -196,6 +196,9 @@
   } else {
     assert(EnableInvokeDynamic, "giant index used only for EnableInvokeDynamic");
     movl(reg, Address(rsi, bcp_offset));
+    // Check if the secondary index definition is still ~x, otherwise
+    // we have to change the following assembler code to calculate the
+    // plain index.
     assert(constantPoolCacheOopDesc::decode_secondary_index(~123) == 123, "else change next line");
     notl(reg);  // convert to plain index
   }
--- a/hotspot/src/cpu/x86/vm/interp_masm_x86_64.cpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/cpu/x86/vm/interp_masm_x86_64.cpp	Wed Jul 05 17:04:56 2017 +0200
@@ -185,12 +185,30 @@
 }
 
 
+void InterpreterMacroAssembler::get_cache_index_at_bcp(Register index,
+                                                       int bcp_offset,
+                                                       bool giant_index) {
+  assert(bcp_offset > 0, "bcp is still pointing to start of bytecode");
+  if (!giant_index) {
+    load_unsigned_short(index, Address(r13, bcp_offset));
+  } else {
+    assert(EnableInvokeDynamic, "giant index used only for EnableInvokeDynamic");
+    movl(index, Address(r13, bcp_offset));
+    // Check if the secondary index definition is still ~x, otherwise
+    // we have to change the following assembler code to calculate the
+    // plain index.
+    assert(constantPoolCacheOopDesc::decode_secondary_index(~123) == 123, "else change next line");
+    notl(index);  // convert to plain index
+  }
+}
+
+
 void InterpreterMacroAssembler::get_cache_and_index_at_bcp(Register cache,
                                                            Register index,
-                                                           int bcp_offset) {
-  assert(bcp_offset > 0, "bcp is still pointing to start of bytecode");
+                                                           int bcp_offset,
+                                                           bool giant_index) {
   assert(cache != index, "must use different registers");
-  load_unsigned_short(index, Address(r13, bcp_offset));
+  get_cache_index_at_bcp(index, bcp_offset, giant_index);
   movptr(cache, Address(rbp, frame::interpreter_frame_cache_offset * wordSize));
   assert(sizeof(ConstantPoolCacheEntry) == 4 * wordSize, "adjust code below");
   // convert from field index to ConstantPoolCacheEntry index
@@ -200,10 +218,10 @@
 
 void InterpreterMacroAssembler::get_cache_entry_pointer_at_bcp(Register cache,
                                                                Register tmp,
-                                                               int bcp_offset) {
-  assert(bcp_offset > 0, "bcp is still pointing to start of bytecode");
+                                                               int bcp_offset,
+                                                               bool giant_index) {
   assert(cache != tmp, "must use different register");
-  load_unsigned_short(tmp, Address(r13, bcp_offset));
+  get_cache_index_at_bcp(tmp, bcp_offset, giant_index);
   assert(sizeof(ConstantPoolCacheEntry) == 4 * wordSize, "adjust code below");
   // convert from field index to ConstantPoolCacheEntry index
   // and from word offset to byte offset
@@ -1236,7 +1254,8 @@
 
 void InterpreterMacroAssembler::profile_virtual_call(Register receiver,
                                                      Register mdp,
-                                                     Register reg2) {
+                                                     Register reg2,
+                                                     bool receiver_can_be_null) {
   if (ProfileInterpreter) {
     Label profile_continue;
 
@@ -1246,8 +1265,15 @@
     // We are making a call.  Increment the count.
     increment_mdp_data_at(mdp, in_bytes(CounterData::count_offset()));
 
+    Label skip_receiver_profile;
+    if (receiver_can_be_null) {
+      testptr(receiver, receiver);
+      jcc(Assembler::zero, skip_receiver_profile);
+    }
+
     // Record the receiver type.
     record_klass_in_profile(receiver, mdp, reg2);
+    bind(skip_receiver_profile);
 
     // The method data pointer needs to be updated to reflect the new target.
     update_mdp_by_constant(mdp,
--- a/hotspot/src/cpu/x86/vm/interp_masm_x86_64.hpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/cpu/x86/vm/interp_masm_x86_64.hpp	Wed Jul 05 17:04:56 2017 +0200
@@ -95,9 +95,10 @@
 
   void get_unsigned_2_byte_index_at_bcp(Register reg, int bcp_offset);
   void get_cache_and_index_at_bcp(Register cache, Register index,
-                                  int bcp_offset);
+                                  int bcp_offset, bool giant_index = false);
   void get_cache_entry_pointer_at_bcp(Register cache, Register tmp,
-                                      int bcp_offset);
+                                      int bcp_offset, bool giant_index = false);
+  void get_cache_index_at_bcp(Register index, int bcp_offset, bool giant_index = false);
 
 
   void pop_ptr(Register r = rax);
@@ -236,7 +237,8 @@
   void profile_call(Register mdp);
   void profile_final_call(Register mdp);
   void profile_virtual_call(Register receiver, Register mdp,
-                            Register scratch2);
+                            Register scratch2,
+                            bool receiver_can_be_null = false);
   void profile_ret(Register return_bci, Register mdp);
   void profile_null_seen(Register mdp);
   void profile_typecheck(Register mdp, Register klass, Register scratch);
--- a/hotspot/src/cpu/x86/vm/interpreter_x86_64.cpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/cpu/x86/vm/interpreter_x86_64.cpp	Wed Jul 05 17:04:56 2017 +0200
@@ -277,12 +277,11 @@
   address entry_point = __ pc();
 
   // abstract method entry
-  // remove return address. Not really needed, since exception
-  // handling throws away expression stack
-  __ pop(rbx);
 
-  // adjust stack to what a normal return would do
-  __ mov(rsp, r13);
+  //  pop return address, reset last_sp to NULL
+  __ empty_expression_stack();
+  __ restore_bcp();      // rsi must be correct for exception handler   (was destroyed)
+  __ restore_locals();   // make sure locals pointer is correct as well (was destroyed)
 
   // throw exception
   __ call_VM(noreg, CAST_FROM_FN_PTR(address,
@@ -300,7 +299,10 @@
   if (!EnableMethodHandles) {
     return generate_abstract_entry();
   }
-  return generate_abstract_entry(); //6815692//
+
+  address entry_point = MethodHandles::generate_method_handle_interpreter_entry(_masm);
+
+  return entry_point;
 }
 
 
--- a/hotspot/src/cpu/x86/vm/methodHandles_x86.cpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/cpu/x86/vm/methodHandles_x86.cpp	Wed Jul 05 17:04:56 2017 +0200
@@ -448,7 +448,7 @@
                                 rbx_index, Address::times_ptr,
                                 base + vtableEntry::method_offset_in_bytes());
       Register rbx_method = rbx_temp;
-      __ movl(rbx_method, vtable_entry_addr);
+      __ movptr(rbx_method, vtable_entry_addr);
 
       __ verify_oop(rbx_method);
       __ jmp(rbx_method_fie);
--- a/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp	Wed Jul 05 17:04:56 2017 +0200
@@ -2935,6 +2935,16 @@
 
     // arraycopy stubs used by compilers
     generate_arraycopy_stubs();
+
+    // generic method handle stubs
+    if (EnableMethodHandles && SystemDictionary::MethodHandle_klass() != NULL) {
+      for (MethodHandles::EntryKind ek = MethodHandles::_EK_FIRST;
+           ek < MethodHandles::_EK_LIMIT;
+           ek = MethodHandles::EntryKind(1 + (int)ek)) {
+        StubCodeMark mark(this, "MethodHandle", MethodHandles::entry_name(ek));
+        MethodHandles::generate_method_handle_stub(_masm, ek);
+      }
+    }
   }
 
  public:
--- a/hotspot/src/cpu/x86/vm/templateInterpreter_x86_32.cpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/cpu/x86/vm/templateInterpreter_x86_32.cpp	Wed Jul 05 17:04:56 2017 +0200
@@ -155,15 +155,8 @@
 }
 
 
-address TemplateInterpreterGenerator::generate_return_entry_for(TosState state, int step, bool unbox) {
+address TemplateInterpreterGenerator::generate_return_entry_for(TosState state, int step) {
   TosState incoming_state = state;
-  if (EnableInvokeDynamic) {
-    if (unbox) {
-      incoming_state = atos;
-    }
-  } else {
-    assert(!unbox, "old behavior");
-  }
 
   Label interpreter_entry;
   address compiled_entry = __ pc();
@@ -216,46 +209,6 @@
   __ restore_bcp();
   __ restore_locals();
 
-  Label L_fail;
-
-  if (unbox && state != atos) {
-    // cast and unbox
-    BasicType type = as_BasicType(state);
-    if (type == T_BYTE)  type = T_BOOLEAN; // FIXME
-    KlassHandle boxk = SystemDictionaryHandles::box_klass(type);
-    __ mov32(rbx, ExternalAddress((address) boxk.raw_value()));
-    __ testl(rax, rax);
-    Label L_got_value, L_get_value;
-    // convert nulls to zeroes (avoid NPEs here)
-    if (!(type == T_FLOAT || type == T_DOUBLE)) {
-      // if rax already contains zero bits, forge ahead
-      __ jcc(Assembler::zero, L_got_value);
-    } else {
-      __ jcc(Assembler::notZero, L_get_value);
-      __ fldz();
-      __ jmp(L_got_value);
-    }
-    __ bind(L_get_value);
-    __ cmp32(rbx, Address(rax, oopDesc::klass_offset_in_bytes()));
-    __ jcc(Assembler::notEqual, L_fail);
-    int offset = java_lang_boxing_object::value_offset_in_bytes(type);
-    // Cf. TemplateTable::getfield_or_static
-    switch (type) {
-      case T_BYTE:     // fall through:
-      case T_BOOLEAN:  __ load_signed_byte(rax, Address(rax, offset));    break;
-      case T_CHAR:     __ load_unsigned_short(rax, Address(rax, offset)); break;
-      case T_SHORT:    __ load_signed_short(rax, Address(rax, offset));   break;
-      case T_INT:      __ movl(rax, Address(rax, offset));                break;
-      case T_FLOAT:    __ fld_s(Address(rax, offset));                    break;
-      case T_DOUBLE:   __ fld_d(Address(rax, offset));                    break;
-      // Access to java.lang.Double.value does not need to be atomic:
-      case T_LONG:   { __ movl(rdx, Address(rax, offset + 4));
-                       __ movl(rax, Address(rax, offset + 0));  }         break;
-      default: ShouldNotReachHere();
-    }
-    __ bind(L_got_value);
-  }
-
   Label L_got_cache, L_giant_index;
   if (EnableInvokeDynamic) {
     __ cmpb(Address(rsi, 0), Bytecodes::_invokedynamic);
@@ -263,32 +216,6 @@
   }
   __ get_cache_and_index_at_bcp(rbx, rcx, 1, false);
   __ bind(L_got_cache);
-  if (unbox && state == atos) {
-    // insert a casting conversion, to keep verifier sane
-    Label L_ok, L_ok_pops;
-    __ testl(rax, rax);
-    __ jcc(Assembler::zero, L_ok);
-    __ push(rax);               // save the object to check
-    __ push(rbx);               // save CP cache reference
-    __ movl(rdx, Address(rax, oopDesc::klass_offset_in_bytes()));
-    __ movl(rbx, Address(rbx, rcx,
-                      Address::times_4, constantPoolCacheOopDesc::base_offset() +
-                      ConstantPoolCacheEntry::f1_offset()));
-    __ movl(rbx, Address(rbx, __ delayed_value(sun_dyn_CallSiteImpl::type_offset_in_bytes, rcx)));
-    __ movl(rbx, Address(rbx, __ delayed_value(java_dyn_MethodType::rtype_offset_in_bytes, rcx)));
-    __ movl(rax, Address(rbx, __ delayed_value(java_lang_Class::klass_offset_in_bytes, rcx)));
-    __ check_klass_subtype(rdx, rax, rbx, L_ok_pops);
-    __ pop(rcx);                // pop and discard CP cache
-    __ mov(rbx, rax);           // target supertype into rbx for L_fail
-    __ pop(rax);                // failed object into rax for L_fail
-    __ jmp(L_fail);
-
-    __ bind(L_ok_pops);
-    // restore pushed temp regs:
-    __ pop(rbx);
-    __ pop(rax);
-    __ bind(L_ok);
-  }
   __ movl(rbx, Address(rbx, rcx,
                     Address::times_ptr, constantPoolCacheOopDesc::base_offset() +
                     ConstantPoolCacheEntry::flags_offset()));
@@ -301,14 +228,6 @@
     __ bind(L_giant_index);
     __ get_cache_and_index_at_bcp(rbx, rcx, 1, true);
     __ jmp(L_got_cache);
-
-    if (unbox) {
-      __ bind(L_fail);
-      __ push(rbx);             // missed klass (required)
-      __ push(rax);             // bad object (actual)
-      __ movptr(rdx, ExternalAddress((address) &Interpreter::_throw_WrongMethodType_entry));
-      __ call(rdx);
-    }
   }
 
   return entry;
--- a/hotspot/src/cpu/x86/vm/templateInterpreter_x86_64.cpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/cpu/x86/vm/templateInterpreter_x86_64.cpp	Wed Jul 05 17:04:56 2017 +0200
@@ -100,21 +100,26 @@
   return entry;
 }
 
-// Arguments are: required type in rarg1, failing object (or NULL) in rarg2
+// Arguments are: required type at TOS+8, failing object (or NULL) at TOS+4.
 address TemplateInterpreterGenerator::generate_WrongMethodType_handler() {
   address entry = __ pc();
 
   __ pop(c_rarg2);              // failing object is at TOS
   __ pop(c_rarg1);              // required type is at TOS+8
 
-  // expression stack must be empty before entering the VM if an
-  // exception happened
+  __ verify_oop(c_rarg1);
+  __ verify_oop(c_rarg2);
+
+  // Various method handle types use interpreter registers as temps.
+  __ restore_bcp();
+  __ restore_locals();
+
+  // Expression stack must be empty before entering the VM for an exception.
   __ empty_expression_stack();
 
   __ call_VM(noreg,
              CAST_FROM_FN_PTR(address,
-                              InterpreterRuntime::
-                              throw_WrongMethodTypeException),
+                              InterpreterRuntime::throw_WrongMethodTypeException),
              // pass required type, failing object (or NULL)
              c_rarg1, c_rarg2);
   return entry;
@@ -166,8 +171,7 @@
 
 
 address TemplateInterpreterGenerator::generate_return_entry_for(TosState state,
-                                                                int step, bool unbox) {
-  assert(!unbox, "NYI");//6815692//
+                                                                int step) {
 
   // amd64 doesn't need to do anything special about compiled returns
   // to the interpreter so the code that exists on x86 to place a sentinel
@@ -183,15 +187,29 @@
   __ restore_bcp();
   __ restore_locals();
 
-  __ get_cache_and_index_at_bcp(rbx, rcx, 1);
+  Label L_got_cache, L_giant_index;
+  if (EnableInvokeDynamic) {
+    __ cmpb(Address(r13, 0), Bytecodes::_invokedynamic);
+    __ jcc(Assembler::equal, L_giant_index);
+  }
+  __ get_cache_and_index_at_bcp(rbx, rcx, 1, false);
+  __ bind(L_got_cache);
   __ movl(rbx, Address(rbx, rcx,
-                       Address::times_8,
+                       Address::times_ptr,
                        in_bytes(constantPoolCacheOopDesc::base_offset()) +
                        3 * wordSize));
   __ andl(rbx, 0xFF);
   if (TaggedStackInterpreter) __ shll(rbx, 1); // 2 slots per parameter.
   __ lea(rsp, Address(rsp, rbx, Address::times_8));
   __ dispatch_next(state, step);
+
+  // out of the main line of code...
+  if (EnableInvokeDynamic) {
+    __ bind(L_giant_index);
+    __ get_cache_and_index_at_bcp(rbx, rcx, 1, true);
+    __ jmp(L_got_cache);
+  }
+
   return entry;
 }
 
--- a/hotspot/src/cpu/x86/vm/templateTable_x86_32.cpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/cpu/x86/vm/templateTable_x86_32.cpp	Wed Jul 05 17:04:56 2017 +0200
@@ -2890,9 +2890,6 @@
 
 
 void TemplateTable::prepare_invoke(Register method, Register index, int byte_no) {
-  bool is_invdyn_bootstrap = (byte_no < 0);
-  if (is_invdyn_bootstrap)  byte_no = -byte_no;
-
   // determine flags
   Bytecodes::Code code = bytecode();
   const bool is_invokeinterface  = code == Bytecodes::_invokeinterface;
@@ -2907,8 +2904,6 @@
   const Register flags  = rdx;
   assert_different_registers(method, index, recv, flags);
 
-  assert(!is_invdyn_bootstrap || is_invokedynamic, "byte_no<0 hack only for invdyn");
-
   // save 'interpreter return address'
   __ save_bcp();
 
@@ -2944,9 +2939,7 @@
   // load return address
   {
     address table_addr;
-    if (is_invdyn_bootstrap)
-      table_addr = (address)Interpreter::return_5_unbox_addrs_by_index_table();
-    else if (is_invokeinterface || is_invokedynamic)
+    if (is_invokeinterface || is_invokedynamic)
       table_addr = (address)Interpreter::return_5_addrs_by_index_table();
     else
       table_addr = (address)Interpreter::return_3_addrs_by_index_table();
@@ -3153,54 +3146,10 @@
     __ profile_call(rsi);
   }
 
-  Label handle_unlinked_site;
-  __ movptr(rcx, Address(rax, __ delayed_value(sun_dyn_CallSiteImpl::target_offset_in_bytes, rcx)));
-  __ testptr(rcx, rcx);
-  __ jcc(Assembler::zero, handle_unlinked_site);
-
+  __ movptr(rcx, Address(rax, __ delayed_value(java_dyn_CallSite::target_offset_in_bytes, rcx)));
+  __ null_check(rcx);
   __ prepare_to_jump_from_interpreted();
   __ jump_to_method_handle_entry(rcx, rdx);
-
-  // Initial calls come here...
-  __ bind(handle_unlinked_site);
-  __ pop(rcx);                 // remove return address pushed by prepare_invoke
-
-  // box stacked arguments into an array for the bootstrap method
-  address entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::bootstrap_invokedynamic);
-  __ restore_bcp();      // rsi must be correct for call_VM
-  __ call_VM(rax, entry, rax);
-  __ movl(rdi, rax);            // protect bootstrap MH from prepare_invoke
-
-  // recompute return address
-  __ restore_bcp();      // rsi must be correct for prepare_invoke
-  prepare_invoke(rax, rbx, -byte_no);  // smashes rcx, rdx
-  // rax: CallSite object (f1)
-  // rbx: unused (f2)
-  // rdi: bootstrap MH
-  // rdx: flags
-
-  // now load up the arglist, which has been neatly boxed
-  __ get_thread(rcx);
-  __ movptr(rdx, Address(rcx, JavaThread::vm_result_2_offset()));
-  __ movptr(Address(rcx, JavaThread::vm_result_2_offset()), NULL_WORD);
-  __ verify_oop(rdx);
-  // rdx = arglist
-
-  // save SP now, before we add the bootstrap call to the stack
-  // We must preserve a fiction that the original arguments are outgoing,
-  // because the return sequence will reset the stack to this point
-  // and then pop all those arguments.  It seems error-prone to use
-  // a different argument list size just for bootstrapping.
-  __ prepare_to_jump_from_interpreted();
-
-  // Now let's play adapter, pushing the real arguments on the stack.
-  __ pop(rbx);                  // return PC
-  __ push(rdi);                 // boot MH
-  __ push(rax);                 // call site
-  __ push(rdx);                 // arglist
-  __ push(rbx);                 // return PC, again
-  __ mov(rcx, rdi);
-  __ jump_to_method_handle_entry(rcx, rdx);
 }
 
 //----------------------------------------------------------------------------------------------------
--- a/hotspot/src/cpu/x86/vm/templateTable_x86_64.cpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/cpu/x86/vm/templateTable_x86_64.cpp	Wed Jul 05 17:04:56 2017 +0200
@@ -203,18 +203,15 @@
     __ jcc(Assembler::notEqual, fast_patch);
     __ get_method(scratch);
     // Let breakpoint table handling rewrite to quicker bytecode
-    __ call_VM(noreg,
-               CAST_FROM_FN_PTR(address,
-                                InterpreterRuntime::set_original_bytecode_at),
-               scratch, r13, bc);
+    __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::set_original_bytecode_at), scratch, r13, bc);
 #ifndef ASSERT
     __ jmpb(patch_done);
+#else
+    __ jmp(patch_done);
+#endif
     __ bind(fast_patch);
   }
-#else
-    __ jmp(patch_done);
-    __ bind(fast_patch);
-  }
+#ifdef ASSERT
   Label okay;
   __ load_unsigned_byte(scratch, at_bcp(0));
   __ cmpl(scratch, (int) Bytecodes::java_code(bytecode));
@@ -2054,26 +2051,28 @@
   }
 }
 
-void TemplateTable::resolve_cache_and_index(int byte_no,
-                                            Register Rcache,
-                                            Register index) {
+void TemplateTable::resolve_cache_and_index(int byte_no, Register Rcache, Register index) {
   assert(byte_no == 1 || byte_no == 2, "byte_no out of range");
+  bool is_invokedynamic = (bytecode() == Bytecodes::_invokedynamic);
 
   const Register temp = rbx;
   assert_different_registers(Rcache, index, temp);
 
   const int shift_count = (1 + byte_no) * BitsPerByte;
   Label resolved;
-  __ get_cache_and_index_at_bcp(Rcache, index, 1);
-  __ movl(temp, Address(Rcache,
-                        index, Address::times_8,
-                        constantPoolCacheOopDesc::base_offset() +
-                        ConstantPoolCacheEntry::indices_offset()));
-  __ shrl(temp, shift_count);
-  // have we resolved this bytecode?
-  __ andl(temp, 0xFF);
-  __ cmpl(temp, (int) bytecode());
-  __ jcc(Assembler::equal, resolved);
+  __ get_cache_and_index_at_bcp(Rcache, index, 1, is_invokedynamic);
+  if (is_invokedynamic) {
+    // we are resolved if the f1 field contains a non-null CallSite object
+    __ cmpptr(Address(Rcache, index, Address::times_ptr, constantPoolCacheOopDesc::base_offset() + ConstantPoolCacheEntry::f1_offset()), (int32_t) NULL_WORD);
+    __ jcc(Assembler::notEqual, resolved);
+  } else {
+    __ movl(temp, Address(Rcache, index, Address::times_ptr, constantPoolCacheOopDesc::base_offset() + ConstantPoolCacheEntry::indices_offset()));
+    __ shrl(temp, shift_count);
+    // have we resolved this bytecode?
+    __ andl(temp, 0xFF);
+    __ cmpl(temp, (int) bytecode());
+    __ jcc(Assembler::equal, resolved);
+  }
 
   // resolve first time through
   address entry;
@@ -2090,6 +2089,9 @@
   case Bytecodes::_invokeinterface:
     entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_invoke);
     break;
+  case Bytecodes::_invokedynamic:
+    entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_invokedynamic);
+    break;
   default:
     ShouldNotReachHere();
     break;
@@ -2098,7 +2100,7 @@
   __ call_VM(noreg, entry, temp);
 
   // Update registers with resolved info
-  __ get_cache_and_index_at_bcp(Rcache, index, 1);
+  __ get_cache_and_index_at_bcp(Rcache, index, 1, is_invokedynamic);
   __ bind(resolved);
 }
 
@@ -2832,15 +2834,14 @@
   ShouldNotReachHere();
 }
 
-void TemplateTable::prepare_invoke(Register method,
-                                   Register index,
-                                   int byte_no,
-                                   Bytecodes::Code code) {
+void TemplateTable::prepare_invoke(Register method, Register index, int byte_no) {
   // determine flags
+  Bytecodes::Code code = bytecode();
   const bool is_invokeinterface  = code == Bytecodes::_invokeinterface;
+  const bool is_invokedynamic    = code == Bytecodes::_invokedynamic;
   const bool is_invokevirtual    = code == Bytecodes::_invokevirtual;
   const bool is_invokespecial    = code == Bytecodes::_invokespecial;
-  const bool load_receiver       = code != Bytecodes::_invokestatic;
+  const bool load_receiver      = (code != Bytecodes::_invokestatic && code != Bytecodes::_invokedynamic);
   const bool receiver_null_check = is_invokespecial;
   const bool save_flags = is_invokeinterface || is_invokevirtual;
   // setup registers & access constant pool cache
@@ -2858,9 +2859,13 @@
     __ movl(recv, flags);
     __ andl(recv, 0xFF);
     if (TaggedStackInterpreter) __ shll(recv, 1);  // index*2
-    __ movptr(recv, Address(rsp, recv, Address::times_8,
-                                 -Interpreter::expr_offset_in_bytes(1)));
-    __ verify_oop(recv);
+    Address recv_addr(rsp, recv, Address::times_8, -Interpreter::expr_offset_in_bytes(1));
+    if (is_invokedynamic) {
+      __ lea(recv, recv_addr);
+    } else {
+      __ movptr(recv, recv_addr);
+      __ verify_oop(recv);
+    }
   }
 
   // do null check if needed
@@ -2878,10 +2883,14 @@
   ConstantPoolCacheEntry::verify_tosBits();
   // load return address
   {
-    ExternalAddress return_5((address)Interpreter::return_5_addrs_by_index_table());
-    ExternalAddress return_3((address)Interpreter::return_3_addrs_by_index_table());
-    __ lea(rscratch1, (is_invokeinterface ? return_5 : return_3));
-    __ movptr(flags, Address(rscratch1, flags, Address::times_8));
+    address table_addr;
+    if (is_invokeinterface || is_invokedynamic)
+      table_addr = (address)Interpreter::return_5_addrs_by_index_table();
+    else
+      table_addr = (address)Interpreter::return_3_addrs_by_index_table();
+    ExternalAddress table(table_addr);
+    __ lea(rscratch1, table);
+    __ movptr(flags, Address(rscratch1, flags, Address::times_ptr));
   }
 
   // push return address
@@ -2947,7 +2956,7 @@
 
 void TemplateTable::invokevirtual(int byte_no) {
   transition(vtos, vtos);
-  prepare_invoke(rbx, noreg, byte_no, bytecode());
+  prepare_invoke(rbx, noreg, byte_no);
 
   // rbx: index
   // rcx: receiver
@@ -2959,7 +2968,7 @@
 
 void TemplateTable::invokespecial(int byte_no) {
   transition(vtos, vtos);
-  prepare_invoke(rbx, noreg, byte_no, bytecode());
+  prepare_invoke(rbx, noreg, byte_no);
   // do the call
   __ verify_oop(rbx);
   __ profile_call(rax);
@@ -2969,7 +2978,7 @@
 
 void TemplateTable::invokestatic(int byte_no) {
   transition(vtos, vtos);
-  prepare_invoke(rbx, noreg, byte_no, bytecode());
+  prepare_invoke(rbx, noreg, byte_no);
   // do the call
   __ verify_oop(rbx);
   __ profile_call(rax);
@@ -2983,7 +2992,7 @@
 
 void TemplateTable::invokeinterface(int byte_no) {
   transition(vtos, vtos);
-  prepare_invoke(rax, rbx, byte_no, bytecode());
+  prepare_invoke(rax, rbx, byte_no);
 
   // rax: Interface
   // rbx: index
@@ -3072,7 +3081,24 @@
     return;
   }
 
-  __ stop("invokedynamic NYI");//6815692//
+  prepare_invoke(rax, rbx, byte_no);
+
+  // rax: CallSite object (f1)
+  // rbx: unused (f2)
+  // rcx: receiver address
+  // rdx: flags (unused)
+
+  if (ProfileInterpreter) {
+    Label L;
+    // %%% should make a type profile for any invokedynamic that takes a ref argument
+    // profile this call
+    __ profile_call(r13);
+  }
+
+  __ movptr(rcx, Address(rax, __ delayed_value(java_dyn_CallSite::target_offset_in_bytes, rcx)));
+  __ null_check(rcx);
+  __ prepare_to_jump_from_interpreted();
+  __ jump_to_method_handle_entry(rcx, rdx);
 }
 
 
--- a/hotspot/src/cpu/x86/vm/templateTable_x86_64.hpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/cpu/x86/vm/templateTable_x86_64.hpp	Wed Jul 05 17:04:56 2017 +0200
@@ -22,8 +22,7 @@
  *
  */
 
-  static void prepare_invoke(Register method, Register index, int byte_no,
-                             Bytecodes::Code code);
+  static void prepare_invoke(Register method, Register index, int byte_no);
   static void invokevirtual_helper(Register index, Register recv,
                                    Register flags);
   static void volatile_barrier(Assembler::Membar_mask_bits order_constraint);
--- a/hotspot/src/cpu/x86/vm/vm_version_x86.cpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/cpu/x86/vm/vm_version_x86.cpp	Wed Jul 05 17:04:56 2017 +0200
@@ -255,6 +255,8 @@
   if (!VM_Version::supports_sse2()) {
     vm_exit_during_initialization("Unknown x64 processor: SSE2 not supported");
   }
+  // in 64 bit the use of SSE2 is the minimum
+  if (UseSSE < 2) UseSSE = 2;
 #endif
 
   // If the OS doesn't support SSE, we can't use this feature even if the HW does
--- a/hotspot/src/cpu/zero/vm/cppInterpreter_zero.cpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/cpu/zero/vm/cppInterpreter_zero.cpp	Wed Jul 05 17:04:56 2017 +0200
@@ -204,6 +204,20 @@
     goto unwind_and_return;
   }
 
+  // Update the invocation counter
+  if ((UseCompiler || CountCompiledCalls) && !method->is_synchronized()) {
+    thread->set_do_not_unlock();
+    InvocationCounter *counter = method->invocation_counter();
+    counter->increment();
+    if (counter->reached_InvocationLimit()) {
+      CALL_VM_NOCHECK(
+        InterpreterRuntime::frequency_counter_overflow(thread, NULL));
+      if (HAS_PENDING_EXCEPTION)
+        goto unwind_and_return;
+    }
+    thread->clr_do_not_unlock();
+  }
+
   // Lock if necessary
   BasicObjectLock *monitor;
   monitor = NULL;
--- a/hotspot/src/cpu/zero/vm/frame_zero.cpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/cpu/zero/vm/frame_zero.cpp	Wed Jul 05 17:04:56 2017 +0200
@@ -36,11 +36,8 @@
   return zeroframe()->is_interpreter_frame();
 }
 
-bool frame::is_fake_stub_frame() const {
-  return zeroframe()->is_fake_stub_frame();
-}
-
 frame frame::sender_for_entry_frame(RegisterMap *map) const {
+  assert(zeroframe()->is_entry_frame(), "wrong type of frame");
   assert(map != NULL, "map must be set");
   assert(!entry_frame_is_first(), "next Java fp must be non zero");
   assert(entry_frame_call_wrapper()->anchor()->last_Java_sp() == sender_sp(),
@@ -50,15 +47,10 @@
   return frame(sender_sp(), sp() + 1);
 }
 
-frame frame::sender_for_interpreter_frame(RegisterMap *map) const {
-  return frame(sender_sp(), sp() + 1);
-}
-
-frame frame::sender_for_compiled_frame(RegisterMap *map) const {
-  return frame(sender_sp(), sp() + 1);
-}
-
-frame frame::sender_for_fake_stub_frame(RegisterMap *map) const {
+frame frame::sender_for_nonentry_frame(RegisterMap *map) const {
+  assert(zeroframe()->is_interpreter_frame() ||
+         zeroframe()->is_shark_frame() ||
+         zeroframe()->is_fake_stub_frame(), "wrong type of frame");
   return frame(sender_sp(), sp() + 1);
 }
 
@@ -69,17 +61,8 @@
 
   if (is_entry_frame())
     return sender_for_entry_frame(map);
-
-  if (is_interpreted_frame())
-    return sender_for_interpreter_frame(map);
-
-  if (is_compiled_frame())
-    return sender_for_compiled_frame(map);
-
-  if (is_fake_stub_frame())
-    return sender_for_fake_stub_frame(map);
-
-  ShouldNotReachHere();
+  else
+    return sender_for_nonentry_frame(map);
 }
 
 #ifdef CC_INTERP
--- a/hotspot/src/cpu/zero/vm/frame_zero.hpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/cpu/zero/vm/frame_zero.hpp	Wed Jul 05 17:04:56 2017 +0200
@@ -65,10 +65,7 @@
   }
 
  public:
-  bool is_fake_stub_frame() const;
-
- public:
-  frame sender_for_fake_stub_frame(RegisterMap* map) const;
+  frame sender_for_nonentry_frame(RegisterMap* map) const;
 
  public:
   void zero_print_on_error(int           index,
--- a/hotspot/src/cpu/zero/vm/globals_zero.hpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/cpu/zero/vm/globals_zero.hpp	Wed Jul 05 17:04:56 2017 +0200
@@ -23,10 +23,8 @@
  *
  */
 
-//
 // Set the default values for platform dependent flags used by the
 // runtime system.  See globals.hpp for details of what they do.
-//
 
 define_pd_global(bool,  ConvertSleepToYield,  true);
 define_pd_global(bool,  ShareVtableStubs,     true);
@@ -37,14 +35,7 @@
 define_pd_global(bool,  UncommonNullCast,     true);
 
 define_pd_global(intx,  CodeEntryAlignment,   32);
-define_pd_global(uintx, TLABSize,             0);
-#ifdef _LP64
-define_pd_global(uintx, NewSize,              ScaleForWordSize(2048 * K));
-#else
-define_pd_global(uintx, NewSize,              ScaleForWordSize(1024 * K));
-#endif // _LP64
 define_pd_global(intx,  InlineFrequencyCount, 100);
-define_pd_global(intx,  InlineSmallCode,      1000);
 define_pd_global(intx,  PreInflateSpin,       10);
 
 define_pd_global(intx,  StackYellowPages,     2);
--- a/hotspot/src/cpu/zero/vm/sharedRuntime_zero.cpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/cpu/zero/vm/sharedRuntime_zero.cpp	Wed Jul 05 17:04:56 2017 +0200
@@ -1,6 +1,6 @@
 /*
  * Copyright 2003-2007 Sun Microsystems, Inc.  All Rights Reserved.
- * Copyright 2007, 2008 Red Hat, Inc.
+ * Copyright 2007, 2008, 2009 Red Hat, Inc.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -61,7 +61,14 @@
                                                 BasicType *in_sig_bt,
                                                 VMRegPair *in_regs,
                                                 BasicType ret_type) {
+#ifdef SHARK
+  return SharkCompiler::compiler()->generate_native_wrapper(masm,
+                                                            method,
+                                                            in_sig_bt,
+                                                            ret_type);
+#else
   ShouldNotCallThis();
+#endif // SHARK
 }
 
 int Deoptimization::last_frame_adjust(int callee_parameters,
--- a/hotspot/src/cpu/zero/vm/sharkFrame_zero.hpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/cpu/zero/vm/sharkFrame_zero.hpp	Wed Jul 05 17:04:56 2017 +0200
@@ -1,6 +1,6 @@
 /*
  * Copyright 2003-2007 Sun Microsystems, Inc.  All Rights Reserved.
- * Copyright 2008 Red Hat, Inc.
+ * Copyright 2008, 2009 Red Hat, Inc.
  * 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,7 +41,7 @@
 // |  ...               |
 
 class SharkFrame : public ZeroFrame {
-  friend class SharkFunction;
+  friend class SharkStack;
 
  private:
   SharkFrame() : ZeroFrame() {
--- a/hotspot/src/os/linux/vm/os_linux.cpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/os/linux/vm/os_linux.cpp	Wed Jul 05 17:04:56 2017 +0200
@@ -223,8 +223,8 @@
                      "environment on Linux when /proc filesystem is not mounted.";
 
 void os::Linux::initialize_system_info() {
-  _processor_count = sysconf(_SC_NPROCESSORS_CONF);
-  if (_processor_count == 1) {
+  set_processor_count(sysconf(_SC_NPROCESSORS_CONF));
+  if (processor_count() == 1) {
     pid_t pid = os::Linux::gettid();
     char fname[32];
     jio_snprintf(fname, sizeof(fname), "/proc/%d", pid);
@@ -236,7 +236,7 @@
     }
   }
   _physical_memory = (julong)sysconf(_SC_PHYS_PAGES) * (julong)sysconf(_SC_PAGESIZE);
-  assert(_processor_count > 0, "linux error");
+  assert(processor_count() > 0, "linux error");
 }
 
 void os::init_system_properties_values() {
@@ -4683,6 +4683,7 @@
   // Return immediately if a permit is available.
   if (_counter > 0) {
       _counter = 0 ;
+      OrderAccess::fence();
       return ;
   }
 
@@ -4725,6 +4726,7 @@
     _counter = 0;
     status = pthread_mutex_unlock(_mutex);
     assert (status == 0, "invariant") ;
+    OrderAccess::fence();
     return;
   }
 
@@ -4765,6 +4767,7 @@
     jt->java_suspend_self();
   }
 
+  OrderAccess::fence();
 }
 
 void Parker::unpark() {
--- a/hotspot/src/os/solaris/dtrace/libjvm_db.c	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/os/solaris/dtrace/libjvm_db.c	Wed Jul 05 17:04:56 2017 +0200
@@ -937,54 +937,56 @@
   return err;
 }
 
-static int
-scopeDesc_chain(Nmethod_t *N)
-{
+static int scopeDesc_chain(Nmethod_t *N) {
   int32_t decode_offset = 0;
   int32_t err;
 
-  if (debug > 2)
-      fprintf(stderr, "\t scopeDesc_chain: BEGIN\n");
+  if (debug > 2) {
+    fprintf(stderr, "\t scopeDesc_chain: BEGIN\n");
+  }
 
   err = ps_pread(N->J->P, N->pc_desc + OFFSET_PcDesc_scope_decode_offset,
                  &decode_offset, SZ32);
   CHECK_FAIL(err);
 
   while (decode_offset > 0) {
-      if (debug > 2)
-          fprintf(stderr, "\t scopeDesc_chain: decode_offset: %#x\n", decode_offset);
+    Vframe_t *vf = &N->vframes[N->vf_cnt];
 
-      Vframe_t *vf = &N->vframes[N->vf_cnt];
+    if (debug > 2) {
+      fprintf(stderr, "\t scopeDesc_chain: decode_offset: %#x\n", decode_offset);
+    }
+
+    err = scope_desc_at(N, decode_offset, vf);
+    CHECK_FAIL(err);
 
-      err = scope_desc_at(N, decode_offset, vf);
-      CHECK_FAIL(err);
+    if (vf->methodIdx > N->oops_len) {
+      fprintf(stderr, "\t scopeDesc_chain: (methodIdx > oops_len) !\n");
+      return -1;
+    }
+    err = read_pointer(N->J, N->nm + N->oops_beg + (vf->methodIdx-1)*POINTER_SIZE,
+                       &vf->methodOop);
+    CHECK_FAIL(err);
 
-      if (vf->methodIdx > N->oops_len) {
-          fprintf(stderr, "\t scopeDesc_chain: (methodIdx > oops_len) !\n");
-          return -1;
-      }
-      err = read_pointer(N->J, N->nm + N->oops_beg + (vf->methodIdx-1)*POINTER_SIZE,
-                               &vf->methodOop);
+    if (vf->methodOop) {
+      N->vf_cnt++;
+      err = line_number_from_bci(N->J, vf);
       CHECK_FAIL(err);
-
-      if (vf->methodOop) {
-          N->vf_cnt++;
-          err = line_number_from_bci(N->J, vf);
-          CHECK_FAIL(err);
-          if (debug > 2) {
-              fprintf(stderr, "\t scopeDesc_chain: methodOop: %#8llx, line: %ld\n",
-                              vf->methodOop, vf->line);
-          }
+      if (debug > 2) {
+        fprintf(stderr, "\t scopeDesc_chain: methodOop: %#8llx, line: %ld\n",
+                vf->methodOop, vf->line);
       }
-      decode_offset = vf->sender_decode_offset;
+    }
+    decode_offset = vf->sender_decode_offset;
   }
-  if (debug > 2)
-      fprintf(stderr, "\t scopeDesc_chain: END \n\n");
+  if (debug > 2) {
+    fprintf(stderr, "\t scopeDesc_chain: END \n\n");
+  }
   return PS_OK;
 
  fail:
-  if (debug)
-      fprintf(stderr, "\t scopeDesc_chain: FAIL \n\n");
+  if (debug) {
+    fprintf(stderr, "\t scopeDesc_chain: FAIL \n\n");
+  }
   return err;
 }
 
--- a/hotspot/src/os/solaris/vm/os_solaris.cpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/os/solaris/vm/os_solaris.cpp	Wed Jul 05 17:04:56 2017 +0200
@@ -457,7 +457,7 @@
 
 
 void os::Solaris::initialize_system_info() {
-  _processor_count = sysconf(_SC_NPROCESSORS_CONF);
+  set_processor_count(sysconf(_SC_NPROCESSORS_CONF));
   _processors_online = sysconf (_SC_NPROCESSORS_ONLN);
   _physical_memory = (julong)sysconf(_SC_PHYS_PAGES) * (julong)sysconf(_SC_PAGESIZE);
 }
@@ -5803,6 +5803,7 @@
   // Return immediately if a permit is available.
   if (_counter > 0) {
       _counter = 0 ;
+      OrderAccess::fence();
       return ;
   }
 
@@ -5846,6 +5847,7 @@
     _counter = 0;
     status = os::Solaris::mutex_unlock(_mutex);
     assert (status == 0, "invariant") ;
+    OrderAccess::fence();
     return;
   }
 
@@ -5892,6 +5894,7 @@
     jt->java_suspend_self();
   }
 
+  OrderAccess::fence();
 }
 
 void Parker::unpark() {
--- a/hotspot/src/os/windows/vm/os_windows.cpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/os/windows/vm/os_windows.cpp	Wed Jul 05 17:04:56 2017 +0200
@@ -3150,7 +3150,7 @@
   _vm_allocation_granularity = si.dwAllocationGranularity;
   _processor_type  = si.dwProcessorType;
   _processor_level = si.wProcessorLevel;
-  _processor_count = si.dwNumberOfProcessors;
+  set_processor_count(si.dwNumberOfProcessors);
 
   MEMORYSTATUSEX ms;
   ms.dwLength = sizeof(ms);
--- a/hotspot/src/os_cpu/linux_x86/vm/globals_linux_x86.hpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/os_cpu/linux_x86/vm/globals_linux_x86.hpp	Wed Jul 05 17:04:56 2017 +0200
@@ -22,10 +22,9 @@
  *
  */
 
-//
 // Sets the default values for platform dependent flags used by the runtime system.
 // (see globals.hpp)
-//
+
 define_pd_global(bool, DontYieldALot,            false);
 #ifdef AMD64
 define_pd_global(intx, ThreadStackSize,          1024); // 0 => use system default
@@ -39,11 +38,10 @@
 #endif // AMD64
 
 define_pd_global(intx, CompilerThreadStackSize,  0);
-define_pd_global(intx, SurvivorRatio,            8);
 
-define_pd_global(uintx, JVMInvokeMethodSlack,    8192);
+define_pd_global(uintx,JVMInvokeMethodSlack,     8192);
 
 // Only used on 64 bit platforms
-define_pd_global(uintx, HeapBaseMinAddress,      2*G);
+define_pd_global(uintx,HeapBaseMinAddress,       2*G);
 // Only used on 64 bit Windows platforms
 define_pd_global(bool, UseVectoredExceptions,    false);
--- a/hotspot/src/os_cpu/solaris_x86/vm/globals_solaris_x86.hpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/os_cpu/solaris_x86/vm/globals_solaris_x86.hpp	Wed Jul 05 17:04:56 2017 +0200
@@ -22,31 +22,25 @@
  *
  */
 
-//
 // Sets the default values for platform dependent flags used by the runtime system.
 // (see globals.hpp)
-//
+
 define_pd_global(bool, DontYieldALot,            true); // Determined in the design center
 #ifdef AMD64
 define_pd_global(intx, ThreadStackSize,          1024); // 0 => use system default
 define_pd_global(intx, VMThreadStackSize,        1024);
-define_pd_global(intx, SurvivorRatio,            6);
-define_pd_global(uintx, JVMInvokeMethodSlack,    8*K);
+define_pd_global(uintx,JVMInvokeMethodSlack,     8*K);
 #else
-//  UseStackBanging is not pd
-// define_pd_global(bool, UseStackBanging,          true);
-
 // ThreadStackSize 320 allows TaggedStackInterpreter and a couple of test cases
 // to run while keeping the number of threads that can be created high.
 define_pd_global(intx, ThreadStackSize,          320);
 define_pd_global(intx, VMThreadStackSize,        512);
-define_pd_global(intx, SurvivorRatio,            8);
-define_pd_global(uintx, JVMInvokeMethodSlack,    10*K);
+define_pd_global(uintx,JVMInvokeMethodSlack,     10*K);
 #endif // AMD64
 
 define_pd_global(intx, CompilerThreadStackSize,  0);
 
 // Only used on 64 bit platforms
-define_pd_global(uintx, HeapBaseMinAddress,      256*M);
+define_pd_global(uintx,HeapBaseMinAddress,       256*M);
 // Only used on 64 bit Windows platforms
 define_pd_global(bool, UseVectoredExceptions,    false);
--- a/hotspot/src/os_cpu/windows_x86/vm/globals_windows_x86.hpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/os_cpu/windows_x86/vm/globals_windows_x86.hpp	Wed Jul 05 17:04:56 2017 +0200
@@ -22,10 +22,9 @@
  *
  */
 
-//
 // Sets the default values for platform dependent flags used by the runtime system.
 // (see globals.hpp)
-//
+
 define_pd_global(bool, DontYieldALot,            false);
 
 // Default stack size on Windows is determined by the executable (java.exe
@@ -35,8 +34,6 @@
 define_pd_global(intx, ThreadStackSize,          0); // 0 => use system default
 define_pd_global(intx, VMThreadStackSize,        0); // 0 => use system default
 
-define_pd_global(intx, SurvivorRatio,            8);
-
 #ifdef ASSERT
 define_pd_global(intx, CompilerThreadStackSize,  1024);
 #else
--- a/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp	Wed Jul 05 17:04:56 2017 +0200
@@ -365,7 +365,7 @@
     if (_next_loop_index < 31) _next_loop_index++;
   } else {
     // block already marked as loop header
-    assert(is_power_of_2(_loop_map.at(block->block_id())), "exactly one bit must be set");
+    assert(is_power_of_2((unsigned int)_loop_map.at(block->block_id())), "exactly one bit must be set");
   }
 }
 
--- a/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp	Wed Jul 05 17:04:56 2017 +0200
@@ -1855,12 +1855,26 @@
     addr = new LIR_Address(base_op, index_op->as_jint(), dst_type);
   } else {
 #ifdef X86
+#ifdef _LP64
+    if (!index_op->is_illegal() && index_op->type() == T_INT) {
+      LIR_Opr tmp = new_pointer_register();
+      __ convert(Bytecodes::_i2l, index_op, tmp);
+      index_op = tmp;
+    }
+#endif
     addr = new LIR_Address(base_op, index_op, LIR_Address::Scale(log2_scale), 0, dst_type);
 #else
     if (index_op->is_illegal() || log2_scale == 0) {
+#ifdef _LP64
+      if (!index_op->is_illegal() && index_op->type() == T_INT) {
+        LIR_Opr tmp = new_pointer_register();
+        __ convert(Bytecodes::_i2l, index_op, tmp);
+        index_op = tmp;
+      }
+#endif
       addr = new LIR_Address(base_op, index_op, dst_type);
     } else {
-      LIR_Opr tmp = new_register(T_INT);
+      LIR_Opr tmp = new_pointer_register();
       __ shift_left(index_op, log2_scale, tmp);
       addr = new LIR_Address(base_op, tmp, dst_type);
     }
@@ -1915,10 +1929,25 @@
   LIR_Opr index_op = idx.result();
   if (log2_scale != 0) {
     // temporary fix (platform dependent code without shift on Intel would be better)
-    index_op = new_register(T_INT);
-    __ move(idx.result(), index_op);
+    index_op = new_pointer_register();
+#ifdef _LP64
+    if(idx.result()->type() == T_INT) {
+      __ convert(Bytecodes::_i2l, idx.result(), index_op);
+    } else {
+#endif
+      __ move(idx.result(), index_op);
+#ifdef _LP64
+    }
+#endif
     __ shift_left(index_op, log2_scale, index_op);
   }
+#ifdef _LP64
+  else if(!index_op->is_illegal() && index_op->type() == T_INT) {
+    LIR_Opr tmp = new_pointer_register();
+    __ convert(Bytecodes::_i2l, index_op, tmp);
+    index_op = tmp;
+  }
+#endif
 
   LIR_Address* addr = new LIR_Address(base_op, index_op, x->basic_type());
   __ move(value.result(), addr);
--- a/hotspot/src/share/vm/c1/c1_LinearScan.cpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/share/vm/c1/c1_LinearScan.cpp	Wed Jul 05 17:04:56 2017 +0200
@@ -2464,6 +2464,10 @@
 
     case T_LONG: // fall through
     case T_DOUBLE: {
+#ifdef _LP64
+      scope_values->append(&_int_0_scope_value);
+      scope_values->append(new ConstantLongValue(c->as_jlong_bits()));
+#else
       if (hi_word_offset_in_bytes > lo_word_offset_in_bytes) {
         scope_values->append(new ConstantIntValue(c->as_jint_hi_bits()));
         scope_values->append(new ConstantIntValue(c->as_jint_lo_bits()));
@@ -2471,7 +2475,7 @@
         scope_values->append(new ConstantIntValue(c->as_jint_lo_bits()));
         scope_values->append(new ConstantIntValue(c->as_jint_hi_bits()));
       }
-
+#endif
       return 2;
     }
 
@@ -2503,17 +2507,18 @@
   } else if (opr->is_single_cpu()) {
     bool is_oop = opr->is_oop_register();
     int cache_idx = opr->cpu_regnr() * 2 + (is_oop ? 1 : 0);
+    Location::Type int_loc_type = NOT_LP64(Location::normal) LP64_ONLY(Location::int_in_long);
 
     ScopeValue* sv = _scope_value_cache.at(cache_idx);
     if (sv == NULL) {
-      Location::Type loc_type = is_oop ? Location::oop : Location::normal;
+      Location::Type loc_type = is_oop ? Location::oop : int_loc_type;
       VMReg rname = frame_map()->regname(opr);
       sv = new LocationValue(Location::new_reg_loc(loc_type, rname));
       _scope_value_cache.at_put(cache_idx, sv);
     }
 
     // check if cached value is correct
-    DEBUG_ONLY(assert_equal(sv, new LocationValue(Location::new_reg_loc(is_oop ? Location::oop : Location::normal, frame_map()->regname(opr)))));
+    DEBUG_ONLY(assert_equal(sv, new LocationValue(Location::new_reg_loc(is_oop ? Location::oop : int_loc_type, frame_map()->regname(opr)))));
 
     scope_values->append(sv);
     return 1;
--- a/hotspot/src/share/vm/ci/bcEscapeAnalyzer.hpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/share/vm/ci/bcEscapeAnalyzer.hpp	Wed Jul 05 17:04:56 2017 +0200
@@ -61,9 +61,11 @@
   BCEscapeAnalyzer* _parent;
   int               _level;
 
+ public:
   class  ArgumentMap;
   class  StateInfo;
 
+ private:
   // helper functions
   bool is_argument(int i)    { return i >= 0 && i < _arg_size; }
 
--- a/hotspot/src/share/vm/ci/ciEnv.cpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/share/vm/ci/ciEnv.cpp	Wed Jul 05 17:04:56 2017 +0200
@@ -46,6 +46,9 @@
 ciInstanceKlass* ciEnv::_Thread;
 ciInstanceKlass* ciEnv::_OutOfMemoryError;
 ciInstanceKlass* ciEnv::_String;
+ciInstanceKlass* ciEnv::_StringBuffer;
+ciInstanceKlass* ciEnv::_StringBuilder;
+ciInstanceKlass* ciEnv::_Integer;
 
 ciSymbol*        ciEnv::_unloaded_cisymbol = NULL;
 ciInstanceKlass* ciEnv::_unloaded_ciinstance_klass = NULL;
@@ -110,6 +113,8 @@
   _ArrayIndexOutOfBoundsException_instance = NULL;
   _ArrayStoreException_instance = NULL;
   _ClassCastException_instance = NULL;
+  _the_null_string = NULL;
+  _the_min_jint_string = NULL;
 }
 
 ciEnv::ciEnv(Arena* arena) {
@@ -163,6 +168,8 @@
   _ArrayIndexOutOfBoundsException_instance = NULL;
   _ArrayStoreException_instance = NULL;
   _ClassCastException_instance = NULL;
+  _the_null_string = NULL;
+  _the_min_jint_string = NULL;
 }
 
 ciEnv::~ciEnv() {
@@ -248,6 +255,22 @@
   return _ClassCastException_instance;
 }
 
+ciInstance* ciEnv::the_null_string() {
+  if (_the_null_string == NULL) {
+    VM_ENTRY_MARK;
+    _the_null_string = get_object(Universe::the_null_string())->as_instance();
+  }
+  return _the_null_string;
+}
+
+ciInstance* ciEnv::the_min_jint_string() {
+  if (_the_min_jint_string == NULL) {
+    VM_ENTRY_MARK;
+    _the_min_jint_string = get_object(Universe::the_min_jint_string())->as_instance();
+  }
+  return _the_min_jint_string;
+}
+
 // ------------------------------------------------------------------
 // ciEnv::get_method_from_handle
 ciMethod* ciEnv::get_method_from_handle(jobject method) {
@@ -690,10 +713,8 @@
   ciInstanceKlass* declared_holder = get_instance_klass_for_declared_method_holder(holder);
 
   // Get the method's name and signature.
-  int nt_index = cpool->name_and_type_ref_index_at(index);
-  int sig_index = cpool->signature_ref_index_at(nt_index);
   symbolOop name_sym = cpool->name_ref_at(index);
-  symbolOop sig_sym = cpool->symbol_at(sig_index);
+  symbolOop sig_sym  = cpool->signature_ref_at(index);
 
   if (holder_is_accessible) { // Our declared holder is loaded.
     instanceKlass* lookup = declared_holder->get_instanceKlass();
--- a/hotspot/src/share/vm/ci/ciEnv.hpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/share/vm/ci/ciEnv.hpp	Wed Jul 05 17:04:56 2017 +0200
@@ -82,6 +82,9 @@
   static ciInstanceKlass* _Thread;
   static ciInstanceKlass* _OutOfMemoryError;
   static ciInstanceKlass* _String;
+  static ciInstanceKlass* _StringBuffer;
+  static ciInstanceKlass* _StringBuilder;
+  static ciInstanceKlass* _Integer;
 
   static ciSymbol*        _unloaded_cisymbol;
   static ciInstanceKlass* _unloaded_ciinstance_klass;
@@ -97,6 +100,9 @@
   ciInstance* _ArrayStoreException_instance;
   ciInstance* _ClassCastException_instance;
 
+  ciInstance* _the_null_string;      // The Java string "null"
+  ciInstance* _the_min_jint_string; // The Java string "-2147483648"
+
   // Look up a klass by name from a particular class loader (the accessor's).
   // If require_local, result must be defined in that class loader, or NULL.
   // If !require_local, a result from remote class loader may be reported,
@@ -310,6 +316,15 @@
   ciInstanceKlass* String_klass() {
     return _String;
   }
+  ciInstanceKlass* StringBuilder_klass() {
+    return _StringBuilder;
+  }
+  ciInstanceKlass* StringBuffer_klass() {
+    return _StringBuffer;
+  }
+  ciInstanceKlass* Integer_klass() {
+    return _Integer;
+  }
   ciInstance* NullPointerException_instance() {
     assert(_NullPointerException_instance != NULL, "initialization problem");
     return _NullPointerException_instance;
@@ -324,6 +339,9 @@
   ciInstance* ArrayStoreException_instance();
   ciInstance* ClassCastException_instance();
 
+  ciInstance* the_null_string();
+  ciInstance* the_min_jint_string();
+
   static ciSymbol* unloaded_cisymbol() {
     return _unloaded_cisymbol;
   }
--- a/hotspot/src/share/vm/ci/ciInstanceKlass.cpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/share/vm/ci/ciInstanceKlass.cpp	Wed Jul 05 17:04:56 2017 +0200
@@ -341,6 +341,20 @@
 }
 
 // ------------------------------------------------------------------
+// ciInstanceKlass::get_field_by_name
+ciField* ciInstanceKlass::get_field_by_name(ciSymbol* name, ciSymbol* signature, bool is_static) {
+  VM_ENTRY_MARK;
+  instanceKlass* k = get_instanceKlass();
+  fieldDescriptor fd;
+  klassOop def = k->find_field(name->get_symbolOop(), signature->get_symbolOop(), is_static, &fd);
+  if (def == NULL) {
+    return NULL;
+  }
+  ciField* field = new (CURRENT_THREAD_ENV->arena()) ciField(&fd);
+  return field;
+}
+
+// ------------------------------------------------------------------
 // ciInstanceKlass::non_static_fields.
 
 class NonStaticFieldFiller: public FieldClosure {
--- a/hotspot/src/share/vm/ci/ciInstanceKlass.hpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/share/vm/ci/ciInstanceKlass.hpp	Wed Jul 05 17:04:56 2017 +0200
@@ -148,6 +148,7 @@
 
   ciInstanceKlass* get_canonical_holder(int offset);
   ciField* get_field_by_offset(int field_offset, bool is_static);
+  ciField* get_field_by_name(ciSymbol* name, ciSymbol* signature, bool is_static);
 
   GrowableArray<ciField*>* non_static_fields();
 
--- a/hotspot/src/share/vm/ci/ciObjectFactory.cpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/share/vm/ci/ciObjectFactory.cpp	Wed Jul 05 17:04:56 2017 +0200
@@ -168,6 +168,15 @@
   ciEnv::_String =
     get(SystemDictionary::string_klass())
       ->as_instance_klass();
+  ciEnv::_StringBuffer =
+    get(SystemDictionary::stringBuffer_klass())
+      ->as_instance_klass();
+  ciEnv::_StringBuilder =
+    get(SystemDictionary::StringBuilder_klass())
+      ->as_instance_klass();
+  ciEnv::_Integer =
+    get(SystemDictionary::int_klass())
+      ->as_instance_klass();
 
   for (int len = -1; len != _ci_objects->length(); ) {
     len = _ci_objects->length();
--- a/hotspot/src/share/vm/classfile/classFileParser.cpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/share/vm/classfile/classFileParser.cpp	Wed Jul 05 17:04:56 2017 +0200
@@ -2511,23 +2511,12 @@
       fac_ptr->nonstatic_byte_count -= 1;
       (*fields_ptr)->ushort_at_put(i + instanceKlass::signature_index_offset,
                                    word_sig_index);
-      if (wordSize == jintSize) {
-        fac_ptr->nonstatic_word_count += 1;
-      } else {
-        fac_ptr->nonstatic_double_count += 1;
-      }
-
-      FieldAllocationType atype = (FieldAllocationType) (*fields_ptr)->ushort_at(i+4);
+      fac_ptr->nonstatic_word_count += 1;
+
+      FieldAllocationType atype = (FieldAllocationType) (*fields_ptr)->ushort_at(i + instanceKlass::low_offset);
       assert(atype == NONSTATIC_BYTE, "");
       FieldAllocationType new_atype = NONSTATIC_WORD;
-      if (wordSize > jintSize) {
-        if (Universe::field_type_should_be_aligned(T_LONG)) {
-          atype = NONSTATIC_ALIGNED_DOUBLE;
-        } else {
-          atype = NONSTATIC_DOUBLE;
-        }
-      }
-      (*fields_ptr)->ushort_at_put(i+4, new_atype);
+      (*fields_ptr)->ushort_at_put(i + instanceKlass::low_offset, new_atype);
 
       found_vmentry = true;
       break;
@@ -3085,7 +3074,7 @@
     int len = fields->length();
     for (int i = 0; i < len; i += instanceKlass::next_offset) {
       int real_offset;
-      FieldAllocationType atype = (FieldAllocationType) fields->ushort_at(i+4);
+      FieldAllocationType atype = (FieldAllocationType) fields->ushort_at(i + instanceKlass::low_offset);
       switch (atype) {
         case STATIC_OOP:
           real_offset = next_static_oop_offset;
@@ -3173,8 +3162,8 @@
         default:
           ShouldNotReachHere();
       }
-      fields->short_at_put(i+4, extract_low_short_from_int(real_offset) );
-      fields->short_at_put(i+5, extract_high_short_from_int(real_offset) );
+      fields->short_at_put(i + instanceKlass::low_offset,  extract_low_short_from_int(real_offset));
+      fields->short_at_put(i + instanceKlass::high_offset, extract_high_short_from_int(real_offset));
     }
 
     // Size of instances
@@ -3766,8 +3755,9 @@
 }
 
 bool ClassFileParser::is_supported_version(u2 major, u2 minor) {
-  u2 max_version = JDK_Version::is_gte_jdk17x_version() ?
-    JAVA_MAX_SUPPORTED_VERSION : JAVA_6_VERSION;
+  u2 max_version =
+    JDK_Version::is_gte_jdk17x_version() ? JAVA_MAX_SUPPORTED_VERSION :
+    (JDK_Version::is_gte_jdk16x_version() ? JAVA_6_VERSION : JAVA_1_5_VERSION);
   return (major >= JAVA_MIN_SUPPORTED_VERSION) &&
          (major <= max_version) &&
          ((major != max_version) ||
--- a/hotspot/src/share/vm/classfile/javaClasses.cpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/share/vm/classfile/javaClasses.cpp	Wed Jul 05 17:04:56 2017 +0200
@@ -1124,8 +1124,7 @@
     if (_dirty && _methods != NULL) {
       BarrierSet* bs = Universe::heap()->barrier_set();
       assert(bs->has_write_ref_array_opt(), "Barrier set must have ref array opt");
-      bs->write_ref_array(MemRegion((HeapWord*)_methods->base(),
-                                    _methods->array_size()));
+      bs->write_ref_array((HeapWord*)_methods->base(), _methods->length());
       _dirty = false;
     }
   }
@@ -2430,15 +2429,15 @@
 }
 
 
-// Support for sun_dyn_CallSiteImpl
-
-int sun_dyn_CallSiteImpl::_type_offset;
-int sun_dyn_CallSiteImpl::_target_offset;
-int sun_dyn_CallSiteImpl::_vmmethod_offset;
-
-void sun_dyn_CallSiteImpl::compute_offsets() {
+// Support for java_dyn_CallSite
+
+int java_dyn_CallSite::_type_offset;
+int java_dyn_CallSite::_target_offset;
+int java_dyn_CallSite::_vmmethod_offset;
+
+void java_dyn_CallSite::compute_offsets() {
   if (!EnableInvokeDynamic)  return;
-  klassOop k = SystemDictionary::CallSiteImpl_klass();
+  klassOop k = SystemDictionary::CallSite_klass();
   if (k != NULL) {
     compute_offset(_type_offset,   k, vmSymbols::type_name(),   vmSymbols::java_dyn_MethodType_signature(), true);
     compute_offset(_target_offset, k, vmSymbols::target_name(), vmSymbols::java_dyn_MethodHandle_signature(), true);
@@ -2446,23 +2445,23 @@
   }
 }
 
-oop sun_dyn_CallSiteImpl::type(oop site) {
+oop java_dyn_CallSite::type(oop site) {
   return site->obj_field(_type_offset);
 }
 
-oop sun_dyn_CallSiteImpl::target(oop site) {
+oop java_dyn_CallSite::target(oop site) {
   return site->obj_field(_target_offset);
 }
 
-void sun_dyn_CallSiteImpl::set_target(oop site, oop target) {
+void java_dyn_CallSite::set_target(oop site, oop target) {
   site->obj_field_put(_target_offset, target);
 }
 
-oop sun_dyn_CallSiteImpl::vmmethod(oop site) {
+oop java_dyn_CallSite::vmmethod(oop site) {
   return site->obj_field(_vmmethod_offset);
 }
 
-void sun_dyn_CallSiteImpl::set_vmmethod(oop site, oop ref) {
+void java_dyn_CallSite::set_vmmethod(oop site, oop ref) {
   site->obj_field_put(_vmmethod_offset, ref);
 }
 
@@ -2811,7 +2810,7 @@
     java_dyn_MethodTypeForm::compute_offsets();
   }
   if (EnableInvokeDynamic) {
-    sun_dyn_CallSiteImpl::compute_offsets();
+    java_dyn_CallSite::compute_offsets();
   }
   java_security_AccessControlContext::compute_offsets();
   // Initialize reflection classes. The layouts of these classes
--- a/hotspot/src/share/vm/classfile/javaClasses.hpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/share/vm/classfile/javaClasses.hpp	Wed Jul 05 17:04:56 2017 +0200
@@ -1061,9 +1061,9 @@
 };
 
 
-// Interface to sun.dyn.CallSiteImpl objects
+// Interface to java.dyn.CallSite objects
 
-class sun_dyn_CallSiteImpl: AllStatic {
+class java_dyn_CallSite: AllStatic {
   friend class JavaClasses;
 
 private:
--- a/hotspot/src/share/vm/classfile/systemDictionary.cpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/share/vm/classfile/systemDictionary.cpp	Wed Jul 05 17:04:56 2017 +0200
@@ -99,6 +99,15 @@
   return java_lang_Class::parallelCapable(class_loader());
 }
 // ----------------------------------------------------------------------------
+// ParallelDefineClass flag does not apply to bootclass loader
+bool SystemDictionary::is_parallelDefine(Handle class_loader) {
+   if (class_loader.is_null()) return false;
+   if (AllowParallelDefineClass && java_lang_Class::parallelCapable(class_loader())) {
+     return true;
+   }
+   return false;
+}
+// ----------------------------------------------------------------------------
 // Resolving of classes
 
 // Forwards to resolve_or_null
@@ -724,13 +733,13 @@
       // Do actual loading
       k = load_instance_class(name, class_loader, THREAD);
 
-      // For UnsyncloadClass and AllowParallelDefineClass only:
+      // For UnsyncloadClass only
       // If they got a linkageError, check if a parallel class load succeeded.
       // If it did, then for bytecode resolution the specification requires
       // that we return the same result we did for the other thread, i.e. the
       // successfully loaded instanceKlass
       // Should not get here for classloaders that support parallelism
-      // with the new cleaner mechanism
+      // with the new cleaner mechanism, even with AllowParallelDefineClass
       // Bootstrap goes through here to allow for an extra guarantee check
       if (UnsyncloadClass || (class_loader.is_null())) {
         if (k.is_null() && HAS_PENDING_EXCEPTION
@@ -1483,14 +1492,17 @@
 }
 
 // Support parallel classloading
-// Initial implementation for bootstrap classloader
-// For custom class loaders that support parallel classloading,
+// All parallel class loaders, including bootstrap classloader
+// lock a placeholder entry for this class/class_loader pair
+// to allow parallel defines of different classes for this class loader
 // With AllowParallelDefine flag==true, in case they do not synchronize around
 // FindLoadedClass/DefineClass, calls, we check for parallel
 // loading for them, wait if a defineClass is in progress
 // and return the initial requestor's results
+// This flag does not apply to the bootstrap classloader.
 // With AllowParallelDefine flag==false, call through to define_instance_class
 // which will throw LinkageError: duplicate class definition.
+// False is the requested default.
 // For better performance, the class loaders should synchronize
 // findClass(), i.e. FindLoadedClass/DefineClassIfAbsent or they
 // potentially waste time reading and parsing the bytestream.
@@ -1511,9 +1523,11 @@
   {
     MutexLocker mu(SystemDictionary_lock, THREAD);
     // First check if class already defined
-    klassOop check = find_class(d_index, d_hash, name_h, class_loader);
-    if (check != NULL) {
-      return(instanceKlassHandle(THREAD, check));
+    if (UnsyncloadClass || (is_parallelDefine(class_loader))) {
+      klassOop check = find_class(d_index, d_hash, name_h, class_loader);
+      if (check != NULL) {
+        return(instanceKlassHandle(THREAD, check));
+      }
     }
 
     // Acquire define token for this class/classloader
@@ -1529,7 +1543,7 @@
     // Only special cases allow parallel defines and can use other thread's results
     // Other cases fall through, and may run into duplicate defines
     // caught by finding an entry in the SystemDictionary
-    if ((UnsyncloadClass || AllowParallelDefineClass) && (probe->instanceKlass() != NULL)) {
+    if ((UnsyncloadClass || is_parallelDefine(class_loader)) && (probe->instanceKlass() != NULL)) {
         probe->remove_seen_thread(THREAD, PlaceholderTable::DEFINE_CLASS);
         placeholders()->find_and_remove(p_index, p_hash, name_h, class_loader, THREAD);
         SystemDictionary_lock->notify_all();
@@ -1973,7 +1987,7 @@
   WKID indy_group_end   = WK_KLASS_ENUM_NAME(Dynamic_klass);
   initialize_wk_klasses_until(indy_group_start, scan, CHECK);
   if (EnableInvokeDynamic) {
-    initialize_wk_klasses_through(indy_group_start, scan, CHECK);
+    initialize_wk_klasses_through(indy_group_end, scan, CHECK);
   }
   if (_well_known_klasses[indy_group_start] == NULL) {
     // Skip the rest of the dynamic typing classes, if Linkage is not loaded.
@@ -2404,7 +2418,7 @@
                                                 methodHandle mh_invdyn,
                                                 TRAPS) {
   Handle empty;
-  // call sun.dyn.CallSiteImpl::makeSite(caller, name, mtype, cmid, cbci)
+  // call java.dyn.CallSite::makeSite(caller, name, mtype, cmid, cbci)
   oop name_str_oop = StringTable::intern(name(), CHECK_(empty)); // not a handle!
   JavaCallArguments args(Handle(THREAD, caller->java_mirror()));
   args.push_oop(name_str_oop);
@@ -2413,17 +2427,19 @@
   args.push_int(caller_bci);
   JavaValue result(T_OBJECT);
   JavaCalls::call_static(&result,
-                         SystemDictionary::CallSiteImpl_klass(),
+                         SystemDictionary::CallSite_klass(),
                          vmSymbols::makeSite_name(), vmSymbols::makeSite_signature(),
                          &args, CHECK_(empty));
   oop call_site_oop = (oop) result.get_jobject();
   assert(call_site_oop->is_oop()
-         /*&& sun_dyn_CallSiteImpl::is_instance(call_site_oop)*/, "must be sane");
-  sun_dyn_CallSiteImpl::set_vmmethod(call_site_oop, mh_invdyn());
+         /*&& java_dyn_CallSite::is_instance(call_site_oop)*/, "must be sane");
+  java_dyn_CallSite::set_vmmethod(call_site_oop, mh_invdyn());
   if (TraceMethodHandles) {
+#ifndef PRODUCT
     tty->print_cr("Linked invokedynamic bci=%d site="INTPTR_FORMAT":", caller_bci, call_site_oop);
     call_site_oop->print();
     tty->cr();
+#endif //PRODUCT
   }
   return call_site_oop;
 }
@@ -2436,9 +2452,17 @@
 
   instanceKlassHandle ik(THREAD, caller());
 
-  if (ik->bootstrap_method() != NULL) {
-    return Handle(THREAD, ik->bootstrap_method());
+  oop boot_method_oop = ik->bootstrap_method();
+  if (boot_method_oop != NULL) {
+    if (TraceMethodHandles) {
+      tty->print_cr("bootstrap method for "PTR_FORMAT" cached as "PTR_FORMAT":", ik(), boot_method_oop);
+    }
+    NOT_PRODUCT(if (!boot_method_oop->is_oop()) { tty->print_cr("*** boot MH of "PTR_FORMAT" = "PTR_FORMAT, ik(), boot_method_oop); ik()->print(); });
+    assert(boot_method_oop->is_oop()
+           && java_dyn_MethodHandle::is_instance(boot_method_oop), "must be sane");
+    return Handle(THREAD, boot_method_oop);
   }
+  boot_method_oop = NULL;  // GC safety
 
   // call java.dyn.Linkage::findBootstrapMethod(caller, sbk)
   JavaCallArguments args(Handle(THREAD, ik->java_mirror()));
@@ -2452,9 +2476,18 @@
                          vmSymbols::findBootstrapMethod_name(),
                          vmSymbols::findBootstrapMethod_signature(),
                          &args, CHECK_(empty));
-  oop boot_method_oop = (oop) result.get_jobject();
+  boot_method_oop = (oop) result.get_jobject();
 
   if (boot_method_oop != NULL) {
+    if (TraceMethodHandles) {
+#ifndef PRODUCT
+      tty->print_cr("--------");
+      tty->print_cr("bootstrap method for "PTR_FORMAT" computed as "PTR_FORMAT":", ik(), boot_method_oop);
+      ik()->print();
+      boot_method_oop->print();
+      tty->print_cr("========");
+#endif //PRODUCT
+    }
     assert(boot_method_oop->is_oop()
            && java_dyn_MethodHandle::is_instance(boot_method_oop), "must be sane");
     // probably no race conditions, but let's be careful:
@@ -2463,6 +2496,14 @@
     else
       boot_method_oop = ik->bootstrap_method();
   } else {
+    if (TraceMethodHandles) {
+#ifndef PRODUCT
+      tty->print_cr("--------");
+      tty->print_cr("bootstrap method for "PTR_FORMAT" computed as NULL:", ik());
+      ik()->print();
+      tty->print_cr("========");
+#endif //PRODUCT
+    }
     boot_method_oop = ik->bootstrap_method();
   }
 
--- a/hotspot/src/share/vm/classfile/systemDictionary.hpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/share/vm/classfile/systemDictionary.hpp	Wed Jul 05 17:04:56 2017 +0200
@@ -144,13 +144,13 @@
   template(WrongMethodTypeException_klass, java_dyn_WrongMethodTypeException, Opt) \
   template(Linkage_klass,                java_dyn_Linkage,               Opt) \
   template(CallSite_klass,               java_dyn_CallSite,              Opt) \
-  template(CallSiteImpl_klass,           sun_dyn_CallSiteImpl,     Opt) \
   template(Dynamic_klass,                java_dyn_Dynamic,               Opt) \
   /* Note: MethodHandle must be first, and Dynamic last in group */           \
                                                                               \
   template(vector_klass,                 java_util_Vector,               Pre) \
   template(hashtable_klass,              java_util_Hashtable,            Pre) \
   template(stringBuffer_klass,           java_lang_StringBuffer,         Pre) \
+  template(StringBuilder_klass,          java_lang_StringBuilder,        Pre) \
                                                                               \
   /* It's NULL in non-1.4 JDKs. */                                            \
   template(stackTraceElement_klass,      java_lang_StackTraceElement,    Opt) \
@@ -578,6 +578,7 @@
   static Handle compute_loader_lock_object(Handle class_loader, TRAPS);
   static void check_loader_lock_contention(Handle loader_lock, TRAPS);
   static bool is_parallelCapable(Handle class_loader);
+  static bool is_parallelDefine(Handle class_loader);
 
   static klassOop find_shared_class(symbolHandle class_name);
 
--- a/hotspot/src/share/vm/classfile/verifier.cpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/share/vm/classfile/verifier.cpp	Wed Jul 05 17:04:56 2017 +0200
@@ -1903,17 +1903,8 @@
   verify_cp_type(index, cp, types, CHECK_VERIFY(this));
 
   // Get method name and signature
-  symbolHandle method_name;
-  symbolHandle method_sig;
-  if (opcode == Bytecodes::_invokedynamic) {
-    int name_index = cp->name_ref_index_at(index);
-    int sig_index  = cp->signature_ref_index_at(index);
-    method_name = symbolHandle(THREAD, cp->symbol_at(name_index));
-    method_sig  = symbolHandle(THREAD, cp->symbol_at(sig_index));
-  } else {
-    method_name = symbolHandle(THREAD, cp->name_ref_at(index));
-    method_sig  = symbolHandle(THREAD, cp->signature_ref_at(index));
-  }
+  symbolHandle method_name(THREAD, cp->name_ref_at(index));
+  symbolHandle method_sig(THREAD, cp->signature_ref_at(index));
 
   if (!SignatureVerifier::is_valid_method_signature(method_sig)) {
     class_format_error(
--- a/hotspot/src/share/vm/classfile/vmSymbols.cpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/share/vm/classfile/vmSymbols.cpp	Wed Jul 05 17:04:56 2017 +0200
@@ -303,6 +303,11 @@
   const int neg = JVM_ACC_STATIC | JVM_ACC_SYNCHRONIZED;
   return (flags & (req | neg)) == req;
 }
+inline bool match_F_Y(jshort flags) {
+  const int req = JVM_ACC_SYNCHRONIZED;
+  const int neg = JVM_ACC_STATIC;
+  return (flags & (req | neg)) == req;
+}
 inline bool match_F_RN(jshort flags) {
   const int req = JVM_ACC_NATIVE;
   const int neg = JVM_ACC_STATIC | JVM_ACC_SYNCHRONIZED;
@@ -361,6 +366,7 @@
   const char* sname = vmSymbols::name_for(signature_for(id));
   const char* fname = "";
   switch (flags_for(id)) {
+  case F_Y:  fname = "synchronized ";  break;
   case F_RN: fname = "native ";        break;
   case F_SN: fname = "native static "; break;
   case F_S:  fname = "static ";        break;
--- a/hotspot/src/share/vm/classfile/vmSymbols.hpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/share/vm/classfile/vmSymbols.hpp	Wed Jul 05 17:04:56 2017 +0200
@@ -84,6 +84,7 @@
   template(java_lang_reflect_Field,                   "java/lang/reflect/Field")                  \
   template(java_lang_reflect_Array,                   "java/lang/reflect/Array")                  \
   template(java_lang_StringBuffer,                    "java/lang/StringBuffer")                   \
+  template(java_lang_StringBuilder,                   "java/lang/StringBuilder")                  \
   template(java_lang_CharSequence,                    "java/lang/CharSequence")                   \
   template(java_security_AccessControlContext,        "java/security/AccessControlContext")       \
   template(java_security_ProtectionDomain,            "java/security/ProtectionDomain")           \
@@ -104,6 +105,7 @@
   template(java_lang_AssertionStatusDirectives,       "java/lang/AssertionStatusDirectives")      \
   template(sun_jkernel_DownloadManager,               "sun/jkernel/DownloadManager")              \
   template(getBootClassPathEntryForClass_name,        "getBootClassPathEntryForClass")            \
+  template(setBootClassLoaderHook_name,               "setBootClassLoaderHook")                   \
                                                                                                   \
   /* class file format tags */                                                                    \
   template(tag_source_file,                           "SourceFile")                               \
@@ -233,10 +235,9 @@
   template(sun_dyn_AdapterMethodHandle,               "sun/dyn/AdapterMethodHandle")              \
   template(sun_dyn_BoundMethodHandle,                 "sun/dyn/BoundMethodHandle")                \
   template(sun_dyn_DirectMethodHandle,                "sun/dyn/DirectMethodHandle")               \
-  template(sun_dyn_CallSiteImpl,                      "sun/dyn/CallSiteImpl")                     \
   template(makeImpl_name,                             "makeImpl") /*MethodType::makeImpl*/        \
   template(makeImpl_signature,    "(Ljava/lang/Class;[Ljava/lang/Class;ZZ)Ljava/dyn/MethodType;") \
-  template(makeSite_name,                             "makeSite") /*CallSiteImpl::makeImpl*/       \
+  template(makeSite_name,                             "makeSite") /*CallSite::makeSite*/          \
   template(makeSite_signature,    "(Ljava/lang/Class;Ljava/lang/String;Ljava/dyn/MethodType;II)Ljava/dyn/CallSite;") \
   template(findBootstrapMethod_name,                  "findBootstrapMethod")                      \
   template(findBootstrapMethod_signature, "(Ljava/lang/Class;Ljava/lang/Class;)Ljava/dyn/MethodHandle;") \
@@ -335,6 +336,7 @@
   template(ptypes_name,                               "ptypes")                                   \
   template(form_name,                                 "form")                                     \
   template(erasedType_name,                           "erasedType")                               \
+  template(append_name,                               "append")                                   \
                                                                                                   \
   /* non-intrinsic name/signature pairs: */                                                       \
   template(register_method_name,                      "register")                                 \
@@ -416,6 +418,13 @@
   template(string_signature,                          "Ljava/lang/String;")                                       \
   template(reference_signature,                       "Ljava/lang/ref/Reference;")                                \
   template(concurrenthashmap_signature,               "Ljava/util/concurrent/ConcurrentHashMap;")                 \
+  template(String_StringBuilder_signature,            "(Ljava/lang/String;)Ljava/lang/StringBuilder;")            \
+  template(int_StringBuilder_signature,               "(I)Ljava/lang/StringBuilder;")                             \
+  template(char_StringBuilder_signature,              "(C)Ljava/lang/StringBuilder;")                             \
+  template(String_StringBuffer_signature,             "(Ljava/lang/String;)Ljava/lang/StringBuffer;")             \
+  template(int_StringBuffer_signature,                "(I)Ljava/lang/StringBuffer;")                              \
+  template(char_StringBuffer_signature,               "(C)Ljava/lang/StringBuffer;")                              \
+  template(int_String_signature,                      "(I)Ljava/lang/String;")                                    \
   /* signature symbols needed by intrinsics */                                                                    \
   VM_INTRINSICS_DO(VM_INTRINSIC_IGNORE, VM_SYMBOL_IGNORE, VM_SYMBOL_IGNORE, template, VM_ALIAS_IGNORE)            \
                                                                                                                   \
@@ -815,10 +824,34 @@
     /*the compiler does have special inlining code for these; bytecode inline is just fine */                           \
                                                                                                                         \
   do_intrinsic(_fillInStackTrace,         java_lang_Throwable, fillInStackTrace_name, void_throwable_signature,  F_RNY) \
-                                                                                                                        \
-  do_intrinsic(_Object_init,              java_lang_Object, object_initializer_name, void_method_signature,      F_R)   \
-  /*    (symbol object_initializer_name defined above) */                                                               \
-                                                                                                                        \
+                                                                                                                          \
+  do_intrinsic(_StringBuilder_void,   java_lang_StringBuilder, object_initializer_name, void_method_signature,     F_R)   \
+  do_intrinsic(_StringBuilder_int,    java_lang_StringBuilder, object_initializer_name, int_void_signature,        F_R)   \
+  do_intrinsic(_StringBuilder_String, java_lang_StringBuilder, object_initializer_name, string_void_signature,     F_R)   \
+                                                                                                                          \
+  do_intrinsic(_StringBuilder_append_char,   java_lang_StringBuilder, append_name, char_StringBuilder_signature,   F_R)   \
+  do_intrinsic(_StringBuilder_append_int,    java_lang_StringBuilder, append_name, int_StringBuilder_signature,    F_R)   \
+  do_intrinsic(_StringBuilder_append_String, java_lang_StringBuilder, append_name, String_StringBuilder_signature, F_R)   \
+                                                                                                                          \
+  do_intrinsic(_StringBuilder_toString, java_lang_StringBuilder, toString_name, void_string_signature,             F_R)   \
+                                                                                                                          \
+  do_intrinsic(_StringBuffer_void,   java_lang_StringBuffer, object_initializer_name, void_method_signature,       F_R)   \
+  do_intrinsic(_StringBuffer_int,    java_lang_StringBuffer, object_initializer_name, int_void_signature,          F_R)   \
+  do_intrinsic(_StringBuffer_String, java_lang_StringBuffer, object_initializer_name, string_void_signature,       F_R)   \
+                                                                                                                          \
+  do_intrinsic(_StringBuffer_append_char,   java_lang_StringBuffer, append_name, char_StringBuffer_signature,      F_Y)   \
+  do_intrinsic(_StringBuffer_append_int,    java_lang_StringBuffer, append_name, int_StringBuffer_signature,       F_Y)   \
+  do_intrinsic(_StringBuffer_append_String, java_lang_StringBuffer, append_name, String_StringBuffer_signature,    F_Y)   \
+                                                                                                                          \
+  do_intrinsic(_StringBuffer_toString,  java_lang_StringBuffer, toString_name, void_string_signature,              F_Y)   \
+                                                                                                                          \
+  do_intrinsic(_Integer_toString,      java_lang_Integer, toString_name, int_String_signature,                     F_S)   \
+                                                                                                                          \
+  do_intrinsic(_String_String, java_lang_String, object_initializer_name, string_void_signature,                   F_R)   \
+                                                                                                                          \
+  do_intrinsic(_Object_init,              java_lang_Object, object_initializer_name, void_method_signature,        F_R)   \
+  /*    (symbol object_initializer_name defined above) */                                                                 \
+                                                                                                                          \
   do_intrinsic(_invoke,                   java_lang_reflect_Method, invoke_name, object_array_object_object_signature, F_R) \
   /*   (symbols invoke_name and invoke_signature defined above) */                                                      \
                                                                                                                         \
@@ -946,11 +979,12 @@
   enum Flags {
     // AccessFlags syndromes relevant to intrinsics.
     F_none = 0,
-    F_R,                        // !static        !synchronized (R="regular")
-    F_S,                        //  static        !synchronized
-    F_RN,                       // !static native !synchronized
-    F_SN,                       //  static native !synchronized
-    F_RNY                       // !static native  synchronized
+    F_R,                        // !static ?native !synchronized (R="regular")
+    F_S,                        //  static ?native !synchronized
+    F_Y,                        // !static ?native  synchronized
+    F_RN,                       // !static  native !synchronized
+    F_SN,                       //  static  native !synchronized
+    F_RNY                       // !static  native  synchronized
   };
 
 public:
--- a/hotspot/src/share/vm/code/dependencies.cpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/share/vm/code/dependencies.cpp	Wed Jul 05 17:04:56 2017 +0200
@@ -1528,19 +1528,23 @@
   int nsup = 0, nint = 0;
   for (ContextStream str(*this); str.next(); ) {
     klassOop k = str.klass();
-    switch (str._change_type) {
+    switch (str.change_type()) {
     case Change_new_type:
       tty->print_cr("  dependee = %s", instanceKlass::cast(k)->external_name());
       break;
     case Change_new_sub:
-      if (!WizardMode)
-           ++nsup;
-      else tty->print_cr("  context super = %s", instanceKlass::cast(k)->external_name());
+      if (!WizardMode) {
+        ++nsup;
+      } else {
+        tty->print_cr("  context super = %s", instanceKlass::cast(k)->external_name());
+      }
       break;
     case Change_new_impl:
-      if (!WizardMode)
-           ++nint;
-      else tty->print_cr("  context interface = %s", instanceKlass::cast(k)->external_name());
+      if (!WizardMode) {
+        ++nint;
+      } else {
+        tty->print_cr("  context interface = %s", instanceKlass::cast(k)->external_name());
+      }
       break;
     }
   }
--- a/hotspot/src/share/vm/code/dependencies.hpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/share/vm/code/dependencies.hpp	Wed Jul 05 17:04:56 2017 +0200
@@ -470,7 +470,7 @@
 // super types can be context types for a relevant dependency, which the
 // new type could invalidate.
 class DepChange : public StackObj {
- private:
+ public:
   enum ChangeType {
     NO_CHANGE = 0,              // an uninvolved klass
     Change_new_type,            // a newly loaded type
@@ -480,6 +480,7 @@
     Start_Klass = CHANGE_LIMIT  // internal indicator for ContextStream
   };
 
+ private:
   // each change set is rooted in exactly one new type (at present):
   KlassHandle _new_type;
 
@@ -510,15 +511,15 @@
   // }
   class ContextStream : public StackObj {
    private:
-    DepChange&       _changes;
+    DepChange&  _changes;
     friend class DepChange;
 
     // iteration variables:
-    ChangeType            _change_type;
-    klassOop              _klass;
-    objArrayOop           _ti_base;    // i.e., transitive_interfaces
-    int                   _ti_index;
-    int                   _ti_limit;
+    ChangeType  _change_type;
+    klassOop    _klass;
+    objArrayOop _ti_base;    // i.e., transitive_interfaces
+    int         _ti_index;
+    int         _ti_limit;
 
     // start at the beginning:
     void start() {
@@ -530,11 +531,11 @@
       _ti_limit = 0;
     }
 
+   public:
     ContextStream(DepChange& changes)
       : _changes(changes)
     { start(); }
 
-   public:
     ContextStream(DepChange& changes, No_Safepoint_Verifier& nsv)
       : _changes(changes)
       // the nsv argument makes it safe to hold oops like _klass
@@ -542,6 +543,7 @@
 
     bool next();
 
+    ChangeType change_type()     { return _change_type; }
     klassOop   klass()           { return _klass; }
   };
   friend class DepChange::ContextStream;
--- a/hotspot/src/share/vm/code/nmethod.cpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/share/vm/code/nmethod.cpp	Wed Jul 05 17:04:56 2017 +0200
@@ -414,9 +414,8 @@
 }
 
 const char* nmethod::compile_kind() const {
-  if (method() == NULL)    return "unloaded";
-  if (is_native_method())  return "c2n";
   if (is_osr_method())     return "osr";
+  if (method() != NULL && is_native_method())  return "c2n";
   return NULL;
 }
 
@@ -1127,6 +1126,9 @@
   }
   flags.state = unloaded;
 
+  // Log the unloading.
+  log_state_change();
+
   // The methodOop is gone at this point
   assert(_method == NULL, "Tautology");
 
@@ -1137,8 +1139,6 @@
 
 void nmethod::invalidate_osr_method() {
   assert(_entry_bci != InvocationEntryBci, "wrong kind of nmethod");
-  if (_entry_bci != InvalidOSREntryBci)
-    inc_decompile_count();
   // Remove from list of active nmethods
   if (method() != NULL)
     instanceKlass::cast(method()->method_holder())->remove_osr_nmethod(this);
@@ -1146,59 +1146,63 @@
   _entry_bci = InvalidOSREntryBci;
 }
 
-void nmethod::log_state_change(int state) const {
+void nmethod::log_state_change() const {
   if (LogCompilation) {
     if (xtty != NULL) {
       ttyLocker ttyl;  // keep the following output all in one block
-      xtty->begin_elem("make_not_entrant %sthread='" UINTX_FORMAT "'",
-                       (state == zombie ? "zombie='1' " : ""),
-                       os::current_thread_id());
+      if (flags.state == unloaded) {
+        xtty->begin_elem("make_unloaded thread='" UINTX_FORMAT "'",
+                         os::current_thread_id());
+      } else {
+        xtty->begin_elem("make_not_entrant thread='" UINTX_FORMAT "'%s",
+                         os::current_thread_id(),
+                         (flags.state == zombie ? " zombie='1'" : ""));
+      }
       log_identity(xtty);
       xtty->stamp();
       xtty->end_elem();
     }
   }
-  if (PrintCompilation) {
-    print_on(tty, state == zombie ? "made zombie " : "made not entrant ");
+  if (PrintCompilation && flags.state != unloaded) {
+    print_on(tty, flags.state == zombie ? "made zombie " : "made not entrant ");
     tty->cr();
   }
 }
 
 // Common functionality for both make_not_entrant and make_zombie
-void nmethod::make_not_entrant_or_zombie(int state) {
+bool nmethod::make_not_entrant_or_zombie(int state) {
   assert(state == zombie || state == not_entrant, "must be zombie or not_entrant");
 
-  // Code for an on-stack-replacement nmethod is removed when a class gets unloaded.
-  // They never become zombie/non-entrant, so the nmethod sweeper will never remove
-  // them. Instead the entry_bci is set to InvalidOSREntryBci, so the osr nmethod
-  // will never be used anymore. That the nmethods only gets removed when class unloading
-  // happens, make life much simpler, since the nmethods are not just going to disappear
-  // out of the blue.
-  if (is_osr_method()) {
-    if (osr_entry_bci() != InvalidOSREntryBci) {
-      // only log this once
-      log_state_change(state);
-    }
-    invalidate_osr_method();
-    return;
+  // If the method is already zombie there is nothing to do
+  if (is_zombie()) {
+    return false;
   }
 
-  // If the method is already zombie or set to the state we want, nothing to do
-  if (is_zombie() || (state == not_entrant && is_not_entrant())) {
-    return;
-  }
-
-  log_state_change(state);
-
   // Make sure the nmethod is not flushed in case of a safepoint in code below.
   nmethodLocker nml(this);
 
   {
+    // invalidate osr nmethod before acquiring the patching lock since
+    // they both acquire leaf locks and we don't want a deadlock.
+    // This logic is equivalent to the logic below for patching the
+    // verified entry point of regular methods.
+    if (is_osr_method()) {
+      // this effectively makes the osr nmethod not entrant
+      invalidate_osr_method();
+    }
+
     // Enter critical section.  Does not block for safepoint.
     MutexLockerEx pl(Patching_lock, Mutex::_no_safepoint_check_flag);
+
+    if (flags.state == state) {
+      // another thread already performed this transition so nothing
+      // to do, but return false to indicate this.
+      return false;
+    }
+
     // The caller can be calling the method statically or through an inline
     // cache call.
-    if (!is_not_entrant()) {
+    if (!is_osr_method() && !is_not_entrant()) {
       NativeJump::patch_verified_entry(entry_point(), verified_entry_point(),
                   SharedRuntime::get_handle_wrong_method_stub());
       assert (NativeJump::instruction_size == nmethod::_zombie_instruction_size, "");
@@ -1217,6 +1221,10 @@
 
     // Change state
     flags.state = state;
+
+    // Log the transition once
+    log_state_change();
+
   } // leave critical region under Patching_lock
 
   if (state == not_entrant) {
@@ -1240,7 +1248,6 @@
   // It's a true state change, so mark the method as decompiled.
   inc_decompile_count();
 
-
   // zombie only - if a JVMTI agent has enabled the CompiledMethodUnload event
   // and it hasn't already been reported for this nmethod then report it now.
   // (the event may have been reported earilier if the GC marked it for unloading).
@@ -1268,7 +1275,7 @@
 
   // Check whether method got unloaded at a safepoint before this,
   // if so we can skip the flushing steps below
-  if (method() == NULL) return;
+  if (method() == NULL) return true;
 
   // Remove nmethod from method.
   // We need to check if both the _code and _from_compiled_code_entry_point
@@ -1282,6 +1289,8 @@
     HandleMark hm;
     method()->clear_code();
   }
+
+  return true;
 }
 
 
--- a/hotspot/src/share/vm/code/nmethod.hpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/share/vm/code/nmethod.hpp	Wed Jul 05 17:04:56 2017 +0200
@@ -252,7 +252,9 @@
   void* operator new(size_t size, int nmethod_size);
 
   const char* reloc_string_for(u_char* begin, u_char* end);
-  void make_not_entrant_or_zombie(int state);
+  // Returns true if this thread changed the state of the nmethod or
+  // false if another thread performed the transition.
+  bool make_not_entrant_or_zombie(int state);
   void inc_decompile_count();
 
   // used to check that writes to nmFlags are done consistently.
@@ -375,10 +377,12 @@
   bool  is_zombie() const                         { return flags.state == zombie; }
   bool  is_unloaded() const                       { return flags.state == unloaded;   }
 
-  // Make the nmethod non entrant. The nmethod will continue to be alive.
-  // It is used when an uncommon trap happens.
-  void  make_not_entrant()                        { make_not_entrant_or_zombie(not_entrant); }
-  void  make_zombie()                             { make_not_entrant_or_zombie(zombie); }
+  // Make the nmethod non entrant. The nmethod will continue to be
+  // alive.  It is used when an uncommon trap happens.  Returns true
+  // if this thread changed the state of the nmethod or false if
+  // another thread performed the transition.
+  bool  make_not_entrant()                        { return make_not_entrant_or_zombie(not_entrant); }
+  bool  make_zombie()                             { return make_not_entrant_or_zombie(zombie); }
 
   // used by jvmti to track if the unload event has been reported
   bool  unload_reported()                         { return _unload_reported; }
@@ -563,7 +567,7 @@
   // Logging
   void log_identity(xmlStream* log) const;
   void log_new_nmethod() const;
-  void log_state_change(int state) const;
+  void log_state_change() const;
 
   // Prints a comment for one native instruction (reloc info, pc desc)
   void print_code_comment_on(outputStream* st, int column, address begin, address end);
--- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp	Wed Jul 05 17:04:56 2017 +0200
@@ -709,7 +709,8 @@
 
   // Support for parallelizing survivor space rescan
   if (CMSParallelRemarkEnabled && CMSParallelSurvivorRemarkEnabled) {
-    size_t max_plab_samples = MaxNewSize/((SurvivorRatio+2)*MinTLABSize);
+    size_t max_plab_samples = cp->max_gen0_size()/
+                                ((SurvivorRatio+2)*MinTLABSize);
     _survivor_plab_array  = NEW_C_HEAP_ARRAY(ChunkArray, ParallelGCThreads);
     _survivor_chunk_array = NEW_C_HEAP_ARRAY(HeapWord*, 2*max_plab_samples);
     _cursor               = NEW_C_HEAP_ARRAY(size_t, ParallelGCThreads);
--- a/hotspot/src/share/vm/gc_implementation/g1/collectionSetChooser.cpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/share/vm/gc_implementation/g1/collectionSetChooser.cpp	Wed Jul 05 17:04:56 2017 +0200
@@ -351,9 +351,16 @@
 CollectionSetChooser::printSortedHeapRegions() {
   gclog_or_tty->print_cr("Printing %d Heap Regions sorted by amount of known garbage",
                 _numMarkedRegions);
+
+  DEBUG_ONLY(int marked_count = 0;)
   for (int i = 0; i < _markedRegions.length(); i++) {
-    printHeapRegion(_markedRegions.at(i));
+    HeapRegion* r = _markedRegions.at(i);
+    if (r != NULL) {
+      printHeapRegion(r);
+      DEBUG_ONLY(marked_count++;)
+    }
   }
+  assert(marked_count == _numMarkedRegions, "must be");
   gclog_or_tty->print_cr("Done sorted heap region print");
 }
 
--- a/hotspot/src/share/vm/gc_implementation/g1/concurrentG1Refine.cpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentG1Refine.cpp	Wed Jul 05 17:04:56 2017 +0200
@@ -42,28 +42,49 @@
   _n_periods(0),
   _threads(NULL), _n_threads(0)
 {
-  if (G1ConcRefine) {
-    _n_threads = (int)thread_num();
-    if (_n_threads > 0) {
-      _threads = NEW_C_HEAP_ARRAY(ConcurrentG1RefineThread*, _n_threads);
-      int worker_id_offset = (int)DirtyCardQueueSet::num_par_ids();
-      ConcurrentG1RefineThread *next = NULL;
-      for (int i = _n_threads - 1; i >= 0; i--) {
-        ConcurrentG1RefineThread* t = new ConcurrentG1RefineThread(this, next, worker_id_offset, i);
-        assert(t != NULL, "Conc refine should have been created");
-        assert(t->cg1r() == this, "Conc refine thread should refer to this");
-        _threads[i] = t;
-        next = t;
-      }
-    }
+
+  // Ergomonically select initial concurrent refinement parameters
+  if (FLAG_IS_DEFAULT(G1ConcRefineGreenZone)) {
+    FLAG_SET_DEFAULT(G1ConcRefineGreenZone, MAX2<int>(ParallelGCThreads, 1));
+  }
+  set_green_zone(G1ConcRefineGreenZone);
+
+  if (FLAG_IS_DEFAULT(G1ConcRefineYellowZone)) {
+    FLAG_SET_DEFAULT(G1ConcRefineYellowZone, green_zone() * 3);
+  }
+  set_yellow_zone(MAX2<int>(G1ConcRefineYellowZone, green_zone()));
+
+  if (FLAG_IS_DEFAULT(G1ConcRefineRedZone)) {
+    FLAG_SET_DEFAULT(G1ConcRefineRedZone, yellow_zone() * 2);
+  }
+  set_red_zone(MAX2<int>(G1ConcRefineRedZone, yellow_zone()));
+  _n_worker_threads = thread_num();
+  // We need one extra thread to do the young gen rset size sampling.
+  _n_threads = _n_worker_threads + 1;
+  reset_threshold_step();
+
+  _threads = NEW_C_HEAP_ARRAY(ConcurrentG1RefineThread*, _n_threads);
+  int worker_id_offset = (int)DirtyCardQueueSet::num_par_ids();
+  ConcurrentG1RefineThread *next = NULL;
+  for (int i = _n_threads - 1; i >= 0; i--) {
+    ConcurrentG1RefineThread* t = new ConcurrentG1RefineThread(this, next, worker_id_offset, i);
+    assert(t != NULL, "Conc refine should have been created");
+    assert(t->cg1r() == this, "Conc refine thread should refer to this");
+    _threads[i] = t;
+    next = t;
   }
 }
 
-size_t ConcurrentG1Refine::thread_num() {
-  if (G1ConcRefine) {
-    return (G1ParallelRSetThreads > 0) ? G1ParallelRSetThreads : ParallelGCThreads;
+void ConcurrentG1Refine::reset_threshold_step() {
+  if (FLAG_IS_DEFAULT(G1ConcRefineThresholdStep)) {
+    _thread_threshold_step = (yellow_zone() - green_zone()) / (worker_thread_num() + 1);
+  } else {
+    _thread_threshold_step = G1ConcRefineThresholdStep;
   }
-  return 0;
+}
+
+int ConcurrentG1Refine::thread_num() {
+  return MAX2<int>((G1ParallelRSetThreads > 0) ? G1ParallelRSetThreads : ParallelGCThreads, 1);
 }
 
 void ConcurrentG1Refine::init() {
@@ -123,6 +144,15 @@
   }
 }
 
+void ConcurrentG1Refine::reinitialize_threads() {
+  reset_threshold_step();
+  if (_threads != NULL) {
+    for (int i = 0; i < _n_threads; i++) {
+      _threads[i]->initialize();
+    }
+  }
+}
+
 ConcurrentG1Refine::~ConcurrentG1Refine() {
   if (G1ConcRSLogCacheSize > 0) {
     assert(_card_counts != NULL, "Logic");
@@ -384,4 +414,3 @@
     st->cr();
   }
 }
-
--- a/hotspot/src/share/vm/gc_implementation/g1/concurrentG1Refine.hpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentG1Refine.hpp	Wed Jul 05 17:04:56 2017 +0200
@@ -29,6 +29,31 @@
 class ConcurrentG1Refine: public CHeapObj {
   ConcurrentG1RefineThread** _threads;
   int _n_threads;
+  int _n_worker_threads;
+ /*
+  * The value of the update buffer queue length falls into one of 3 zones:
+  * green, yellow, red. If the value is in [0, green) nothing is
+  * done, the buffers are left unprocessed to enable the caching effect of the
+  * dirtied cards. In the yellow zone [green, yellow) the concurrent refinement
+  * threads are gradually activated. In [yellow, red) all threads are
+  * running. If the length becomes red (max queue length) the mutators start
+  * processing the buffers.
+  *
+  * There are some interesting cases (with G1AdaptiveConcRefine turned off):
+  * 1) green = yellow = red = 0. In this case the mutator will process all
+  *    buffers. Except for those that are created by the deferred updates
+  *    machinery during a collection.
+  * 2) green = 0. Means no caching. Can be a good way to minimize the
+  *    amount of time spent updating rsets during a collection.
+  */
+  int _green_zone;
+  int _yellow_zone;
+  int _red_zone;
+
+  int _thread_threshold_step;
+
+  // Reset the threshold step value based of the current zone boundaries.
+  void reset_threshold_step();
 
   // The cache for card refinement.
   bool   _use_cache;
@@ -147,6 +172,8 @@
   void init(); // Accomplish some initialization that has to wait.
   void stop();
 
+  void reinitialize_threads();
+
   // Iterate over the conc refine threads
   void threads_do(ThreadClosure *tc);
 
@@ -178,7 +205,20 @@
 
   void clear_and_record_card_counts();
 
-  static size_t thread_num();
+  static int thread_num();
 
   void print_worker_threads_on(outputStream* st) const;
+
+  void set_green_zone(int x)  { _green_zone = x;  }
+  void set_yellow_zone(int x) { _yellow_zone = x; }
+  void set_red_zone(int x)    { _red_zone = x;    }
+
+  int green_zone() const      { return _green_zone;  }
+  int yellow_zone() const     { return _yellow_zone; }
+  int red_zone() const        { return _red_zone;    }
+
+  int total_thread_num() const  { return _n_threads;        }
+  int worker_thread_num() const { return _n_worker_threads; }
+
+  int thread_threshold_step() const { return _thread_threshold_step; }
 };
--- a/hotspot/src/share/vm/gc_implementation/g1/concurrentG1RefineThread.cpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentG1RefineThread.cpp	Wed Jul 05 17:04:56 2017 +0200
@@ -25,10 +25,6 @@
 #include "incls/_precompiled.incl"
 #include "incls/_concurrentG1RefineThread.cpp.incl"
 
-// ======= Concurrent Mark Thread ========
-
-// The CM thread is created when the G1 garbage collector is used
-
 ConcurrentG1RefineThread::
 ConcurrentG1RefineThread(ConcurrentG1Refine* cg1r, ConcurrentG1RefineThread *next,
                          int worker_id_offset, int worker_id) :
@@ -37,19 +33,42 @@
   _worker_id(worker_id),
   _active(false),
   _next(next),
+  _monitor(NULL),
   _cg1r(cg1r),
-  _vtime_accum(0.0),
-  _interval_ms(5.0)
+  _vtime_accum(0.0)
 {
+
+  // Each thread has its own monitor. The i-th thread is responsible for signalling
+  // to thread i+1 if the number of buffers in the queue exceeds a threashold for this
+  // thread. Monitors are also used to wake up the threads during termination.
+  // The 0th worker in notified by mutator threads and has a special monitor.
+  // The last worker is used for young gen rset size sampling.
+  if (worker_id > 0) {
+    _monitor = new Monitor(Mutex::nonleaf, "Refinement monitor", true);
+  } else {
+    _monitor = DirtyCardQ_CBL_mon;
+  }
+  initialize();
   create_and_start();
 }
 
+void ConcurrentG1RefineThread::initialize() {
+  if (_worker_id < cg1r()->worker_thread_num()) {
+    // Current thread activation threshold
+    _threshold = MIN2<int>(cg1r()->thread_threshold_step() * (_worker_id + 1) + cg1r()->green_zone(),
+                           cg1r()->yellow_zone());
+    // A thread deactivates once the number of buffer reached a deactivation threshold
+    _deactivation_threshold = MAX2<int>(_threshold - cg1r()->thread_threshold_step(), cg1r()->green_zone());
+  } else {
+    set_active(true);
+  }
+}
+
 void ConcurrentG1RefineThread::sample_young_list_rs_lengths() {
   G1CollectedHeap* g1h = G1CollectedHeap::heap();
   G1CollectorPolicy* g1p = g1h->g1_policy();
   if (g1p->adaptive_young_list_length()) {
     int regions_visited = 0;
-
     g1h->young_list_rs_length_sampling_init();
     while (g1h->young_list_rs_length_sampling_more()) {
       g1h->young_list_rs_length_sampling_next();
@@ -70,99 +89,121 @@
   }
 }
 
-void ConcurrentG1RefineThread::run() {
-  initialize_in_thread();
+void ConcurrentG1RefineThread::run_young_rs_sampling() {
+  DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set();
   _vtime_start = os::elapsedVTime();
-  wait_for_universe_init();
+  while(!_should_terminate) {
+    _sts.join();
+    sample_young_list_rs_lengths();
+    _sts.leave();
 
-  while (!_should_terminate) {
-    DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set();
-    // Wait for completed log buffers to exist.
-    {
-      MutexLockerEx x(DirtyCardQ_CBL_mon, Mutex::_no_safepoint_check_flag);
-      while (((_worker_id == 0 && !dcqs.process_completed_buffers()) ||
-              (_worker_id > 0 && !is_active())) &&
-             !_should_terminate) {
-         DirtyCardQ_CBL_mon->wait(Mutex::_no_safepoint_check_flag);
-      }
-    }
-
-    if (_should_terminate) {
-      return;
+    if (os::supports_vtime()) {
+      _vtime_accum = (os::elapsedVTime() - _vtime_start);
+    } else {
+      _vtime_accum = 0.0;
     }
 
-    // Now we take them off (this doesn't hold locks while it applies
-    // closures.)  (If we did a full collection, then we'll do a full
-    // traversal.
-    _sts.join();
-    int n_logs = 0;
-    int lower_limit = 0;
-    double start_vtime_sec; // only used when G1SmoothConcRefine is on
-    int prev_buffer_num; // only used when G1SmoothConcRefine is on
-    // This thread activation threshold
-    int threshold = G1UpdateBufferQueueProcessingThreshold * _worker_id;
-    // Next thread activation threshold
-    int next_threshold = threshold + G1UpdateBufferQueueProcessingThreshold;
-    int deactivation_threshold = MAX2<int>(threshold - G1UpdateBufferQueueProcessingThreshold / 2, 0);
+    MutexLockerEx x(_monitor, Mutex::_no_safepoint_check_flag);
+    if (_should_terminate) {
+      break;
+    }
+    _monitor->wait(Mutex::_no_safepoint_check_flag, G1ConcRefineServiceInterval);
+  }
+}
 
-    if (G1SmoothConcRefine) {
-      lower_limit = 0;
-      start_vtime_sec = os::elapsedVTime();
-      prev_buffer_num = (int) dcqs.completed_buffers_num();
-    } else {
-      lower_limit = G1UpdateBufferQueueProcessingThreshold / 4; // For now.
+void ConcurrentG1RefineThread::wait_for_completed_buffers() {
+  DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set();
+  MutexLockerEx x(_monitor, Mutex::_no_safepoint_check_flag);
+  while (!_should_terminate && !is_active()) {
+    _monitor->wait(Mutex::_no_safepoint_check_flag);
+  }
+}
+
+bool ConcurrentG1RefineThread::is_active() {
+  DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set();
+  return _worker_id > 0 ? _active : dcqs.process_completed_buffers();
+}
+
+void ConcurrentG1RefineThread::activate() {
+  MutexLockerEx x(_monitor, Mutex::_no_safepoint_check_flag);
+  if (_worker_id > 0) {
+    if (G1TraceConcurrentRefinement) {
+      DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set();
+      gclog_or_tty->print_cr("G1-Refine-activated worker %d, on threshold %d, current %d",
+                             _worker_id, _threshold, (int)dcqs.completed_buffers_num());
     }
-    while (dcqs.apply_closure_to_completed_buffer(_worker_id + _worker_id_offset, lower_limit)) {
-      double end_vtime_sec;
-      double elapsed_vtime_sec;
-      int elapsed_vtime_ms;
-      int curr_buffer_num = (int) dcqs.completed_buffers_num();
+    set_active(true);
+  } else {
+    DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set();
+    dcqs.set_process_completed(true);
+  }
+  _monitor->notify();
+}
 
-      if (G1SmoothConcRefine) {
-        end_vtime_sec = os::elapsedVTime();
-        elapsed_vtime_sec = end_vtime_sec - start_vtime_sec;
-        elapsed_vtime_ms = (int) (elapsed_vtime_sec * 1000.0);
+void ConcurrentG1RefineThread::deactivate() {
+  MutexLockerEx x(_monitor, Mutex::_no_safepoint_check_flag);
+  if (_worker_id > 0) {
+    if (G1TraceConcurrentRefinement) {
+      DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set();
+      gclog_or_tty->print_cr("G1-Refine-deactivated worker %d, off threshold %d, current %d",
+                             _worker_id, _deactivation_threshold, (int)dcqs.completed_buffers_num());
+    }
+    set_active(false);
+  } else {
+    DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set();
+    dcqs.set_process_completed(false);
+  }
+}
+
+void ConcurrentG1RefineThread::run() {
+  initialize_in_thread();
+  wait_for_universe_init();
 
-        if (curr_buffer_num > prev_buffer_num ||
-            curr_buffer_num > next_threshold) {
-          decreaseInterval(elapsed_vtime_ms);
-        } else if (curr_buffer_num < prev_buffer_num) {
-          increaseInterval(elapsed_vtime_ms);
-        }
+  if (_worker_id >= cg1r()->worker_thread_num()) {
+    run_young_rs_sampling();
+    terminate();
+  }
+
+  _vtime_start = os::elapsedVTime();
+  while (!_should_terminate) {
+    DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set();
+
+    // Wait for work
+    wait_for_completed_buffers();
+
+    if (_should_terminate) {
+      break;
+    }
+
+    _sts.join();
+
+    do {
+      int curr_buffer_num = (int)dcqs.completed_buffers_num();
+      // If the number of the buffers falls down into the yellow zone,
+      // that means that the transition period after the evacuation pause has ended.
+      if (dcqs.completed_queue_padding() > 0 && curr_buffer_num <= cg1r()->yellow_zone()) {
+        dcqs.set_completed_queue_padding(0);
       }
-      if (_worker_id == 0) {
-        sample_young_list_rs_lengths();
-      } else if (curr_buffer_num < deactivation_threshold) {
+
+      if (_worker_id > 0 && curr_buffer_num <= _deactivation_threshold) {
         // If the number of the buffer has fallen below our threshold
         // we should deactivate. The predecessor will reactivate this
         // thread should the number of the buffers cross the threshold again.
-        MutexLockerEx x(DirtyCardQ_CBL_mon, Mutex::_no_safepoint_check_flag);
         deactivate();
-        if (G1TraceConcurrentRefinement) {
-          gclog_or_tty->print_cr("G1-Refine-deactivated worker %d", _worker_id);
-        }
         break;
       }
 
       // Check if we need to activate the next thread.
-      if (curr_buffer_num > next_threshold && _next != NULL && !_next->is_active()) {
-        MutexLockerEx x(DirtyCardQ_CBL_mon, Mutex::_no_safepoint_check_flag);
+      if (_next != NULL && !_next->is_active() && curr_buffer_num > _next->_threshold) {
         _next->activate();
-        DirtyCardQ_CBL_mon->notify_all();
-        if (G1TraceConcurrentRefinement) {
-          gclog_or_tty->print_cr("G1-Refine-activated worker %d", _next->_worker_id);
-        }
       }
+    } while (dcqs.apply_closure_to_completed_buffer(_worker_id + _worker_id_offset, cg1r()->green_zone()));
 
-      if (G1SmoothConcRefine) {
-        prev_buffer_num = curr_buffer_num;
-        _sts.leave();
-        os::sleep(Thread::current(), (jlong) _interval_ms, false);
-        _sts.join();
-        start_vtime_sec = os::elapsedVTime();
-      }
-      n_logs++;
+    // We can exit the loop above while being active if there was a yield request.
+    if (is_active()) {
+      deactivate();
     }
+
     _sts.leave();
 
     if (os::supports_vtime()) {
@@ -172,7 +213,6 @@
     }
   }
   assert(_should_terminate, "just checking");
-
   terminate();
 }
 
@@ -191,8 +231,8 @@
   }
 
   {
-    MutexLockerEx x(DirtyCardQ_CBL_mon, Mutex::_no_safepoint_check_flag);
-    DirtyCardQ_CBL_mon->notify_all();
+    MutexLockerEx x(_monitor, Mutex::_no_safepoint_check_flag);
+    _monitor->notify();
   }
 
   {
--- a/hotspot/src/share/vm/gc_implementation/g1/concurrentG1RefineThread.hpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentG1RefineThread.hpp	Wed Jul 05 17:04:56 2017 +0200
@@ -40,42 +40,36 @@
   // when the number of the rset update buffer crosses a certain threshold. A successor
   // would self-deactivate when the number of the buffers falls below the threshold.
   bool _active;
-  ConcurrentG1RefineThread *       _next;
- public:
-  virtual void run();
-
-  bool is_active()  { return _active;  }
-  void activate()   { _active = true;  }
-  void deactivate() { _active = false; }
-
- private:
-  ConcurrentG1Refine*              _cg1r;
-
-  double                           _interval_ms;
+  ConcurrentG1RefineThread* _next;
+  Monitor* _monitor;
+  ConcurrentG1Refine* _cg1r;
 
-  void decreaseInterval(int processing_time_ms) {
-    double min_interval_ms = (double) processing_time_ms;
-    _interval_ms = 0.8 * _interval_ms;
-    if (_interval_ms < min_interval_ms)
-      _interval_ms = min_interval_ms;
-  }
-  void increaseInterval(int processing_time_ms) {
-    double max_interval_ms = 9.0 * (double) processing_time_ms;
-    _interval_ms = 1.1 * _interval_ms;
-    if (max_interval_ms > 0 && _interval_ms > max_interval_ms)
-      _interval_ms = max_interval_ms;
-  }
+  int _thread_threshold_step;
+  // This thread activation threshold
+  int _threshold;
+  // This thread deactivation threshold
+  int _deactivation_threshold;
 
-  void sleepBeforeNextCycle();
+  void sample_young_list_rs_lengths();
+  void run_young_rs_sampling();
+  void wait_for_completed_buffers();
+
+  void set_active(bool x) { _active = x; }
+  bool is_active();
+  void activate();
+  void deactivate();
 
   // For use by G1CollectedHeap, which is a friend.
   static SuspendibleThreadSet* sts() { return &_sts; }
 
- public:
+public:
+  virtual void run();
   // Constructor
   ConcurrentG1RefineThread(ConcurrentG1Refine* cg1r, ConcurrentG1RefineThread* next,
                            int worker_id_offset, int worker_id);
 
+  void initialize();
+
   // Printing
   void print() const;
   void print_on(outputStream* st) const;
@@ -83,13 +77,10 @@
   // Total virtual time so far.
   double vtime_accum() { return _vtime_accum; }
 
-  ConcurrentG1Refine* cg1r()                     { return _cg1r;     }
-
-  void            sample_young_list_rs_lengths();
+  ConcurrentG1Refine* cg1r() { return _cg1r;     }
 
   // Yield for GC
-  void            yield();
-
+  void yield();
   // shutdown
   void stop();
 };
--- a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp	Wed Jul 05 17:04:56 2017 +0200
@@ -760,7 +760,6 @@
   rp->setup_policy(false); // snapshot the soft ref policy to be used in this cycle
 
   SATBMarkQueueSet& satb_mq_set = JavaThread::satb_mark_queue_set();
-  satb_mq_set.set_process_completed_threshold(G1SATBProcessCompletedThreshold);
   satb_mq_set.set_active_all_threads(true);
 
   // update_g1_committed() will be called at the end of an evac pause
--- a/hotspot/src/share/vm/gc_implementation/g1/dirtyCardQueue.cpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/share/vm/gc_implementation/g1/dirtyCardQueue.cpp	Wed Jul 05 17:04:56 2017 +0200
@@ -61,8 +61,8 @@
 #pragma warning( disable:4355 ) // 'this' : used in base member initializer list
 #endif // _MSC_VER
 
-DirtyCardQueueSet::DirtyCardQueueSet() :
-  PtrQueueSet(true /*notify_when_complete*/),
+DirtyCardQueueSet::DirtyCardQueueSet(bool notify_when_complete) :
+  PtrQueueSet(notify_when_complete),
   _closure(NULL),
   _shared_dirty_card_queue(this, true /*perm*/),
   _free_ids(NULL),
@@ -77,12 +77,12 @@
 }
 
 void DirtyCardQueueSet::initialize(Monitor* cbl_mon, Mutex* fl_lock,
+                                   int process_completed_threshold,
                                    int max_completed_queue,
                                    Mutex* lock, PtrQueueSet* fl_owner) {
-  PtrQueueSet::initialize(cbl_mon, fl_lock, max_completed_queue, fl_owner);
+  PtrQueueSet::initialize(cbl_mon, fl_lock, process_completed_threshold,
+                          max_completed_queue, fl_owner);
   set_buffer_size(G1UpdateBufferSize);
-  set_process_completed_threshold(G1UpdateBufferQueueProcessingThreshold);
-
   _shared_dirty_card_queue.set_lock(lock);
   _free_ids = new FreeIdSet((int) num_par_ids(), _cbl_mon);
 }
@@ -154,9 +154,10 @@
   return b;
 }
 
-DirtyCardQueueSet::CompletedBufferNode*
-DirtyCardQueueSet::get_completed_buffer_lock(int stop_at) {
-  CompletedBufferNode* nd = NULL;
+
+BufferNode*
+DirtyCardQueueSet::get_completed_buffer(int stop_at) {
+  BufferNode* nd = NULL;
   MutexLockerEx x(_cbl_mon, Mutex::_no_safepoint_check_flag);
 
   if ((int)_n_completed_buffers <= stop_at) {
@@ -166,53 +167,31 @@
 
   if (_completed_buffers_head != NULL) {
     nd = _completed_buffers_head;
-    _completed_buffers_head = nd->next;
+    _completed_buffers_head = nd->next();
     if (_completed_buffers_head == NULL)
       _completed_buffers_tail = NULL;
     _n_completed_buffers--;
+    assert(_n_completed_buffers >= 0, "Invariant");
   }
   debug_only(assert_completed_buffer_list_len_correct_locked());
   return nd;
 }
 
-// We only do this in contexts where there is no concurrent enqueueing.
-DirtyCardQueueSet::CompletedBufferNode*
-DirtyCardQueueSet::get_completed_buffer_CAS() {
-  CompletedBufferNode* nd = _completed_buffers_head;
-
-  while (nd != NULL) {
-    CompletedBufferNode* next = nd->next;
-    CompletedBufferNode* result =
-      (CompletedBufferNode*)Atomic::cmpxchg_ptr(next,
-                                                &_completed_buffers_head,
-                                                nd);
-    if (result == nd) {
-      return result;
-    } else {
-      nd = _completed_buffers_head;
-    }
-  }
-  assert(_completed_buffers_head == NULL, "Loop post");
-  _completed_buffers_tail = NULL;
-  return NULL;
-}
-
 bool DirtyCardQueueSet::
 apply_closure_to_completed_buffer_helper(int worker_i,
-                                         CompletedBufferNode* nd) {
+                                         BufferNode* nd) {
   if (nd != NULL) {
+    void **buf = BufferNode::make_buffer_from_node(nd);
+    size_t index = nd->index();
     bool b =
-      DirtyCardQueue::apply_closure_to_buffer(_closure, nd->buf,
-                                              nd->index, _sz,
+      DirtyCardQueue::apply_closure_to_buffer(_closure, buf,
+                                              index, _sz,
                                               true, worker_i);
-    void** buf = nd->buf;
-    size_t index = nd->index;
-    delete nd;
     if (b) {
       deallocate_buffer(buf);
       return true;  // In normal case, go on to next buffer.
     } else {
-      enqueue_complete_buffer(buf, index, true);
+      enqueue_complete_buffer(buf, index);
       return false;
     }
   } else {
@@ -222,40 +201,36 @@
 
 bool DirtyCardQueueSet::apply_closure_to_completed_buffer(int worker_i,
                                                           int stop_at,
-                                                          bool with_CAS)
+                                                          bool during_pause)
 {
-  CompletedBufferNode* nd = NULL;
-  if (with_CAS) {
-    guarantee(stop_at == 0, "Precondition");
-    nd = get_completed_buffer_CAS();
-  } else {
-    nd = get_completed_buffer_lock(stop_at);
-  }
+  assert(!during_pause || stop_at == 0, "Should not leave any completed buffers during a pause");
+  BufferNode* nd = get_completed_buffer(stop_at);
   bool res = apply_closure_to_completed_buffer_helper(worker_i, nd);
   if (res) Atomic::inc(&_processed_buffers_rs_thread);
   return res;
 }
 
 void DirtyCardQueueSet::apply_closure_to_all_completed_buffers() {
-  CompletedBufferNode* nd = _completed_buffers_head;
+  BufferNode* nd = _completed_buffers_head;
   while (nd != NULL) {
     bool b =
-      DirtyCardQueue::apply_closure_to_buffer(_closure, nd->buf, 0, _sz,
-                                              false);
+      DirtyCardQueue::apply_closure_to_buffer(_closure,
+                                              BufferNode::make_buffer_from_node(nd),
+                                              0, _sz, false);
     guarantee(b, "Should not stop early.");
-    nd = nd->next;
+    nd = nd->next();
   }
 }
 
 void DirtyCardQueueSet::abandon_logs() {
   assert(SafepointSynchronize::is_at_safepoint(), "Must be at safepoint.");
-  CompletedBufferNode* buffers_to_delete = NULL;
+  BufferNode* buffers_to_delete = NULL;
   {
     MutexLockerEx x(_cbl_mon, Mutex::_no_safepoint_check_flag);
     while (_completed_buffers_head != NULL) {
-      CompletedBufferNode* nd = _completed_buffers_head;
-      _completed_buffers_head = nd->next;
-      nd->next = buffers_to_delete;
+      BufferNode* nd = _completed_buffers_head;
+      _completed_buffers_head = nd->next();
+      nd->set_next(buffers_to_delete);
       buffers_to_delete = nd;
     }
     _n_completed_buffers = 0;
@@ -263,10 +238,9 @@
     debug_only(assert_completed_buffer_list_len_correct_locked());
   }
   while (buffers_to_delete != NULL) {
-    CompletedBufferNode* nd = buffers_to_delete;
-    buffers_to_delete = nd->next;
-    deallocate_buffer(nd->buf);
-    delete nd;
+    BufferNode* nd = buffers_to_delete;
+    buffers_to_delete = nd->next();
+    deallocate_buffer(BufferNode::make_buffer_from_node(nd));
   }
   // Since abandon is done only at safepoints, we can safely manipulate
   // these queues.
--- a/hotspot/src/share/vm/gc_implementation/g1/dirtyCardQueue.hpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/share/vm/gc_implementation/g1/dirtyCardQueue.hpp	Wed Jul 05 17:04:56 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright 2001-2007 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2001-2009 Sun Microsystems, Inc.  All Rights Reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -84,11 +84,12 @@
   jint _processed_buffers_rs_thread;
 
 public:
-  DirtyCardQueueSet();
+  DirtyCardQueueSet(bool notify_when_complete = true);
 
   void initialize(Monitor* cbl_mon, Mutex* fl_lock,
-                  int max_completed_queue = 0,
-                  Mutex* lock = NULL, PtrQueueSet* fl_owner = NULL);
+                  int process_completed_threshold,
+                  int max_completed_queue,
+                  Mutex* lock, PtrQueueSet* fl_owner = NULL);
 
   // The number of parallel ids that can be claimed to allow collector or
   // mutator threads to do card-processing work.
@@ -120,12 +121,13 @@
   // is returned to the completed buffer set, and this call returns false.
   bool apply_closure_to_completed_buffer(int worker_i = 0,
                                          int stop_at = 0,
-                                         bool with_CAS = false);
+                                         bool during_pause = false);
+
   bool apply_closure_to_completed_buffer_helper(int worker_i,
-                                                CompletedBufferNode* nd);
+                                                BufferNode* nd);
 
-  CompletedBufferNode* get_completed_buffer_CAS();
-  CompletedBufferNode* get_completed_buffer_lock(int stop_at);
+  BufferNode* get_completed_buffer(int stop_at);
+
   // Applies the current closure to all completed buffers,
   // non-consumptively.
   void apply_closure_to_all_completed_buffers();
--- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp	Wed Jul 05 17:04:56 2017 +0200
@@ -928,6 +928,8 @@
     TraceCPUTime tcpu(PrintGCDetails, true, gclog_or_tty);
     TraceTime t(full ? "Full GC (System.gc())" : "Full GC", PrintGC, true, gclog_or_tty);
 
+    TraceMemoryManagerStats tms(true /* fullGC */);
+
     double start = os::elapsedTime();
     g1_policy()->record_full_collection_start();
 
@@ -1001,6 +1003,8 @@
 
     COMPILER2_PRESENT(DerivedPointerTable::update_pointers());
 
+    MemoryService::track_memory_usage();
+
     if (VerifyAfterGC && total_collections() >= VerifyGCStartAt) {
       HandleMark hm;  // Discard invalid handles created during verification
       gclog_or_tty->print(" VerifyAfterGC:");
@@ -1371,6 +1375,7 @@
 G1CollectedHeap::G1CollectedHeap(G1CollectorPolicy* policy_) :
   SharedHeap(policy_),
   _g1_policy(policy_),
+  _dirty_card_queue_set(false),
   _ref_processor(NULL),
   _process_strong_tasks(new SubTasksDone(G1H_PS_NumElements)),
   _bot_shared(NULL),
@@ -1456,8 +1461,6 @@
   Universe::check_alignment(init_byte_size, HeapRegion::GrainBytes, "g1 heap");
   Universe::check_alignment(max_byte_size, HeapRegion::GrainBytes, "g1 heap");
 
-  // We allocate this in any case, but only do no work if the command line
-  // param is off.
   _cg1r = new ConcurrentG1Refine();
 
   // Reserve the maximum.
@@ -1590,18 +1593,20 @@
 
   JavaThread::satb_mark_queue_set().initialize(SATB_Q_CBL_mon,
                                                SATB_Q_FL_lock,
-                                               0,
+                                               G1SATBProcessCompletedThreshold,
                                                Shared_SATB_Q_lock);
 
   JavaThread::dirty_card_queue_set().initialize(DirtyCardQ_CBL_mon,
                                                 DirtyCardQ_FL_lock,
-                                                G1UpdateBufferQueueMaxLength,
+                                                concurrent_g1_refine()->yellow_zone(),
+                                                concurrent_g1_refine()->red_zone(),
                                                 Shared_DirtyCardQ_lock);
 
   if (G1DeferredRSUpdate) {
     dirty_card_queue_set().initialize(DirtyCardQ_CBL_mon,
                                       DirtyCardQ_FL_lock,
-                                      0,
+                                      -1, // never trigger processing
+                                      -1, // no limit on length
                                       Shared_DirtyCardQ_lock,
                                       &JavaThread::dirty_card_queue_set());
   }
@@ -1732,13 +1737,6 @@
   return car->free();
 }
 
-void G1CollectedHeap::collect(GCCause::Cause cause) {
-  // The caller doesn't have the Heap_lock
-  assert(!Heap_lock->owned_by_self(), "this thread should not own the Heap_lock");
-  MutexLocker ml(Heap_lock);
-  collect_locked(cause);
-}
-
 void G1CollectedHeap::collect_as_vm_thread(GCCause::Cause cause) {
   assert(Thread::current()->is_VM_thread(), "Precondition#1");
   assert(Heap_lock->is_locked(), "Precondition#2");
@@ -1755,17 +1753,31 @@
   }
 }
 
-
-void G1CollectedHeap::collect_locked(GCCause::Cause cause) {
-  // Don't want to do a GC until cleanup is completed.
-  wait_for_cleanup_complete();
-
-  // Read the GC count while holding the Heap_lock
-  int gc_count_before = SharedHeap::heap()->total_collections();
+void G1CollectedHeap::collect(GCCause::Cause cause) {
+  // The caller doesn't have the Heap_lock
+  assert(!Heap_lock->owned_by_self(), "this thread should not own the Heap_lock");
+
+  int gc_count_before;
   {
-    MutexUnlocker mu(Heap_lock);  // give up heap lock, execute gets it back
-    VM_G1CollectFull op(gc_count_before, cause);
-    VMThread::execute(&op);
+    MutexLocker ml(Heap_lock);
+    // Read the GC count while holding the Heap_lock
+    gc_count_before = SharedHeap::heap()->total_collections();
+
+    // Don't want to do a GC until cleanup is completed.
+    wait_for_cleanup_complete();
+  } // We give up heap lock; VMThread::execute gets it back below
+  switch (cause) {
+    case GCCause::_scavenge_alot: {
+      // Do an incremental pause, which might sometimes be abandoned.
+      VM_G1IncCollectionPause op(gc_count_before, cause);
+      VMThread::execute(&op);
+      break;
+    }
+    default: {
+      // In all other cases, we currently do a full gc.
+      VM_G1CollectFull op(gc_count_before, cause);
+      VMThread::execute(&op);
+    }
   }
 }
 
@@ -2119,7 +2131,7 @@
 }
 
 size_t G1CollectedHeap::max_capacity() const {
-  return _g1_committed.byte_size();
+  return g1_reserved_obj_bytes();
 }
 
 jlong G1CollectedHeap::millis_since_last_gc() {
@@ -2638,6 +2650,8 @@
   }
 
   {
+    ResourceMark rm;
+
     char verbose_str[128];
     sprintf(verbose_str, "GC pause ");
     if (g1_policy()->in_young_gc_mode()) {
@@ -2649,8 +2663,6 @@
     if (g1_policy()->should_initiate_conc_mark())
       strcat(verbose_str, " (initial-mark)");
 
-    GCCauseSetter x(this, GCCause::_g1_inc_collection_pause);
-
     // if PrintGCDetails 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.
@@ -2658,7 +2670,8 @@
     TraceCPUTime tcpu(PrintGCDetails, true, gclog_or_tty);
     TraceTime t(verbose_str, PrintGC && !PrintGCDetails, true, gclog_or_tty);
 
-    ResourceMark rm;
+    TraceMemoryManagerStats tms(false /* fullGC */);
+
     assert(SafepointSynchronize::is_at_safepoint(), "should be at safepoint");
     assert(Thread::current() == VMThread::vm_thread(), "should be in vm thread");
     guarantee(!is_gc_active(), "collection is not reentrant");
@@ -2802,6 +2815,22 @@
           _young_list->reset_auxilary_lists();
         }
       } else {
+        if (_in_cset_fast_test != NULL) {
+          assert(_in_cset_fast_test_base != NULL, "Since _in_cset_fast_test isn't");
+          FREE_C_HEAP_ARRAY(bool, _in_cset_fast_test_base);
+          //  this is more for peace of mind; we're nulling them here and
+          // we're expecting them to be null at the beginning of the next GC
+          _in_cset_fast_test = NULL;
+          _in_cset_fast_test_base = NULL;
+        }
+        // This looks confusing, because the DPT should really be empty
+        // at this point -- since we have not done any collection work,
+        // there should not be any derived pointers in the table to update;
+        // however, there is some additional state in the DPT which is
+        // reset at the end of the (null) "gc" here via the following call.
+        // A better approach might be to split off that state resetting work
+        // into a separate method that asserts that the DPT is empty and call
+        // that here. That is deferred for now.
         COMPILER2_PRESENT(DerivedPointerTable::update_pointers());
       }
 
@@ -2838,6 +2867,8 @@
 
       assert(regions_accounted_for(), "Region leakage.");
 
+      MemoryService::track_memory_usage();
+
       if (VerifyAfterGC && total_collections() >= VerifyGCStartAt) {
         HandleMark hm;  // Discard invalid handles created during verification
         gclog_or_tty->print(" VerifyAfterGC:");
@@ -4209,10 +4240,11 @@
     RedirtyLoggedCardTableEntryFastClosure redirty;
     dirty_card_queue_set().set_closure(&redirty);
     dirty_card_queue_set().apply_closure_to_all_completed_buffers();
-    JavaThread::dirty_card_queue_set().merge_bufferlists(&dirty_card_queue_set());
+
+    DirtyCardQueueSet& dcq = JavaThread::dirty_card_queue_set();
+    dcq.merge_bufferlists(&dirty_card_queue_set());
     assert(dirty_card_queue_set().completed_buffers_num() == 0, "All should be consumed");
   }
-
   COMPILER2_PRESENT(DerivedPointerTable::update_pointers());
 }
 
--- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp	Wed Jul 05 17:04:56 2017 +0200
@@ -692,7 +692,7 @@
 
   // Reserved (g1 only; super method includes perm), capacity and the used
   // portion in bytes.
-  size_t g1_reserved_obj_bytes() { return _g1_reserved.byte_size(); }
+  size_t g1_reserved_obj_bytes() const { return _g1_reserved.byte_size(); }
   virtual size_t capacity() const;
   virtual size_t used() const;
   // This should be called when we're not holding the heap lock. The
--- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp	Wed Jul 05 17:04:56 2017 +0200
@@ -1516,8 +1516,30 @@
       (end_time_sec - _recent_prev_end_times_for_all_gcs_sec->oldest()) * 1000.0;
     update_recent_gc_times(end_time_sec, elapsed_ms);
     _recent_avg_pause_time_ratio = _recent_gc_times_ms->sum()/interval_ms;
-    // using 1.01 to account for floating point inaccuracies
-    assert(recent_avg_pause_time_ratio() < 1.01, "All GC?");
+    if (recent_avg_pause_time_ratio() < 0.0 ||
+        (recent_avg_pause_time_ratio() - 1.0 > 0.0)) {
+#ifndef PRODUCT
+      // Dump info to allow post-facto debugging
+      gclog_or_tty->print_cr("recent_avg_pause_time_ratio() out of bounds");
+      gclog_or_tty->print_cr("-------------------------------------------");
+      gclog_or_tty->print_cr("Recent GC Times (ms):");
+      _recent_gc_times_ms->dump();
+      gclog_or_tty->print_cr("(End Time=%3.3f) Recent GC End Times (s):", end_time_sec);
+      _recent_prev_end_times_for_all_gcs_sec->dump();
+      gclog_or_tty->print_cr("GC = %3.3f, Interval = %3.3f, Ratio = %3.3f",
+                             _recent_gc_times_ms->sum(), interval_ms, recent_avg_pause_time_ratio());
+      // In debug mode, terminate the JVM if the user wants to debug at this point.
+      assert(!G1FailOnFPError, "Debugging data for CR 6898948 has been dumped above");
+#endif  // !PRODUCT
+      // Clip ratio between 0.0 and 1.0, and continue. This will be fixed in
+      // CR 6902692 by redoing the manner in which the ratio is incrementally computed.
+      if (_recent_avg_pause_time_ratio < 0.0) {
+        _recent_avg_pause_time_ratio = 0.0;
+      } else {
+        assert(_recent_avg_pause_time_ratio - 1.0 > 0.0, "Ctl-point invariant");
+        _recent_avg_pause_time_ratio = 1.0;
+      }
+    }
   }
 
   if (G1PolicyVerbose > 1) {
@@ -1892,6 +1914,10 @@
   calculate_young_list_min_length();
   calculate_young_list_target_config();
 
+  // Note that _mmu_tracker->max_gc_time() returns the time in seconds.
+  double update_rs_time_goal_ms = _mmu_tracker->max_gc_time() * MILLIUNITS * G1RSUpdatePauseFractionPercent / 100.0;
+  adjust_concurrent_refinement(update_rs_time, update_rs_processed_buffers, update_rs_time_goal_ms);
+
   // </NEW PREDICTION>
 
   _target_pause_time_ms = -1.0;
@@ -1899,6 +1925,47 @@
 
 // <NEW PREDICTION>
 
+void G1CollectorPolicy::adjust_concurrent_refinement(double update_rs_time,
+                                                     double update_rs_processed_buffers,
+                                                     double goal_ms) {
+  DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set();
+  ConcurrentG1Refine *cg1r = G1CollectedHeap::heap()->concurrent_g1_refine();
+
+  if (G1AdaptiveConcRefine) {
+    const int k_gy = 3, k_gr = 6;
+    const double inc_k = 1.1, dec_k = 0.9;
+
+    int g = cg1r->green_zone();
+    if (update_rs_time > goal_ms) {
+      g = (int)(g * dec_k);  // Can become 0, that's OK. That would mean a mutator-only processing.
+    } else {
+      if (update_rs_time < goal_ms && update_rs_processed_buffers > g) {
+        g = (int)MAX2(g * inc_k, g + 1.0);
+      }
+    }
+    // Change the refinement threads params
+    cg1r->set_green_zone(g);
+    cg1r->set_yellow_zone(g * k_gy);
+    cg1r->set_red_zone(g * k_gr);
+    cg1r->reinitialize_threads();
+
+    int processing_threshold_delta = MAX2((int)(cg1r->green_zone() * sigma()), 1);
+    int processing_threshold = MIN2(cg1r->green_zone() + processing_threshold_delta,
+                                    cg1r->yellow_zone());
+    // Change the barrier params
+    dcqs.set_process_completed_threshold(processing_threshold);
+    dcqs.set_max_completed_queue(cg1r->red_zone());
+  }
+
+  int curr_queue_size = dcqs.completed_buffers_num();
+  if (curr_queue_size >= cg1r->yellow_zone()) {
+    dcqs.set_completed_queue_padding(curr_queue_size);
+  } else {
+    dcqs.set_completed_queue_padding(0);
+  }
+  dcqs.notify_if_necessary();
+}
+
 double
 G1CollectorPolicy::
 predict_young_collection_elapsed_time_ms(size_t adjustment) {
@@ -2825,8 +2892,15 @@
   double non_young_start_time_sec;
   start_recording_regions();
 
-  guarantee(_target_pause_time_ms > -1.0,
+  guarantee(_target_pause_time_ms > -1.0
+            NOT_PRODUCT(|| Universe::heap()->gc_cause() == GCCause::_scavenge_alot),
             "_target_pause_time_ms should have been set!");
+#ifndef PRODUCT
+  if (_target_pause_time_ms <= -1.0) {
+    assert(ScavengeALot && Universe::heap()->gc_cause() == GCCause::_scavenge_alot, "Error");
+    _target_pause_time_ms = _mmu_tracker->max_gc_time() * 1000.0;
+  }
+#endif
   assert(_collection_set == NULL, "Precondition");
 
   double base_time_ms = predict_base_elapsed_time_ms(_pending_cards);
@@ -2972,7 +3046,3 @@
   G1CollectorPolicy::record_collection_pause_end(abandoned);
   assert(assertMarkedBytesDataOK(), "Marked regions not OK at pause end.");
 }
-
-// Local Variables: ***
-// c-indentation-style: gnu ***
-// End: ***
--- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp	Wed Jul 05 17:04:56 2017 +0200
@@ -316,6 +316,10 @@
   bool verify_young_ages(HeapRegion* head, SurvRateGroup *surv_rate_group);
 #endif // PRODUCT
 
+  void adjust_concurrent_refinement(double update_rs_time,
+                                    double update_rs_processed_buffers,
+                                    double goal_ms);
+
 protected:
   double _pause_time_target_ms;
   double _recorded_young_cset_choice_time_ms;
--- a/hotspot/src/share/vm/gc_implementation/g1/g1MMUTracker.cpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1MMUTracker.cpp	Wed Jul 05 17:04:56 2017 +0200
@@ -86,12 +86,22 @@
     //   increase the array size (:-)
     //   remove the oldest entry (this might allow more GC time for
     //     the time slice than what's allowed)
-    //   concolidate the two entries with the minimum gap between them
-    //     (this mighte allow less GC time than what's allowed)
-    guarantee(0, "array full, currently we can't recover");
+    //   consolidate the two entries with the minimum gap between them
+    //     (this might allow less GC time than what's allowed)
+    guarantee(NOT_PRODUCT(ScavengeALot ||) G1ForgetfulMMUTracker,
+              "array full, currently we can't recover unless +G1ForgetfulMMUTracker");
+    // In the case where ScavengeALot is true, such overflow is not
+    // uncommon; in such cases, we can, without much loss of precision
+    // or performance (we are GC'ing most of the time anyway!),
+    // simply overwrite the oldest entry in the tracker: this
+    // is also the behaviour when G1ForgetfulMMUTracker is enabled.
+    _head_index = trim_index(_head_index + 1);
+    assert(_head_index == _tail_index, "Because we have a full circular buffer");
+    _tail_index = trim_index(_tail_index + 1);
+  } else {
+    _head_index = trim_index(_head_index + 1);
+    ++_no_entries;
   }
-  _head_index = trim_index(_head_index + 1);
-  ++_no_entries;
   _array[_head_index] = G1MMUTrackerQueueElem(start, end);
 }
 
--- a/hotspot/src/share/vm/gc_implementation/g1/g1MMUTracker.hpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1MMUTracker.hpp	Wed Jul 05 17:04:56 2017 +0200
@@ -99,7 +99,10 @@
   // The array is of fixed size and I don't think we'll need more than
   // two or three entries with the current behaviour of G1 pauses.
   // If the array is full, an easy fix is to look for the pauses with
-  // the shortest gap between them and concolidate them.
+  // the shortest gap between them and consolidate them.
+  // For now, we have taken the expedient alternative of forgetting
+  // the oldest entry in the event that +G1ForgetfulMMUTracker, thus
+  // potentially violating MMU specs for some time thereafter.
 
   G1MMUTrackerQueueElem _array[QueueLength];
   int                   _head_index;
--- a/hotspot/src/share/vm/gc_implementation/g1/g1_globals.hpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1_globals.hpp	Wed Jul 05 17:04:56 2017 +0200
@@ -85,7 +85,7 @@
   diagnostic(bool, G1SummarizeZFStats, false,                               \
           "Summarize zero-filling info")                                    \
                                                                             \
-  develop(bool, G1TraceConcurrentRefinement, false,                         \
+  diagnostic(bool, G1TraceConcurrentRefinement, false,                      \
           "Trace G1 concurrent refinement")                                 \
                                                                             \
   product(intx, G1MarkStackSize, 2 * 1024 * 1024,                           \
@@ -94,19 +94,6 @@
   product(intx, G1MarkRegionStackSize, 1024 * 1024,                         \
           "Size of the region stack for concurrent marking.")               \
                                                                             \
-  develop(bool, G1ConcRefine, true,                                         \
-          "If true, run concurrent rem set refinement for G1")              \
-                                                                            \
-  develop(intx, G1ConcRefineTargTraversals, 4,                              \
-          "Number of concurrent refinement we try to achieve")              \
-                                                                            \
-  develop(intx, G1ConcRefineInitialDelta, 4,                                \
-          "Number of heap regions of alloc ahead of starting collection "   \
-          "pause to start concurrent refinement (initially)")               \
-                                                                            \
-  develop(bool, G1SmoothConcRefine, true,                                   \
-          "Attempts to smooth out the overhead of concurrent refinement")   \
-                                                                            \
   develop(bool, G1ConcZeroFill, true,                                       \
           "If true, run concurrent zero-filling thread")                    \
                                                                             \
@@ -178,13 +165,38 @@
   product(intx, G1UpdateBufferSize, 256,                                    \
           "Size of an update buffer")                                       \
                                                                             \
-  product(intx, G1UpdateBufferQueueProcessingThreshold, 5,                  \
+  product(intx, G1ConcRefineYellowZone, 0,                                  \
           "Number of enqueued update buffers that will "                    \
-          "trigger concurrent processing")                                  \
+          "trigger concurrent processing. Will be selected ergonomically "  \
+          "by default.")                                                    \
+                                                                            \
+  product(intx, G1ConcRefineRedZone, 0,                                     \
+          "Maximum number of enqueued update buffers before mutator "       \
+          "threads start processing new ones instead of enqueueing them. "  \
+          "Will be selected ergonomically by default. Zero will disable "   \
+          "concurrent processing.")                                         \
+                                                                            \
+  product(intx, G1ConcRefineGreenZone, 0,                                   \
+          "The number of update buffers that are left in the queue by the " \
+          "concurrent processing threads. Will be selected ergonomically "  \
+          "by default.")                                                    \
                                                                             \
-  product(intx, G1UpdateBufferQueueMaxLength, 30,                           \
-          "Maximum number of enqueued update buffers before mutator "       \
-          "threads start processing new ones instead of enqueueing them")   \
+  product(intx, G1ConcRefineServiceInterval, 300,                           \
+          "The last concurrent refinement thread wakes up every "           \
+          "specified number of milliseconds to do miscellaneous work.")     \
+                                                                            \
+  product(intx, G1ConcRefineThresholdStep, 0,                               \
+          "Each time the rset update queue increases by this amount "       \
+          "activate the next refinement thread if available. "              \
+          "Will be selected ergonomically by default.")                     \
+                                                                            \
+  product(intx, G1RSUpdatePauseFractionPercent, 10,                         \
+          "A target percentage of time that is allowed to be spend on "     \
+          "process RS update buffers during the collection pause.")         \
+                                                                            \
+  product(bool, G1AdaptiveConcRefine, true,                                 \
+          "Select green, yellow and red zones adaptively to meet the "      \
+          "the pause requirements.")                                        \
                                                                             \
   develop(intx, G1ConcRSLogCacheSize, 10,                                   \
           "Log base 2 of the length of conc RS hot-card cache.")            \
@@ -242,6 +254,10 @@
   product(bool, G1UseSurvivorSpaces, true,                                  \
           "When true, use survivor space.")                                 \
                                                                             \
+  develop(bool, G1FailOnFPError, false,                                     \
+          "When set, G1 will fail when it encounters an FP 'error', "       \
+          "so as to allow debugging")                                       \
+                                                                            \
   develop(bool, G1FixedTenuringThreshold, false,                            \
           "When set, G1 will not adjust the tenuring threshold")            \
                                                                             \
@@ -252,6 +268,9 @@
           "If non-0 is the size of the G1 survivor space, "                 \
           "otherwise SurvivorRatio is used to determine the size")          \
                                                                             \
+  product(bool, G1ForgetfulMMUTracker, false,                               \
+          "If the MMU tracker's memory is full, forget the oldest entry")   \
+                                                                            \
   product(uintx, G1HeapRegionSize, 0,                                       \
           "Size of the G1 regions.")                                        \
                                                                             \
--- a/hotspot/src/share/vm/gc_implementation/g1/ptrQueue.cpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/share/vm/gc_implementation/g1/ptrQueue.cpp	Wed Jul 05 17:04:56 2017 +0200
@@ -64,8 +64,8 @@
   while (_index == 0) {
     handle_zero_index();
   }
+
   assert(_index > 0, "postcondition");
-
   _index -= oopSize;
   _buf[byte_index_to_index((int)_index)] = ptr;
   assert(0 <= _index && _index <= _sz, "Invariant.");
@@ -99,94 +99,110 @@
   assert(_sz > 0, "Didn't set a buffer size.");
   MutexLockerEx x(_fl_owner->_fl_lock, Mutex::_no_safepoint_check_flag);
   if (_fl_owner->_buf_free_list != NULL) {
-    void** res = _fl_owner->_buf_free_list;
-    _fl_owner->_buf_free_list = (void**)_fl_owner->_buf_free_list[0];
+    void** res = BufferNode::make_buffer_from_node(_fl_owner->_buf_free_list);
+    _fl_owner->_buf_free_list = _fl_owner->_buf_free_list->next();
     _fl_owner->_buf_free_list_sz--;
-    // Just override the next pointer with NULL, just in case we scan this part
-    // of the buffer.
-    res[0] = NULL;
     return res;
   } else {
-    return NEW_C_HEAP_ARRAY(void*, _sz);
+    // Allocate space for the BufferNode in front of the buffer.
+    char *b =  NEW_C_HEAP_ARRAY(char, _sz + BufferNode::aligned_size());
+    return BufferNode::make_buffer_from_block(b);
   }
 }
 
 void PtrQueueSet::deallocate_buffer(void** buf) {
   assert(_sz > 0, "Didn't set a buffer size.");
   MutexLockerEx x(_fl_owner->_fl_lock, Mutex::_no_safepoint_check_flag);
-  buf[0] = (void*)_fl_owner->_buf_free_list;
-  _fl_owner->_buf_free_list = buf;
+  BufferNode *node = BufferNode::make_node_from_buffer(buf);
+  node->set_next(_fl_owner->_buf_free_list);
+  _fl_owner->_buf_free_list = node;
   _fl_owner->_buf_free_list_sz++;
 }
 
 void PtrQueueSet::reduce_free_list() {
+  assert(_fl_owner == this, "Free list reduction is allowed only for the owner");
   // For now we'll adopt the strategy of deleting half.
   MutexLockerEx x(_fl_lock, Mutex::_no_safepoint_check_flag);
   size_t n = _buf_free_list_sz / 2;
   while (n > 0) {
     assert(_buf_free_list != NULL, "_buf_free_list_sz must be wrong.");
-    void** head = _buf_free_list;
-    _buf_free_list = (void**)_buf_free_list[0];
-    FREE_C_HEAP_ARRAY(void*,head);
+    void* b = BufferNode::make_block_from_node(_buf_free_list);
+    _buf_free_list = _buf_free_list->next();
+    FREE_C_HEAP_ARRAY(char, b);
+    _buf_free_list_sz --;
     n--;
   }
 }
 
-void PtrQueueSet::enqueue_complete_buffer(void** buf, size_t index, bool ignore_max_completed) {
-  // I use explicit locking here because there's a bailout in the middle.
-  _cbl_mon->lock_without_safepoint_check();
-
-  Thread* thread = Thread::current();
-  assert( ignore_max_completed ||
-          thread->is_Java_thread() ||
-          SafepointSynchronize::is_at_safepoint(),
-          "invariant" );
-  ignore_max_completed = ignore_max_completed || !thread->is_Java_thread();
+void PtrQueue::handle_zero_index() {
+  assert(0 == _index, "Precondition.");
+  // This thread records the full buffer and allocates a new one (while
+  // holding the lock if there is one).
+  if (_buf != NULL) {
+    if (_lock) {
+      locking_enqueue_completed_buffer(_buf);
+    } else {
+      if (qset()->process_or_enqueue_complete_buffer(_buf)) {
+        // Recycle the buffer. No allocation.
+        _sz = qset()->buffer_size();
+        _index = _sz;
+        return;
+      }
+    }
+  }
+  // Reallocate the buffer
+  _buf = qset()->allocate_buffer();
+  _sz = qset()->buffer_size();
+  _index = _sz;
+  assert(0 <= _index && _index <= _sz, "Invariant.");
+}
 
-  if (!ignore_max_completed && _max_completed_queue > 0 &&
-      _n_completed_buffers >= (size_t) _max_completed_queue) {
-    _cbl_mon->unlock();
-    bool b = mut_process_buffer(buf);
-    if (b) {
-      deallocate_buffer(buf);
-      return;
+bool PtrQueueSet::process_or_enqueue_complete_buffer(void** buf) {
+  if (Thread::current()->is_Java_thread()) {
+    // We don't lock. It is fine to be epsilon-precise here.
+    if (_max_completed_queue == 0 || _max_completed_queue > 0 &&
+        _n_completed_buffers >= _max_completed_queue + _completed_queue_padding) {
+      bool b = mut_process_buffer(buf);
+      if (b) {
+        // True here means that the buffer hasn't been deallocated and the caller may reuse it.
+        return true;
+      }
     }
+  }
+  // The buffer will be enqueued. The caller will have to get a new one.
+  enqueue_complete_buffer(buf);
+  return false;
+}
 
-    // Otherwise, go ahead and enqueue the buffer.  Must reaquire the lock.
-    _cbl_mon->lock_without_safepoint_check();
-  }
-
-  // Here we still hold the _cbl_mon.
-  CompletedBufferNode* cbn = new CompletedBufferNode;
-  cbn->buf = buf;
-  cbn->next = NULL;
-  cbn->index = index;
+void PtrQueueSet::enqueue_complete_buffer(void** buf, size_t index) {
+  MutexLockerEx x(_cbl_mon, Mutex::_no_safepoint_check_flag);
+  BufferNode* cbn = BufferNode::new_from_buffer(buf);
+  cbn->set_index(index);
   if (_completed_buffers_tail == NULL) {
     assert(_completed_buffers_head == NULL, "Well-formedness");
     _completed_buffers_head = cbn;
     _completed_buffers_tail = cbn;
   } else {
-    _completed_buffers_tail->next = cbn;
+    _completed_buffers_tail->set_next(cbn);
     _completed_buffers_tail = cbn;
   }
   _n_completed_buffers++;
 
-  if (!_process_completed &&
+  if (!_process_completed && _process_completed_threshold >= 0 &&
       _n_completed_buffers >= _process_completed_threshold) {
     _process_completed = true;
     if (_notify_when_complete)
-      _cbl_mon->notify_all();
+      _cbl_mon->notify();
   }
   debug_only(assert_completed_buffer_list_len_correct_locked());
-  _cbl_mon->unlock();
 }
 
 int PtrQueueSet::completed_buffers_list_length() {
   int n = 0;
-  CompletedBufferNode* cbn = _completed_buffers_head;
+  BufferNode* cbn = _completed_buffers_head;
   while (cbn != NULL) {
     n++;
-    cbn = cbn->next;
+    cbn = cbn->next();
   }
   return n;
 }
@@ -197,7 +213,7 @@
 }
 
 void PtrQueueSet::assert_completed_buffer_list_len_correct_locked() {
-  guarantee((size_t)completed_buffers_list_length() ==  _n_completed_buffers,
+  guarantee(completed_buffers_list_length() ==  _n_completed_buffers,
             "Completed buffer length is wrong.");
 }
 
@@ -206,12 +222,8 @@
   _sz = sz * oopSize;
 }
 
-void PtrQueueSet::set_process_completed_threshold(size_t sz) {
-  _process_completed_threshold = sz;
-}
-
-// Merge lists of buffers. Notify waiting threads if the length of the list
-// exceeds threshold. The source queue is emptied as a result. The queues
+// Merge lists of buffers. Notify the processing threads.
+// The source queue is emptied as a result. The queues
 // must share the monitor.
 void PtrQueueSet::merge_bufferlists(PtrQueueSet *src) {
   assert(_cbl_mon == src->_cbl_mon, "Should share the same lock");
@@ -223,7 +235,7 @@
   } else {
     assert(_completed_buffers_head != NULL, "Well formedness");
     if (src->_completed_buffers_head != NULL) {
-      _completed_buffers_tail->next = src->_completed_buffers_head;
+      _completed_buffers_tail->set_next(src->_completed_buffers_head);
       _completed_buffers_tail = src->_completed_buffers_tail;
     }
   }
@@ -236,31 +248,13 @@
   assert(_completed_buffers_head == NULL && _completed_buffers_tail == NULL ||
          _completed_buffers_head != NULL && _completed_buffers_tail != NULL,
          "Sanity");
-
-  if (!_process_completed &&
-      _n_completed_buffers >= _process_completed_threshold) {
-    _process_completed = true;
-    if (_notify_when_complete)
-      _cbl_mon->notify_all();
-  }
 }
 
-// Merge free lists of the two queues. The free list of the source
-// queue is emptied as a result. The queues must share the same
-// mutex that guards free lists.
-void PtrQueueSet::merge_freelists(PtrQueueSet* src) {
-  assert(_fl_lock == src->_fl_lock, "Should share the same lock");
-  MutexLockerEx x(_fl_lock, Mutex::_no_safepoint_check_flag);
-  if (_buf_free_list != NULL) {
-    void **p = _buf_free_list;
-    while (*p != NULL) {
-      p = (void**)*p;
-    }
-    *p = src->_buf_free_list;
-  } else {
-    _buf_free_list = src->_buf_free_list;
+void PtrQueueSet::notify_if_necessary() {
+  MutexLockerEx x(_cbl_mon, Mutex::_no_safepoint_check_flag);
+  if (_n_completed_buffers >= _process_completed_threshold || _max_completed_queue == 0) {
+    _process_completed = true;
+    if (_notify_when_complete)
+      _cbl_mon->notify();
   }
-  _buf_free_list_sz += src->_buf_free_list_sz;
-  src->_buf_free_list = NULL;
-  src->_buf_free_list_sz = 0;
 }
--- a/hotspot/src/share/vm/gc_implementation/g1/ptrQueue.hpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/share/vm/gc_implementation/g1/ptrQueue.hpp	Wed Jul 05 17:04:56 2017 +0200
@@ -27,8 +27,10 @@
 // the addresses of modified old-generation objects.  This type supports
 // this operation.
 
+// The definition of placement operator new(size_t, void*) in the <new>.
+#include <new>
+
 class PtrQueueSet;
-
 class PtrQueue VALUE_OBJ_CLASS_SPEC {
 
 protected:
@@ -77,7 +79,7 @@
     else enqueue_known_active(ptr);
   }
 
-  inline void handle_zero_index();
+  void handle_zero_index();
   void locking_enqueue_completed_buffer(void** buf);
 
   void enqueue_known_active(void* ptr);
@@ -126,34 +128,65 @@
 
 };
 
+class BufferNode {
+  size_t _index;
+  BufferNode* _next;
+public:
+  BufferNode() : _index(0), _next(NULL) { }
+  BufferNode* next() const     { return _next;  }
+  void set_next(BufferNode* n) { _next = n;     }
+  size_t index() const         { return _index; }
+  void set_index(size_t i)     { _index = i;    }
+
+  // Align the size of the structure to the size of the pointer
+  static size_t aligned_size() {
+    static const size_t alignment = round_to(sizeof(BufferNode), sizeof(void*));
+    return alignment;
+  }
+
+  // BufferNode is allocated before the buffer.
+  // The chunk of memory that holds both of them is a block.
+
+  // Produce a new BufferNode given a buffer.
+  static BufferNode* new_from_buffer(void** buf) {
+    return new (make_block_from_buffer(buf)) BufferNode;
+  }
+
+  // The following are the required conversion routines:
+  static BufferNode* make_node_from_buffer(void** buf) {
+    return (BufferNode*)make_block_from_buffer(buf);
+  }
+  static void** make_buffer_from_node(BufferNode *node) {
+    return make_buffer_from_block(node);
+  }
+  static void* make_block_from_node(BufferNode *node) {
+    return (void*)node;
+  }
+  static void** make_buffer_from_block(void* p) {
+    return (void**)((char*)p + aligned_size());
+  }
+  static void* make_block_from_buffer(void** p) {
+    return (void*)((char*)p - aligned_size());
+  }
+};
+
 // A PtrQueueSet represents resources common to a set of pointer queues.
 // In particular, the individual queues allocate buffers from this shared
 // set, and return completed buffers to the set.
 // All these variables are are protected by the TLOQ_CBL_mon. XXX ???
 class PtrQueueSet VALUE_OBJ_CLASS_SPEC {
-
 protected:
-
-  class CompletedBufferNode: public CHeapObj {
-  public:
-    void** buf;
-    size_t index;
-    CompletedBufferNode* next;
-    CompletedBufferNode() : buf(NULL),
-      index(0), next(NULL){ }
-  };
-
   Monitor* _cbl_mon;  // Protects the fields below.
-  CompletedBufferNode* _completed_buffers_head;
-  CompletedBufferNode* _completed_buffers_tail;
-  size_t _n_completed_buffers;
-  size_t _process_completed_threshold;
+  BufferNode* _completed_buffers_head;
+  BufferNode* _completed_buffers_tail;
+  int _n_completed_buffers;
+  int _process_completed_threshold;
   volatile bool _process_completed;
 
   // This (and the interpretation of the first element as a "next"
   // pointer) are protected by the TLOQ_FL_lock.
   Mutex* _fl_lock;
-  void** _buf_free_list;
+  BufferNode* _buf_free_list;
   size_t _buf_free_list_sz;
   // Queue set can share a freelist. The _fl_owner variable
   // specifies the owner. It is set to "this" by default.
@@ -170,6 +203,7 @@
   // Maximum number of elements allowed on completed queue: after that,
   // enqueuer does the work itself.  Zero indicates no maximum.
   int _max_completed_queue;
+  int _completed_queue_padding;
 
   int completed_buffers_list_length();
   void assert_completed_buffer_list_len_correct_locked();
@@ -191,9 +225,12 @@
   // Because of init-order concerns, we can't pass these as constructor
   // arguments.
   void initialize(Monitor* cbl_mon, Mutex* fl_lock,
-                  int max_completed_queue = 0,
+                  int process_completed_threshold,
+                  int max_completed_queue,
                   PtrQueueSet *fl_owner = NULL) {
     _max_completed_queue = max_completed_queue;
+    _process_completed_threshold = process_completed_threshold;
+    _completed_queue_padding = 0;
     assert(cbl_mon != NULL && fl_lock != NULL, "Init order issue?");
     _cbl_mon = cbl_mon;
     _fl_lock = fl_lock;
@@ -208,14 +245,17 @@
   void deallocate_buffer(void** buf);
 
   // Declares that "buf" is a complete buffer.
-  void enqueue_complete_buffer(void** buf, size_t index = 0,
-                               bool ignore_max_completed = false);
+  void enqueue_complete_buffer(void** buf, size_t index = 0);
+
+  // To be invoked by the mutator.
+  bool process_or_enqueue_complete_buffer(void** buf);
 
   bool completed_buffers_exist_dirty() {
     return _n_completed_buffers > 0;
   }
 
   bool process_completed_buffers() { return _process_completed; }
+  void set_process_completed(bool x) { _process_completed = x; }
 
   bool active() { return _all_active; }
 
@@ -226,15 +266,24 @@
   // Get the buffer size.
   size_t buffer_size() { return _sz; }
 
-  // Set the number of completed buffers that triggers log processing.
-  void set_process_completed_threshold(size_t sz);
+  // Get/Set the number of completed buffers that triggers log processing.
+  void set_process_completed_threshold(int sz) { _process_completed_threshold = sz; }
+  int process_completed_threshold() const { return _process_completed_threshold; }
 
   // Must only be called at a safe point.  Indicates that the buffer free
   // list size may be reduced, if that is deemed desirable.
   void reduce_free_list();
 
-  size_t completed_buffers_num() { return _n_completed_buffers; }
+  int completed_buffers_num() { return _n_completed_buffers; }
 
   void merge_bufferlists(PtrQueueSet* src);
-  void merge_freelists(PtrQueueSet* src);
+
+  void set_max_completed_queue(int m) { _max_completed_queue = m; }
+  int max_completed_queue() { return _max_completed_queue; }
+
+  void set_completed_queue_padding(int padding) { _completed_queue_padding = padding; }
+  int completed_queue_padding() { return _completed_queue_padding; }
+
+  // Notify the consumer if the number of buffers crossed the threshold
+  void notify_if_necessary();
 };
--- a/hotspot/src/share/vm/gc_implementation/g1/satbQueue.cpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/share/vm/gc_implementation/g1/satbQueue.cpp	Wed Jul 05 17:04:56 2017 +0200
@@ -67,9 +67,9 @@
 {}
 
 void SATBMarkQueueSet::initialize(Monitor* cbl_mon, Mutex* fl_lock,
-                                  int max_completed_queue,
+                                  int process_completed_threshold,
                                   Mutex* lock) {
-  PtrQueueSet::initialize(cbl_mon, fl_lock, max_completed_queue);
+  PtrQueueSet::initialize(cbl_mon, fl_lock, process_completed_threshold, -1);
   _shared_satb_queue.set_lock(lock);
   if (ParallelGCThreads > 0) {
     _par_closures = NEW_C_HEAP_ARRAY(ObjectClosure*, ParallelGCThreads);
@@ -122,12 +122,12 @@
 
 bool SATBMarkQueueSet::apply_closure_to_completed_buffer_work(bool par,
                                                               int worker) {
-  CompletedBufferNode* nd = NULL;
+  BufferNode* nd = NULL;
   {
     MutexLockerEx x(_cbl_mon, Mutex::_no_safepoint_check_flag);
     if (_completed_buffers_head != NULL) {
       nd = _completed_buffers_head;
-      _completed_buffers_head = nd->next;
+      _completed_buffers_head = nd->next();
       if (_completed_buffers_head == NULL) _completed_buffers_tail = NULL;
       _n_completed_buffers--;
       if (_n_completed_buffers == 0) _process_completed = false;
@@ -135,9 +135,9 @@
   }
   ObjectClosure* cl = (par ? _par_closures[worker] : _closure);
   if (nd != NULL) {
-    ObjPtrQueue::apply_closure_to_buffer(cl, nd->buf, 0, _sz);
-    deallocate_buffer(nd->buf);
-    delete nd;
+    void **buf = BufferNode::make_buffer_from_node(nd);
+    ObjPtrQueue::apply_closure_to_buffer(cl, buf, 0, _sz);
+    deallocate_buffer(buf);
     return true;
   } else {
     return false;
@@ -145,13 +145,13 @@
 }
 
 void SATBMarkQueueSet::abandon_partial_marking() {
-  CompletedBufferNode* buffers_to_delete = NULL;
+  BufferNode* buffers_to_delete = NULL;
   {
     MutexLockerEx x(_cbl_mon, Mutex::_no_safepoint_check_flag);
     while (_completed_buffers_head != NULL) {
-      CompletedBufferNode* nd = _completed_buffers_head;
-      _completed_buffers_head = nd->next;
-      nd->next = buffers_to_delete;
+      BufferNode* nd = _completed_buffers_head;
+      _completed_buffers_head = nd->next();
+      nd->set_next(buffers_to_delete);
       buffers_to_delete = nd;
     }
     _completed_buffers_tail = NULL;
@@ -159,10 +159,9 @@
     DEBUG_ONLY(assert_completed_buffer_list_len_correct_locked());
   }
   while (buffers_to_delete != NULL) {
-    CompletedBufferNode* nd = buffers_to_delete;
-    buffers_to_delete = nd->next;
-    deallocate_buffer(nd->buf);
-    delete nd;
+    BufferNode* nd = buffers_to_delete;
+    buffers_to_delete = nd->next();
+    deallocate_buffer(BufferNode::make_buffer_from_node(nd));
   }
   assert(SafepointSynchronize::is_at_safepoint(), "Must be at safepoint.");
   // So we can safely manipulate these queues.
--- a/hotspot/src/share/vm/gc_implementation/g1/satbQueue.hpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/share/vm/gc_implementation/g1/satbQueue.hpp	Wed Jul 05 17:04:56 2017 +0200
@@ -60,8 +60,8 @@
   SATBMarkQueueSet();
 
   void initialize(Monitor* cbl_mon, Mutex* fl_lock,
-                  int max_completed_queue = 0,
-                  Mutex* lock = NULL);
+                  int process_completed_threshold,
+                  Mutex* lock);
 
   static void handle_zero_index_for_thread(JavaThread* t);
 
--- a/hotspot/src/share/vm/gc_implementation/g1/vm_operations_g1.cpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/share/vm/gc_implementation/g1/vm_operations_g1.cpp	Wed Jul 05 17:04:56 2017 +0200
@@ -42,7 +42,7 @@
 void VM_G1IncCollectionPause::doit() {
   JvmtiGCForAllocationMarker jgcm;
   G1CollectedHeap* g1h = G1CollectedHeap::heap();
-  GCCauseSetter x(g1h, GCCause::_g1_inc_collection_pause);
+  GCCauseSetter x(g1h, _gc_cause);
   g1h->do_collection_pause_at_safepoint();
 }
 
--- a/hotspot/src/share/vm/gc_implementation/g1/vm_operations_g1.hpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/share/vm/gc_implementation/g1/vm_operations_g1.hpp	Wed Jul 05 17:04:56 2017 +0200
@@ -68,8 +68,9 @@
 
 class VM_G1IncCollectionPause: public VM_GC_Operation {
  public:
-  VM_G1IncCollectionPause(int gc_count_before) :
-    VM_GC_Operation(gc_count_before) {}
+  VM_G1IncCollectionPause(int gc_count_before,
+                          GCCause::Cause gc_cause = GCCause::_g1_inc_collection_pause) :
+    VM_GC_Operation(gc_count_before) { _gc_cause = gc_cause; }
   virtual VMOp_Type type() const { return VMOp_G1IncCollectionPause; }
   virtual void doit();
   virtual const char* name() const {
--- a/hotspot/src/share/vm/gc_implementation/includeDB_gc_g1	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/share/vm/gc_implementation/includeDB_gc_g1	Wed Jul 05 17:04:56 2017 +0200
@@ -109,7 +109,6 @@
 dirtyCardQueue.cpp                      dirtyCardQueue.hpp
 dirtyCardQueue.cpp			heapRegionRemSet.hpp
 dirtyCardQueue.cpp                      mutexLocker.hpp
-dirtyCardQueue.cpp                      ptrQueue.inline.hpp
 dirtyCardQueue.cpp                      safepoint.hpp
 dirtyCardQueue.cpp                      thread.hpp
 dirtyCardQueue.cpp                      thread_<os_family>.inline.hpp
@@ -222,6 +221,15 @@
 g1MarkSweep.hpp                         timer.hpp
 g1MarkSweep.hpp                         universe.hpp
 
+g1MemoryPool.cpp                        heapRegion.hpp
+g1MemoryPool.cpp                        g1CollectedHeap.inline.hpp
+g1MemoryPool.cpp                        g1CollectedHeap.hpp
+g1MemoryPool.cpp                        g1CollectorPolicy.hpp
+g1MemoryPool.cpp                        g1MemoryPool.hpp
+
+g1MemoryPool.hpp                        memoryUsage.hpp
+g1MemoryPool.hpp                        memoryPool.hpp
+
 g1OopClosures.inline.hpp		concurrentMark.hpp
 g1OopClosures.inline.hpp		g1OopClosures.hpp
 g1OopClosures.inline.hpp		g1CollectedHeap.hpp
@@ -303,12 +311,13 @@
 
 klass.hpp				g1OopClosures.hpp
 
+memoryService.cpp                       g1MemoryPool.hpp
+
 ptrQueue.cpp                            allocation.hpp
 ptrQueue.cpp                            allocation.inline.hpp
 ptrQueue.cpp                            mutex.hpp
 ptrQueue.cpp                            mutexLocker.hpp
 ptrQueue.cpp                            ptrQueue.hpp
-ptrQueue.cpp                            ptrQueue.inline.hpp
 ptrQueue.cpp                            thread_<os_family>.inline.hpp
 
 ptrQueue.hpp                            allocation.hpp
@@ -318,7 +327,6 @@
 
 satbQueue.cpp                           allocation.inline.hpp
 satbQueue.cpp                           mutexLocker.hpp
-satbQueue.cpp                           ptrQueue.inline.hpp
 satbQueue.cpp                           satbQueue.hpp
 satbQueue.cpp                           sharedHeap.hpp
 satbQueue.cpp                           thread.hpp
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psGCAdaptivePolicyCounters.cpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psGCAdaptivePolicyCounters.cpp	Wed Jul 05 17:04:56 2017 +0200
@@ -51,7 +51,7 @@
 
     cname = PerfDataManager::counter_name(name_space(), "oldCapacity");
     _old_capacity = PerfDataManager::create_variable(SUN_GC, cname,
-      PerfData::U_Bytes, (jlong) Arguments::initial_heap_size(), CHECK);
+      PerfData::U_Bytes, (jlong) InitialHeapSize, CHECK);
 
     cname = PerfDataManager::counter_name(name_space(), "boundaryMoved");
     _boundary_moved = PerfDataManager::create_variable(SUN_GC, cname,
--- a/hotspot/src/share/vm/includeDB_compiler2	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/share/vm/includeDB_compiler2	Wed Jul 05 17:04:56 2017 +0200
@@ -149,6 +149,7 @@
 c2compiler.hpp                          abstractCompiler.hpp
 
 callGenerator.cpp                       addnode.hpp
+callGenerator.cpp                       bcEscapeAnalyzer.hpp
 callGenerator.cpp                       callGenerator.hpp
 callGenerator.cpp                       callnode.hpp
 callGenerator.cpp                       cfgnode.hpp
@@ -321,6 +322,7 @@
 compile.cpp                             rootnode.hpp
 compile.cpp                             runtime.hpp
 compile.cpp                             signature.hpp
+compile.cpp                             stringopts.hpp
 compile.cpp                             stubRoutines.hpp
 compile.cpp                             systemDictionary.hpp
 compile.cpp                             timer.hpp
@@ -476,12 +478,16 @@
 graphKit.cpp                            runtime.hpp
 graphKit.cpp                            sharedRuntime.hpp
 
+graphKit.hpp                            addnode.hpp
 graphKit.hpp                            callnode.hpp
 graphKit.hpp                            cfgnode.hpp
 graphKit.hpp                            ciEnv.hpp
+graphKit.hpp                            divnode.hpp
 graphKit.hpp                            compile.hpp
 graphKit.hpp                            deoptimization.hpp
 graphKit.hpp                            phaseX.hpp
+graphKit.hpp                            mulnode.hpp
+graphKit.hpp                            subnode.hpp
 graphKit.hpp                            type.hpp
 
 idealKit.cpp                            addnode.hpp
@@ -490,7 +496,10 @@
 idealKit.cpp                            idealKit.hpp
 idealKit.cpp				runtime.hpp
 
+idealKit.hpp                            addnode.hpp
+idealKit.hpp                            cfgnode.hpp
 idealKit.hpp                            connode.hpp
+idealKit.hpp                            divnode.hpp
 idealKit.hpp                            mulnode.hpp
 idealKit.hpp                            phaseX.hpp
 idealKit.hpp                            subnode.hpp
@@ -641,6 +650,7 @@
 macro.cpp                               callnode.hpp
 macro.cpp                               cfgnode.hpp
 macro.cpp                               compile.hpp
+macro.cpp                              compileLog.hpp
 macro.cpp                               connode.hpp
 macro.cpp                               locknode.hpp
 macro.cpp                               loopnode.hpp
@@ -993,6 +1003,21 @@
 split_if.cpp                            connode.hpp
 split_if.cpp                            loopnode.hpp
 
+stringopts.hpp                          phaseX.hpp
+stringopts.hpp                          node.hpp
+
+stringopts.cpp                          addnode.hpp
+stringopts.cpp                          callnode.hpp
+stringopts.cpp                          callGenerator.hpp
+stringopts.cpp                          compileLog.hpp
+stringopts.cpp                          divnode.hpp
+stringopts.cpp                          idealKit.hpp
+stringopts.cpp                          graphKit.hpp
+stringopts.cpp                          rootnode.hpp
+stringopts.cpp                          runtime.hpp
+stringopts.cpp                          subnode.hpp
+stringopts.cpp                          stringopts.hpp
+
 stubGenerator_<arch_model>.cpp          runtime.hpp
 
 stubRoutines.cpp                        runtime.hpp
--- a/hotspot/src/share/vm/includeDB_core	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/share/vm/includeDB_core	Wed Jul 05 17:04:56 2017 +0200
@@ -289,7 +289,7 @@
 attachListener.hpp                      debug.hpp
 attachListener.hpp                      ostream.hpp
 
-barrierSet.cpp				barrierSet.hpp
+barrierSet.cpp				barrierSet.inline.hpp
 barrierSet.cpp			        collectedHeap.hpp
 barrierSet.cpp				universe.hpp
 
@@ -570,6 +570,7 @@
 ciEnv.hpp                               dependencies.hpp
 ciEnv.hpp                               exceptionHandlerTable.hpp
 ciEnv.hpp                               oopMap.hpp
+ciEnv.hpp                               systemDictionary.hpp
 ciEnv.hpp                               thread.hpp
 
 ciExceptionHandler.cpp                  ciExceptionHandler.hpp
@@ -1291,6 +1292,7 @@
 cpCacheOop.cpp                          markSweep.inline.hpp
 cpCacheOop.cpp                          objArrayOop.hpp
 cpCacheOop.cpp                          oop.inline.hpp
+cpCacheOop.cpp                          rewriter.hpp
 cpCacheOop.cpp                          universe.inline.hpp
 
 cpCacheOop.hpp                          allocation.hpp
--- a/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp	Wed Jul 05 17:04:56 2017 +0200
@@ -281,7 +281,7 @@
 
 #define DO_BACKEDGE_CHECKS(skip, branch_pc)                                                         \
     if ((skip) <= 0) {                                                                              \
-      if (UseCompiler && UseLoopCounter) {                                                          \
+      if (UseLoopCounter) {                                                                         \
         bool do_OSR = UseOnStackReplacement;                                                        \
         BACKEDGE_COUNT->increment();                                                                \
         if (do_OSR) do_OSR = BACKEDGE_COUNT->reached_InvocationLimit();                             \
@@ -289,16 +289,12 @@
           nmethod*  osr_nmethod;                                                                    \
           OSR_REQUEST(osr_nmethod, branch_pc);                                                      \
           if (osr_nmethod != NULL && osr_nmethod->osr_entry_bci() != InvalidOSREntryBci) {          \
-            intptr_t* buf;                                                                          \
-            CALL_VM(buf=SharedRuntime::OSR_migration_begin(THREAD), handle_exception);              \
+            intptr_t* buf = SharedRuntime::OSR_migration_begin(THREAD);                             \
             istate->set_msg(do_osr);                                                                \
             istate->set_osr_buf((address)buf);                                                      \
             istate->set_osr_entry(osr_nmethod->osr_entry());                                        \
             return;                                                                                 \
           }                                                                                         \
-        } else {                                                                                    \
-          INCR_INVOCATION_COUNT;                                                                    \
-          SAFEPOINT;                                                                                \
         }                                                                                           \
       }  /* UseCompiler ... */                                                                      \
       INCR_INVOCATION_COUNT;                                                                        \
@@ -1281,12 +1277,7 @@
           jfloat f;
           jdouble r;
           f = STACK_FLOAT(-1);
-#ifdef IA64
-          // IA64 gcc bug
-          r = ( f == 0.0f ) ? (jdouble) f : (jdouble) f + ia64_double_zero;
-#else
           r = (jdouble) f;
-#endif
           MORE_STACK(-1); // POP
           SET_STACK_DOUBLE(r, 1);
           UPDATE_PC_AND_TOS_AND_CONTINUE(1, 2);
--- a/hotspot/src/share/vm/interpreter/bytecodeTracer.cpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/share/vm/interpreter/bytecodeTracer.cpp	Wed Jul 05 17:04:56 2017 +0200
@@ -282,18 +282,21 @@
   constantPoolOop constants = method()->constants();
   constantTag tag = constants->tag_at(i);
 
+  int nt_index = -1;
+
   switch (tag.value()) {
   case JVM_CONSTANT_InterfaceMethodref:
   case JVM_CONSTANT_Methodref:
   case JVM_CONSTANT_Fieldref:
+  case JVM_CONSTANT_NameAndType:
     break;
   default:
     st->print_cr(" bad tag=%d at %d", tag.value(), i);
     return;
   }
 
-  symbolOop name = constants->name_ref_at(orig_i);
-  symbolOop signature = constants->signature_ref_at(orig_i);
+  symbolOop name = constants->uncached_name_ref_at(i);
+  symbolOop signature = constants->uncached_signature_ref_at(i);
   st->print_cr(" %d <%s> <%s> ", i, name->as_C_string(), signature->as_C_string());
 }
 
--- a/hotspot/src/share/vm/interpreter/interpreter.cpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/share/vm/interpreter/interpreter.cpp	Wed Jul 05 17:04:56 2017 +0200
@@ -314,6 +314,20 @@
       break;
     }
 
+   case Bytecodes::_invokedynamic: {
+      Thread *thread = Thread::current();
+      ResourceMark rm(thread);
+      methodHandle mh(thread, method);
+      type = Bytecode_invoke_at(mh, bci)->result_type(thread);
+      // since the cache entry might not be initialized:
+      // (NOT needed for the old calling convension)
+      if (!is_top_frame) {
+        int index = Bytes::get_native_u4(bcp+1);
+        method->constants()->cache()->entry_at(index)->set_parameter_size(callee_parameters);
+      }
+      break;
+    }
+
     case Bytecodes::_ldc   :
       type = constant_pool_type( method, *(bcp+1) );
       break;
--- a/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp	Wed Jul 05 17:04:56 2017 +0200
@@ -681,7 +681,7 @@
 IRT_END
 
 
-// First time execution:  Resolve symbols, create a permanent CallSiteImpl object.
+// First time execution:  Resolve symbols, create a permanent CallSite object.
 IRT_ENTRY(void, InterpreterRuntime::resolve_invokedynamic(JavaThread* thread)) {
   ResourceMark rm(thread);
 
@@ -708,21 +708,16 @@
   constantPoolHandle pool(thread, caller_method->constants());
   pool->set_invokedynamic();    // mark header to flag active call sites
 
-  int raw_index = four_byte_index(thread);
-  assert(constantPoolCacheOopDesc::is_secondary_index(raw_index), "invokedynamic indexes marked specially");
-
-  // there are two CPC entries that are of interest:
-  int site_index = constantPoolCacheOopDesc::decode_secondary_index(raw_index);
-  int main_index = pool->cache()->entry_at(site_index)->main_entry_index();
-  // and there is one CP entry, a NameAndType:
-  int nt_index = pool->map_instruction_operand_to_index(raw_index);
+  int site_index = four_byte_index(thread);
+  // there is a second CPC entries that is of interest; it caches signature info:
+  int main_index = pool->cache()->secondary_entry_at(site_index)->main_entry_index();
 
   // first resolve the signature to a MH.invoke methodOop
   if (!pool->cache()->entry_at(main_index)->is_resolved(bytecode)) {
     JvmtiHideSingleStepping jhss(thread);
     CallInfo info;
     LinkResolver::resolve_invoke(info, Handle(), pool,
-                                 raw_index, bytecode, CHECK);
+                                 site_index, bytecode, CHECK);
     // The main entry corresponds to a JVM_CONSTANT_NameAndType, and serves
     // as a common reference point for all invokedynamic call sites with
     // that exact call descriptor.  We will link it in the CP cache exactly
@@ -741,7 +736,7 @@
   assert(mh_invdyn.not_null() && mh_invdyn->is_method() && mh_invdyn->is_method_handle_invoke(),
          "correct result from LinkResolver::resolve_invokedynamic");
 
-  symbolHandle call_site_name(THREAD, pool->nt_name_ref_at(nt_index));
+  symbolHandle call_site_name(THREAD, pool->name_ref_at(site_index));
   Handle call_site
     = SystemDictionary::make_dynamic_call_site(caller_method->method_holder(),
                                                caller_method->method_idnum(),
@@ -753,61 +748,11 @@
   // In the secondary entry, the f1 field is the call site, and the f2 (index)
   // field is some data about the invoke site.
   int extra_data = 0;
-  pool->cache()->entry_at(site_index)->set_dynamic_call(call_site(), extra_data);
+  pool->cache()->secondary_entry_at(site_index)->set_dynamic_call(call_site(), extra_data);
 }
 IRT_END
 
 
-// Called on first time execution, and also whenever the CallSite.target is null.
-// FIXME:  Do more of this in Java code.
-IRT_ENTRY(void, InterpreterRuntime::bootstrap_invokedynamic(JavaThread* thread, oopDesc* call_site)) {
-  methodHandle   mh_invdyn(thread, (methodOop) sun_dyn_CallSiteImpl::vmmethod(call_site));
-  Handle         mh_type(thread,   mh_invdyn->method_handle_type());
-  objArrayHandle mh_ptypes(thread, java_dyn_MethodType::ptypes(mh_type()));
-
-  // squish the arguments down to a single array
-  int nargs = mh_ptypes->length();
-  objArrayHandle arg_array;
-  {
-    objArrayOop aaoop = oopFactory::new_objArray(SystemDictionary::object_klass(), nargs, CHECK);
-    arg_array = objArrayHandle(thread, aaoop);
-  }
-  frame fr = thread->last_frame();
-  assert(fr.interpreter_frame_bcp() != NULL, "sanity");
-  int tos_offset = 0;
-  for (int i = nargs; --i >= 0; ) {
-    intptr_t* slot_addr = fr.interpreter_frame_tos_at(tos_offset++);
-    oop ptype = mh_ptypes->obj_at(i);
-    oop arg = NULL;
-    if (!java_lang_Class::is_primitive(ptype)) {
-      arg = *(oop*) slot_addr;
-    } else {
-      BasicType bt = java_lang_Class::primitive_type(ptype);
-      assert(frame::interpreter_frame_expression_stack_direction() < 0, "else reconsider this code");
-      jvalue value;
-      Interpreter::get_jvalue_in_slot(slot_addr, bt, &value);
-      tos_offset += type2size[bt]-1;
-      arg = java_lang_boxing_object::create(bt, &value, CHECK);
-      // FIXME:  These boxing objects are not canonicalized under
-      // the Java autoboxing rules.  They should be...
-      // The best approach would be to push the arglist creation into Java.
-      // The JVM should use a lower-level interface to communicate argument lists.
-    }
-    arg_array->obj_at_put(i, arg);
-  }
-
-  // now find the bootstrap method
-  oop bootstrap_mh_oop = instanceKlass::cast(fr.interpreter_frame_method()->method_holder())->bootstrap_method();
-  assert(bootstrap_mh_oop != NULL, "resolve_invokedynamic ensures a BSM");
-
-  // return the bootstrap method and argument array via vm_result/_2
-  thread->set_vm_result(bootstrap_mh_oop);
-  thread->set_vm_result_2(arg_array());
-}
-IRT_END
-
-
-
 //------------------------------------------------------------------------------------------------------------------------
 // Miscellaneous
 
--- a/hotspot/src/share/vm/interpreter/interpreterRuntime.hpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/share/vm/interpreter/interpreterRuntime.hpp	Wed Jul 05 17:04:56 2017 +0200
@@ -91,7 +91,6 @@
   // Calls
   static void    resolve_invoke       (JavaThread* thread, Bytecodes::Code bytecode);
   static void    resolve_invokedynamic(JavaThread* thread);
-  static void  bootstrap_invokedynamic(JavaThread* thread, oopDesc* call_site);
 
   // Breakpoints
   static void _breakpoint(JavaThread* thread, methodOopDesc* method, address bcp);
--- a/hotspot/src/share/vm/interpreter/linkResolver.cpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/share/vm/interpreter/linkResolver.cpp	Wed Jul 05 17:04:56 2017 +0200
@@ -1015,11 +1015,8 @@
 
   // This guy is reached from InterpreterRuntime::resolve_invokedynamic.
 
-  assert(constantPoolCacheOopDesc::is_secondary_index(raw_index), "must be secondary index");
-  int nt_index = pool->map_instruction_operand_to_index(raw_index);
-
   // At this point, we only need the signature, and can ignore the name.
-  symbolHandle method_signature(THREAD, pool->nt_signature_ref_at(nt_index));
+  symbolHandle method_signature(THREAD, pool->signature_ref_at(raw_index));  // raw_index works directly
   symbolHandle method_name = vmSymbolHandles::invoke_name();
   KlassHandle resolved_klass = SystemDictionaryHandles::MethodHandle_klass();
 
--- a/hotspot/src/share/vm/interpreter/rewriter.cpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/share/vm/interpreter/rewriter.cpp	Wed Jul 05 17:04:56 2017 +0200
@@ -48,16 +48,6 @@
 }
 
 
-int Rewriter::add_extra_cp_cache_entry(int main_entry) {
-  // Hack: We put it on the map as an encoded value.
-  // The only place that consumes this is ConstantPoolCacheEntry::set_initial_state
-  int encoded = constantPoolCacheOopDesc::encode_secondary_index(main_entry);
-  int plain_secondary_index = _cp_cache_map.append(encoded);
-  return constantPoolCacheOopDesc::encode_secondary_index(plain_secondary_index);
-}
-
-
-
 // Creates a constant pool cache given a CPC map
 // This creates the constant pool cache initially in a state
 // that is unsafe for concurrent GC processing but sets it to
@@ -127,7 +117,7 @@
   assert(p[-1] == Bytecodes::_invokedynamic, "");
   int cp_index = Bytes::get_Java_u2(p);
   int cpc  = maybe_add_cp_cache_entry(cp_index);  // add lazily
-  int cpc2 = add_extra_cp_cache_entry(cpc);
+  int cpc2 = add_secondary_cp_cache_entry(cpc);
 
   // Replace the trailing four bytes with a CPC index for the dynamic
   // call site.  Unlike other CPC entries, there is one per bytecode,
@@ -137,7 +127,7 @@
   // all these entries.  That is the main reason invokedynamic
   // must have a five-byte instruction format.  (Of course, other JVM
   // implementations can use the bytes for other purposes.)
-  Bytes::put_native_u4(p, cpc2);
+  Bytes::put_native_u4(p, constantPoolCacheOopDesc::encode_secondary_index(cpc2));
   // Note: We use native_u4 format exclusively for 4-byte indexes.
 }
 
--- a/hotspot/src/share/vm/interpreter/rewriter.hpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/share/vm/interpreter/rewriter.hpp	Wed Jul 05 17:04:56 2017 +0200
@@ -43,13 +43,18 @@
   bool has_cp_cache(int i) { return (uint)i < (uint)_cp_map.length() && _cp_map[i] >= 0; }
   int maybe_add_cp_cache_entry(int i) { return has_cp_cache(i) ? _cp_map[i] : add_cp_cache_entry(i); }
   int add_cp_cache_entry(int cp_index) {
+    assert((cp_index & _secondary_entry_tag) == 0, "bad tag");
     assert(_cp_map[cp_index] == -1, "not twice on same cp_index");
     int cache_index = _cp_cache_map.append(cp_index);
     _cp_map.at_put(cp_index, cache_index);
     assert(cp_entry_to_cp_cache(cp_index) == cache_index, "");
     return cache_index;
   }
-  int add_extra_cp_cache_entry(int main_entry);
+  int add_secondary_cp_cache_entry(int main_cpc_entry) {
+    assert(main_cpc_entry < _cp_cache_map.length(), "must be earlier CP cache entry");
+    int cache_index = _cp_cache_map.append(main_cpc_entry | _secondary_entry_tag);
+    return cache_index;
+  }
 
   // All the work goes in here:
   Rewriter(instanceKlassHandle klass, TRAPS);
@@ -65,4 +70,8 @@
  public:
   // Driver routine:
   static void rewrite(instanceKlassHandle klass, TRAPS);
+
+  enum {
+    _secondary_entry_tag = nth_bit(30)
+  };
 };
--- a/hotspot/src/share/vm/interpreter/templateInterpreter.cpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/share/vm/interpreter/templateInterpreter.cpp	Wed Jul 05 17:04:56 2017 +0200
@@ -178,14 +178,12 @@
 #endif // !PRODUCT
 EntryPoint TemplateInterpreter::_return_entry[TemplateInterpreter::number_of_return_entries];
 EntryPoint TemplateInterpreter::_earlyret_entry;
-EntryPoint TemplateInterpreter::_return_unbox_entry;
 EntryPoint TemplateInterpreter::_deopt_entry [TemplateInterpreter::number_of_deopt_entries ];
 EntryPoint TemplateInterpreter::_continuation_entry;
 EntryPoint TemplateInterpreter::_safept_entry;
 
 address    TemplateInterpreter::_return_3_addrs_by_index[TemplateInterpreter::number_of_return_addrs];
 address    TemplateInterpreter::_return_5_addrs_by_index[TemplateInterpreter::number_of_return_addrs];
-address    TemplateInterpreter::_return_5_unbox_addrs_by_index[TemplateInterpreter::number_of_return_addrs];
 
 DispatchTable TemplateInterpreter::_active_table;
 DispatchTable TemplateInterpreter::_normal_table;
@@ -253,22 +251,6 @@
     }
   }
 
-  if (EnableInvokeDynamic) {
-    CodeletMark cm(_masm, "unboxing return entry points");
-    Interpreter::_return_unbox_entry =
-      EntryPoint(
-        generate_return_unbox_entry_for(btos, 5),
-        generate_return_unbox_entry_for(ctos, 5),
-        generate_return_unbox_entry_for(stos, 5),
-        generate_return_unbox_entry_for(atos, 5), // cast conversion
-        generate_return_unbox_entry_for(itos, 5),
-        generate_return_unbox_entry_for(ltos, 5),
-        generate_return_unbox_entry_for(ftos, 5),
-        generate_return_unbox_entry_for(dtos, 5),
-        Interpreter::_return_entry[5].entry(vtos) // no unboxing for void
-      );
-  }
-
   { CodeletMark cm(_masm, "earlyret entry points");
     Interpreter::_earlyret_entry =
       EntryPoint(
@@ -319,8 +301,6 @@
     int index = Interpreter::TosState_as_index(states[j]);
     Interpreter::_return_3_addrs_by_index[index] = Interpreter::return_entry(states[j], 3);
     Interpreter::_return_5_addrs_by_index[index] = Interpreter::return_entry(states[j], 5);
-    if (EnableInvokeDynamic)
-      Interpreter::_return_5_unbox_addrs_by_index[index] = Interpreter::return_unbox_entry(states[j], 5);
   }
 
   { CodeletMark cm(_masm, "continuation entry points");
@@ -485,9 +465,11 @@
 void TemplateInterpreterGenerator::set_short_entry_points(Template* t, address& bep, address& cep, address& sep, address& aep, address& iep, address& lep, address& fep, address& dep, address& vep) {
   assert(t->is_valid(), "template must exist");
   switch (t->tos_in()) {
-    case btos: vep = __ pc(); __ pop(btos); bep = __ pc(); generate_and_dispatch(t); break;
-    case ctos: vep = __ pc(); __ pop(ctos); sep = __ pc(); generate_and_dispatch(t); break;
-    case stos: vep = __ pc(); __ pop(stos); sep = __ pc(); generate_and_dispatch(t); break;
+    case btos:
+    case ctos:
+    case stos:
+      ShouldNotReachHere();  // btos/ctos/stos should use itos.
+      break;
     case atos: vep = __ pc(); __ pop(atos); aep = __ pc(); generate_and_dispatch(t); break;
     case itos: vep = __ pc(); __ pop(itos); iep = __ pc(); generate_and_dispatch(t); break;
     case ltos: vep = __ pc(); __ pop(ltos); lep = __ pc(); generate_and_dispatch(t); break;
@@ -547,18 +529,6 @@
 }
 
 
-address TemplateInterpreter::return_unbox_entry(TosState state, int length) {
-  assert(EnableInvokeDynamic, "");
-  if (state == vtos) {
-    // no unboxing to do, actually
-    return return_entry(state, length);
-  } else {
-    assert(length == 5, "unboxing entries generated for invokedynamic only");
-    return _return_unbox_entry.entry(state);
-  }
-}
-
-
 address TemplateInterpreter::deopt_entry(TosState state, int length) {
   guarantee(0 <= length && length < Interpreter::number_of_deopt_entries, "illegal length");
   return _deopt_entry[length].entry(state);
--- a/hotspot/src/share/vm/interpreter/templateInterpreter.hpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/share/vm/interpreter/templateInterpreter.hpp	Wed Jul 05 17:04:56 2017 +0200
@@ -110,14 +110,12 @@
 #endif // !PRODUCT
   static EntryPoint _return_entry[number_of_return_entries];    // entry points to return to from a call
   static EntryPoint _earlyret_entry;                            // entry point to return early from a call
-  static EntryPoint _return_unbox_entry;                        // entry point to unbox a return value from a call
   static EntryPoint _deopt_entry[number_of_deopt_entries];      // entry points to return to from a deoptimization
   static EntryPoint _continuation_entry;
   static EntryPoint _safept_entry;
 
   static address    _return_3_addrs_by_index[number_of_return_addrs];     // for invokevirtual   return entries
   static address    _return_5_addrs_by_index[number_of_return_addrs];     // for invokeinterface return entries
-  static address    _return_5_unbox_addrs_by_index[number_of_return_addrs]; // for invokedynamic bootstrap methods
 
   static DispatchTable _active_table;                           // the active    dispatch table (used by the interpreter for dispatch)
   static DispatchTable _normal_table;                           // the normal    dispatch table (used to set the active table in normal mode)
@@ -159,12 +157,10 @@
   // Support for invokes
   static address*   return_3_addrs_by_index_table()             { return _return_3_addrs_by_index; }
   static address*   return_5_addrs_by_index_table()             { return _return_5_addrs_by_index; }
-  static address*   return_5_unbox_addrs_by_index_table()       { return _return_5_unbox_addrs_by_index; }
   static int        TosState_as_index(TosState state);          // computes index into return_3_entry_by_index table
 
   static address    return_entry  (TosState state, int length);
   static address    deopt_entry   (TosState state, int length);
-  static address    return_unbox_entry(TosState state, int length);
 
   // Safepoint support
   static void       notice_safepoints();                        // stops the thread when reaching a safepoint
--- a/hotspot/src/share/vm/interpreter/templateInterpreterGenerator.hpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/share/vm/interpreter/templateInterpreterGenerator.hpp	Wed Jul 05 17:04:56 2017 +0200
@@ -51,10 +51,7 @@
   address generate_WrongMethodType_handler();
   address generate_ArrayIndexOutOfBounds_handler(const char* name);
   address generate_continuation_for(TosState state);
-  address generate_return_entry_for(TosState state, int step, bool unbox = false);
-  address generate_return_unbox_entry_for(TosState state, int step) {
-    return generate_return_entry_for(state, step, true);
-  }
+  address generate_return_entry_for(TosState state, int step);
   address generate_earlyret_entry_for(TosState state);
   address generate_deopt_entry_for(TosState state, int step);
   address generate_safept_entry_for(TosState state, address runtime_entry);
--- a/hotspot/src/share/vm/memory/barrierSet.cpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/share/vm/memory/barrierSet.cpp	Wed Jul 05 17:04:56 2017 +0200
@@ -41,11 +41,6 @@
 
 // count is number of array elements being written
 void BarrierSet::static_write_ref_array_post(HeapWord* start, size_t count) {
-  assert(count <= (size_t)max_intx, "count too large");
-  HeapWord* end = start + objArrayOopDesc::array_size((int)count);
-#if 0
-  warning("Post:\t" INTPTR_FORMAT "[" SIZE_FORMAT "] : [" INTPTR_FORMAT","INTPTR_FORMAT")\t",
-                   start,            count,              start,          end);
-#endif
-  Universe::heap()->barrier_set()->write_ref_array_work(MemRegion(start, end));
+  // simply delegate to instance method
+  Universe::heap()->barrier_set()->write_ref_array(start, count);
 }
--- a/hotspot/src/share/vm/memory/barrierSet.hpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/share/vm/memory/barrierSet.hpp	Wed Jul 05 17:04:56 2017 +0200
@@ -121,17 +121,20 @@
   virtual void read_ref_array(MemRegion mr) = 0;
   virtual void read_prim_array(MemRegion mr) = 0;
 
+  // Below length is the # array elements being written
   virtual void write_ref_array_pre(      oop* dst, int length) {}
   virtual void write_ref_array_pre(narrowOop* dst, int length) {}
+  // Below MemRegion mr is expected to be HeapWord-aligned
   inline void write_ref_array(MemRegion mr);
+  // Below count is the # array elements being written, starting
+  // at the address "start", which may not necessarily be HeapWord-aligned
+  inline void write_ref_array(HeapWord* start, size_t count);
 
-  // Static versions, suitable for calling from generated code.
+  // Static versions, suitable for calling from generated code;
+  // count is # array elements being written, starting with "start",
+  // which may not necessarily be HeapWord-aligned.
   static void static_write_ref_array_pre(HeapWord* start, size_t count);
   static void static_write_ref_array_post(HeapWord* start, size_t count);
-  // Narrow oop versions of the above; count is # of array elements being written,
-  // starting with "start", which is HeapWord-aligned.
-  static void static_write_ref_array_pre_narrow(HeapWord* start, size_t count);
-  static void static_write_ref_array_post_narrow(HeapWord* start, size_t count);
 
 protected:
   virtual void write_ref_array_work(MemRegion mr) = 0;
--- a/hotspot/src/share/vm/memory/barrierSet.inline.hpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/share/vm/memory/barrierSet.inline.hpp	Wed Jul 05 17:04:56 2017 +0200
@@ -43,6 +43,8 @@
 }
 
 void BarrierSet::write_ref_array(MemRegion mr) {
+  assert((HeapWord*)align_size_down((uintptr_t)mr.start(), HeapWordSize) == mr.start() , "Unaligned start");
+  assert((HeapWord*)align_size_up  ((uintptr_t)mr.end(),   HeapWordSize) == mr.end(),    "Unaligned end"  );
   if (kind() == CardTableModRef) {
     ((CardTableModRefBS*)this)->inline_write_ref_array(mr);
   } else {
@@ -50,6 +52,34 @@
   }
 }
 
+// count is number of array elements being written
+void BarrierSet::write_ref_array(HeapWord* start, size_t count) {
+  assert(count <= (size_t)max_intx, "count too large");
+  HeapWord* end = (HeapWord*)((char*)start + (count*heapOopSize));
+  // In the case of compressed oops, start and end may potentially be misaligned;
+  // so we need to conservatively align the first downward (this is not
+  // strictly necessary for current uses, but a case of good hygiene and,
+  // if you will, aesthetics) and the second upward (this is essential for
+  // current uses) to a HeapWord boundary, so we mark all cards overlapping
+  // this write. In the event that this evolves in the future to calling a
+  // logging barrier of narrow oop granularity, like the pre-barrier for G1
+  // (mentioned here merely by way of example), we will need to change this
+  // interface, much like the pre-barrier one above, so it is "exactly precise"
+  // (if i may be allowed the adverbial redundancy for emphasis) and does not
+  // include narrow oop slots not included in the original write interval.
+  HeapWord* aligned_start = (HeapWord*)align_size_down((uintptr_t)start, HeapWordSize);
+  HeapWord* aligned_end   = (HeapWord*)align_size_up  ((uintptr_t)end,   HeapWordSize);
+  // If compressed oops were not being used, these should already be aligned
+  assert(UseCompressedOops || (aligned_start == start && aligned_end == end),
+         "Expected heap word alignment of start and end");
+#if 0
+  warning("Post:\t" INTPTR_FORMAT "[" SIZE_FORMAT "] : [" INTPTR_FORMAT","INTPTR_FORMAT")\t",
+                   start,            count,              aligned_start,   aligned_end);
+#endif
+  write_ref_array_work(MemRegion(aligned_start, aligned_end));
+}
+
+
 void BarrierSet::write_region(MemRegion mr) {
   if (kind() == CardTableModRef) {
     ((CardTableModRefBS*)this)->inline_write_region(mr);
--- a/hotspot/src/share/vm/memory/cardTableModRefBS.cpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/share/vm/memory/cardTableModRefBS.cpp	Wed Jul 05 17:04:56 2017 +0200
@@ -511,6 +511,8 @@
 }
 
 void CardTableModRefBS::dirty_MemRegion(MemRegion mr) {
+  assert((HeapWord*)align_size_down((uintptr_t)mr.start(), HeapWordSize) == mr.start(), "Unaligned start");
+  assert((HeapWord*)align_size_up  ((uintptr_t)mr.end(),   HeapWordSize) == mr.end(),   "Unaligned end"  );
   jbyte* cur  = byte_for(mr.start());
   jbyte* last = byte_after(mr.last());
   while (cur < last) {
@@ -520,6 +522,8 @@
 }
 
 void CardTableModRefBS::invalidate(MemRegion mr, bool whole_heap) {
+  assert((HeapWord*)align_size_down((uintptr_t)mr.start(), HeapWordSize) == mr.start(), "Unaligned start");
+  assert((HeapWord*)align_size_up  ((uintptr_t)mr.end(),   HeapWordSize) == mr.end(),   "Unaligned end"  );
   for (int i = 0; i < _cur_covered_regions; i++) {
     MemRegion mri = mr.intersection(_covered[i]);
     if (!mri.is_empty()) dirty_MemRegion(mri);
--- a/hotspot/src/share/vm/memory/collectorPolicy.cpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/share/vm/memory/collectorPolicy.cpp	Wed Jul 05 17:04:56 2017 +0200
@@ -55,7 +55,7 @@
 
 void CollectorPolicy::initialize_size_info() {
   // User inputs from -mx and ms are aligned
-  set_initial_heap_byte_size(Arguments::initial_heap_size());
+  set_initial_heap_byte_size(InitialHeapSize);
   if (initial_heap_byte_size() == 0) {
     set_initial_heap_byte_size(NewSize + OldSize);
   }
--- a/hotspot/src/share/vm/memory/heap.cpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/share/vm/memory/heap.cpp	Wed Jul 05 17:04:56 2017 +0200
@@ -464,7 +464,7 @@
   }
 
   // Verify that freelist contains the right amount of free space
-  guarantee(len == _free_segments, "wrong freelist");
+  //  guarantee(len == _free_segments, "wrong freelist");
 
   // Verify that the number of free blocks is not out of hand.
   static int free_block_threshold = 10000;
@@ -479,5 +479,5 @@
   for(HeapBlock *h = first_block(); h != NULL; h = next_block(h)) {
     if (h->free()) count--;
   }
-  guarantee(count == 0, "missing free blocks");
+  //  guarantee(count == 0, "missing free blocks");
 }
--- a/hotspot/src/share/vm/memory/referenceProcessor.cpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/share/vm/memory/referenceProcessor.cpp	Wed Jul 05 17:04:56 2017 +0200
@@ -299,8 +299,8 @@
 
 
 template <class T>
-static bool enqueue_discovered_ref_helper(ReferenceProcessor* ref,
-                                          AbstractRefProcTaskExecutor* task_executor) {
+bool enqueue_discovered_ref_helper(ReferenceProcessor* ref,
+                                   AbstractRefProcTaskExecutor* task_executor) {
 
   // Remember old value of pending references list
   T* pending_list_addr = (T*)java_lang_ref_Reference::pending_list_addr();
--- a/hotspot/src/share/vm/memory/sharedHeap.hpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/share/vm/memory/sharedHeap.hpp	Wed Jul 05 17:04:56 2017 +0200
@@ -224,10 +224,6 @@
                           CodeBlobClosure* code_roots,
                           OopClosure* non_root_closure);
 
-
-  // Like CollectedHeap::collect, but assume that the caller holds the Heap_lock.
-  virtual void collect_locked(GCCause::Cause cause) = 0;
-
   // The functions below are helper functions that a subclass of
   // "SharedHeap" can use in the implementation of its virtual
   // functions.
--- a/hotspot/src/share/vm/memory/universe.cpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/share/vm/memory/universe.cpp	Wed Jul 05 17:04:56 2017 +0200
@@ -67,6 +67,8 @@
 objArrayOop Universe::_the_empty_system_obj_array     = NULL;
 objArrayOop Universe::_the_empty_class_klass_array    = NULL;
 objArrayOop Universe::_the_array_interfaces_array     = NULL;
+oop Universe::_the_null_string                        = NULL;
+oop Universe::_the_min_jint_string                   = NULL;
 LatestMethodOopCache* Universe::_finalizer_register_cache = NULL;
 LatestMethodOopCache* Universe::_loader_addClass_cache    = NULL;
 ActiveMethodOopsCache* Universe::_reflect_invoke_cache    = NULL;
@@ -187,6 +189,8 @@
   f->do_oop((oop*)&_the_empty_system_obj_array);
   f->do_oop((oop*)&_the_empty_class_klass_array);
   f->do_oop((oop*)&_the_array_interfaces_array);
+  f->do_oop((oop*)&_the_null_string);
+  f->do_oop((oop*)&_the_min_jint_string);
   _finalizer_register_cache->oops_do(f);
   _loader_addClass_cache->oops_do(f);
   _reflect_invoke_cache->oops_do(f);
@@ -289,6 +293,9 @@
 
     klassOop ok = SystemDictionary::object_klass();
 
+    _the_null_string            = StringTable::intern("null", CHECK);
+    _the_min_jint_string       = StringTable::intern("-2147483648", CHECK);
+
     if (UseSharedSpaces) {
       // Verify shared interfaces array.
       assert(_the_array_interfaces_array->obj_at(0) ==
@@ -744,22 +751,22 @@
 static const uint64_t OopEncodingHeapMax = NarrowOopHeapMax << LogMinObjAlignmentInBytes;
 
 char* Universe::preferred_heap_base(size_t heap_size, NARROW_OOP_MODE mode) {
+  size_t base = 0;
 #ifdef _LP64
   if (UseCompressedOops) {
     assert(mode == UnscaledNarrowOop  ||
            mode == ZeroBasedNarrowOop ||
            mode == HeapBasedNarrowOop, "mode is invalid");
+    const size_t total_size = heap_size + HeapBaseMinAddress;
     // Return specified base for the first request.
     if (!FLAG_IS_DEFAULT(HeapBaseMinAddress) && (mode == UnscaledNarrowOop)) {
-      return (char*)HeapBaseMinAddress;
-    }
-    const size_t total_size = heap_size + HeapBaseMinAddress;
-    if (total_size <= OopEncodingHeapMax && (mode != HeapBasedNarrowOop)) {
+      base = HeapBaseMinAddress;
+    } else if (total_size <= OopEncodingHeapMax && (mode != HeapBasedNarrowOop)) {
       if (total_size <= NarrowOopHeapMax && (mode == UnscaledNarrowOop) &&
           (Universe::narrow_oop_shift() == 0)) {
         // Use 32-bits oops without encoding and
         // place heap's top on the 4Gb boundary
-        return (char*)(NarrowOopHeapMax - heap_size);
+        base = (NarrowOopHeapMax - heap_size);
       } else {
         // Can't reserve with NarrowOopShift == 0
         Universe::set_narrow_oop_shift(LogMinObjAlignmentInBytes);
@@ -768,16 +775,38 @@
           // Use zero based compressed oops with encoding and
           // place heap's top on the 32Gb boundary in case
           // total_size > 4Gb or failed to reserve below 4Gb.
-          return (char*)(OopEncodingHeapMax - heap_size);
+          base = (OopEncodingHeapMax - heap_size);
         }
       }
     } else {
       // Can't reserve below 32Gb.
       Universe::set_narrow_oop_shift(LogMinObjAlignmentInBytes);
     }
+    // Set narrow_oop_base and narrow_oop_use_implicit_null_checks
+    // used in ReservedHeapSpace() constructors.
+    // The final values will be set in initialize_heap() below.
+    if (base != 0 && (base + heap_size) <= OopEncodingHeapMax) {
+      // Use zero based compressed oops
+      Universe::set_narrow_oop_base(NULL);
+      // Don't need guard page for implicit checks in indexed
+      // addressing mode with zero based Compressed Oops.
+      Universe::set_narrow_oop_use_implicit_null_checks(true);
+    } else {
+      // Set to a non-NULL value so the ReservedSpace ctor computes
+      // the correct no-access prefix.
+      // The final value will be set in initialize_heap() below.
+      Universe::set_narrow_oop_base((address)NarrowOopHeapMax);
+#ifdef _WIN64
+      if (UseLargePages) {
+        // Cannot allocate guard pages for implicit checks in indexed
+        // addressing mode when large pages are specified on windows.
+        Universe::set_narrow_oop_use_implicit_null_checks(false);
+      }
+#endif //  _WIN64
+    }
   }
 #endif
-  return NULL; // also return NULL (don't care) for 32-bit VM
+  return (char*)base; // also return NULL (don't care) for 32-bit VM
 }
 
 jint Universe::initialize_heap() {
--- a/hotspot/src/share/vm/memory/universe.hpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/share/vm/memory/universe.hpp	Wed Jul 05 17:04:56 2017 +0200
@@ -169,6 +169,8 @@
   static objArrayOop  _the_empty_system_obj_array;    // Canonicalized system obj array
   static objArrayOop  _the_empty_class_klass_array;   // Canonicalized obj array of type java.lang.Class
   static objArrayOop  _the_array_interfaces_array;    // Canonicalized 2-array of cloneable & serializable klasses
+  static oop          _the_null_string;               // A cache of "null" as a Java string
+  static oop          _the_min_jint_string;          // A cache of "-2147483648" as a Java string
   static LatestMethodOopCache* _finalizer_register_cache; // static method for registering finalizable objects
   static LatestMethodOopCache* _loader_addClass_cache;    // method for registering loaded classes in class loader vector
   static ActiveMethodOopsCache* _reflect_invoke_cache;    // method for security checks
@@ -310,6 +312,8 @@
   static objArrayOop  the_empty_system_obj_array ()   { return _the_empty_system_obj_array;    }
   static objArrayOop  the_empty_class_klass_array ()  { return _the_empty_class_klass_array;   }
   static objArrayOop  the_array_interfaces_array()    { return _the_array_interfaces_array;    }
+  static oop          the_null_string()               { return _the_null_string;               }
+  static oop          the_min_jint_string()          { return _the_min_jint_string;          }
   static methodOop    finalizer_register_method()     { return _finalizer_register_cache->get_methodOop(); }
   static methodOop    loader_addClass_method()        { return _loader_addClass_cache->get_methodOop(); }
   static ActiveMethodOopsCache* reflect_invoke_cache() { return _reflect_invoke_cache; }
--- a/hotspot/src/share/vm/oops/constantPoolOop.cpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/share/vm/oops/constantPoolOop.cpp	Wed Jul 05 17:04:56 2017 +0200
@@ -262,25 +262,48 @@
 
 
 int constantPoolOopDesc::impl_name_and_type_ref_index_at(int which, bool uncached) {
-  jint ref_index = field_or_method_at(which, uncached);
+  int i = which;
+  if (!uncached && cache() != NULL) {
+    if (constantPoolCacheOopDesc::is_secondary_index(which))
+      // Invokedynamic indexes are always processed in native order
+      // so there is no question of reading a native u2 in Java order here.
+      return cache()->main_entry_at(which)->constant_pool_index();
+    // change byte-ordering and go via cache
+    i = remap_instruction_operand_from_cache(which);
+  } else {
+    if (tag_at(which).is_name_and_type())
+      // invokedynamic index is a simple name-and-type
+      return which;
+  }
+  assert(tag_at(i).is_field_or_method(), "Corrupted constant pool");
+  jint ref_index = *int_at_addr(i);
   return extract_high_short_from_int(ref_index);
 }
 
 
 int constantPoolOopDesc::impl_klass_ref_index_at(int which, bool uncached) {
-  jint ref_index = field_or_method_at(which, uncached);
+  guarantee(!constantPoolCacheOopDesc::is_secondary_index(which),
+            "an invokedynamic instruction does not have a klass");
+  int i = which;
+  if (!uncached && cache() != NULL) {
+    // change byte-ordering and go via cache
+    i = remap_instruction_operand_from_cache(which);
+  }
+  assert(tag_at(i).is_field_or_method(), "Corrupted constant pool");
+  jint ref_index = *int_at_addr(i);
   return extract_low_short_from_int(ref_index);
 }
 
 
 
-int constantPoolOopDesc::map_instruction_operand_to_index(int operand) {
-  if (constantPoolCacheOopDesc::is_secondary_index(operand)) {
-    return cache()->main_entry_at(operand)->constant_pool_index();
-  }
+int constantPoolOopDesc::remap_instruction_operand_from_cache(int operand) {
+  // Operand was fetched by a stream using get_Java_u2, yet was stored
+  // by Rewriter::rewrite_member_reference in native order.
+  // So now we have to fix the damage by swapping back to native order.
   assert((int)(u2)operand == operand, "clean u2");
-  int index = Bytes::swap_u2(operand);
-  return cache()->entry_at(index)->constant_pool_index();
+  int cpc_index = Bytes::swap_u2(operand);
+  int member_index = cache()->entry_at(cpc_index)->constant_pool_index();
+  return member_index;
 }
 
 
--- a/hotspot/src/share/vm/oops/constantPoolOop.hpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/share/vm/oops/constantPoolOop.hpp	Wed Jul 05 17:04:56 2017 +0200
@@ -342,12 +342,14 @@
   }
 
   // The following methods (name/signature/klass_ref_at, klass_ref_at_noresolve,
-  // name_and_type_ref_index_at) all expect constant pool indices
-  // from the bytecodes to be passed in, which are actually potentially byte-swapped
-  // or rewritten constant pool cache indices.  They all call map_instruction_operand_to_index.
-  int map_instruction_operand_to_index(int operand);
+  // name_and_type_ref_index_at) all expect to be passed indices obtained
+  // directly from the bytecode, and extracted according to java byte order.
+  // If the indices are meant to refer to fields or methods, they are
+  // actually potentially byte-swapped, rewritten constant pool cache indices.
+  // The routine remap_instruction_operand_from_cache manages the adjustment
+  // of these values back to constant pool indices.
 
-  // There are also "uncached" versions which do not map the operand index; see below.
+  // There are also "uncached" versions which do not adjust the operand index; see below.
 
   // Lookup for entries consisting of (klass_index, name_and_type index)
   klassOop klass_ref_at(int which, TRAPS);
@@ -361,8 +363,6 @@
   // Lookup for entries consisting of (name_index, signature_index)
   int name_ref_index_at(int which_nt);            // ==  low-order jshort of name_and_type_at(which_nt)
   int signature_ref_index_at(int which_nt);       // == high-order jshort of name_and_type_at(which_nt)
-  symbolOop nt_name_ref_at(int which_nt)          { return symbol_at(name_ref_index_at(which_nt)); }
-  symbolOop nt_signature_ref_at(int which_nt)     { return symbol_at(signature_ref_index_at(which_nt)); }
 
   BasicType basic_type_for_signature_at(int which);
 
@@ -425,18 +425,7 @@
   int       impl_klass_ref_index_at(int which, bool uncached);
   int       impl_name_and_type_ref_index_at(int which, bool uncached);
 
-  // Takes either a constant pool cache index in possibly byte-swapped
-  // byte order (which comes from the bytecodes after rewriting) or,
-  // if "uncached" is true, a vanilla constant pool index
-  jint field_or_method_at(int which, bool uncached) {
-    int i = which;
-    if (!uncached && cache() != NULL) {
-      // change byte-ordering and go via cache
-      i = map_instruction_operand_to_index(which);
-    }
-    assert(tag_at(i).is_field_or_method(), "Corrupted constant pool");
-    return *int_at_addr(i);
-  }
+  int remap_instruction_operand_from_cache(int operand);
 
   // Used while constructing constant pool (only by ClassFileParser)
   jint klass_index_at(int which) {
--- a/hotspot/src/share/vm/oops/cpCacheOop.cpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/share/vm/oops/cpCacheOop.cpp	Wed Jul 05 17:04:56 2017 +0200
@@ -28,21 +28,17 @@
 
 // Implememtation of ConstantPoolCacheEntry
 
-void ConstantPoolCacheEntry::set_initial_state(int index) {
-  if (constantPoolCacheOopDesc::is_secondary_index(index)) {
-    // Hack:  The rewriter is trying to say that this entry itself
-    // will be a secondary entry.
-    int main_index = constantPoolCacheOopDesc::decode_secondary_index(index);
-    assert(0 <= main_index && main_index < 0x10000, "sanity check");
-    _indices = (main_index << 16);
-    assert(main_entry_index() == main_index, "");
-    return;
-  }
+void ConstantPoolCacheEntry::initialize_entry(int index) {
   assert(0 < index && index < 0x10000, "sanity check");
   _indices = index;
   assert(constant_pool_index() == index, "");
 }
 
+void ConstantPoolCacheEntry::initialize_secondary_entry(int main_index) {
+  assert(0 <= main_index && main_index < 0x10000, "sanity check");
+  _indices = (main_index << 16);
+  assert(main_entry_index() == main_index, "");
+}
 
 int ConstantPoolCacheEntry::as_flags(TosState state, bool is_final,
                     bool is_vfinal, bool is_volatile,
@@ -223,10 +219,10 @@
 
 
 void ConstantPoolCacheEntry::set_dynamic_call(Handle call_site, int extra_data) {
-  methodOop method = (methodOop) sun_dyn_CallSiteImpl::vmmethod(call_site());
+  methodOop method = (methodOop) java_dyn_CallSite::vmmethod(call_site());
   assert(method->is_method(), "must be initialized properly");
   int param_size = method->size_of_parameters();
-  assert(param_size > 1, "method argument size must include MH.this & initial dynamic receiver");
+  assert(param_size >= 1, "method argument size must include MH.this");
   param_size -= 1;              // do not count MH.this; it is not stacked for invokedynamic
   if (Atomic::cmpxchg_ptr(call_site(), &_f1, NULL) == NULL) {
     // racing threads might be trying to install their own favorites
@@ -439,7 +435,18 @@
 
 void constantPoolCacheOopDesc::initialize(intArray& inverse_index_map) {
   assert(inverse_index_map.length() == length(), "inverse index map must have same length as cache");
-  for (int i = 0; i < length(); i++) entry_at(i)->set_initial_state(inverse_index_map[i]);
+  for (int i = 0; i < length(); i++) {
+    ConstantPoolCacheEntry* e = entry_at(i);
+    int original_index = inverse_index_map[i];
+    if ((original_index & Rewriter::_secondary_entry_tag) != 0) {
+      int main_index = (original_index - Rewriter::_secondary_entry_tag);
+      assert(!entry_at(main_index)->is_secondary_entry(), "valid main index");
+      e->initialize_secondary_entry(main_index);
+    } else {
+      e->initialize_entry(original_index);
+    }
+    assert(entry_at(i) == e, "sanity");
+  }
 }
 
 // RedefineClasses() API support:
--- a/hotspot/src/share/vm/oops/cpCacheOop.hpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/share/vm/oops/cpCacheOop.hpp	Wed Jul 05 17:04:56 2017 +0200
@@ -154,7 +154,8 @@
   };
 
   // Initialization
-  void set_initial_state(int index);             // sets entry to initial state
+  void initialize_entry(int original_index);     // initialize primary entry
+  void initialize_secondary_entry(int main_index); // initialize secondary entry
 
   void set_field(                                // sets entry to resolved field state
     Bytecodes::Code get_code,                    // the bytecode used for reading the field
@@ -251,6 +252,7 @@
 
   // Code generation support
   static WordSize size()                         { return in_WordSize(sizeof(ConstantPoolCacheEntry) / HeapWordSize); }
+  static ByteSize size_in_bytes()                { return in_ByteSize(sizeof(ConstantPoolCacheEntry)); }
   static ByteSize indices_offset()               { return byte_offset_of(ConstantPoolCacheEntry, _indices); }
   static ByteSize f1_offset()                    { return byte_offset_of(ConstantPoolCacheEntry, _f1); }
   static ByteSize f2_offset()                    { return byte_offset_of(ConstantPoolCacheEntry, _f2); }
@@ -321,6 +323,7 @@
   ConstantPoolCacheEntry* base() const           { return (ConstantPoolCacheEntry*)((address)this + in_bytes(base_offset())); }
 
   friend class constantPoolCacheKlass;
+  friend class ConstantPoolCacheEntry;
 
  public:
   // Initialization
@@ -329,7 +332,8 @@
   // Secondary indexes.
   // They must look completely different from normal indexes.
   // The main reason is that byte swapping is sometimes done on normal indexes.
-  // Also, it is helpful for debugging to tell the two apart.
+  // Also, some of the CP accessors do different things for secondary indexes.
+  // Finally, it is helpful for debugging to tell the two apart.
   static bool is_secondary_index(int i) { return (i < 0); }
   static int  decode_secondary_index(int i) { assert(is_secondary_index(i),  ""); return ~i; }
   static int  encode_secondary_index(int i) { assert(!is_secondary_index(i), ""); return ~i; }
@@ -337,18 +341,35 @@
   // Accessors
   void set_constant_pool(constantPoolOop pool)   { oop_store_without_check((oop*)&_constant_pool, (oop)pool); }
   constantPoolOop constant_pool() const          { return _constant_pool; }
-  ConstantPoolCacheEntry* entry_at(int i) const  { assert(0 <= i && i < length(), "index out of bounds"); return base() + i; }
+  // Fetches the entry at the given index.
+  // The entry may be either primary or secondary.
+  // In either case the index must not be encoded or byte-swapped in any way.
+  ConstantPoolCacheEntry* entry_at(int i) const {
+    assert(0 <= i && i < length(), "index out of bounds");
+    return base() + i;
+  }
+  // Fetches the secondary entry referred to by index.
+  // The index may be a secondary index, and must not be byte-swapped.
+  ConstantPoolCacheEntry* secondary_entry_at(int i) const {
+    int raw_index = i;
+    if (is_secondary_index(i)) {  // correct these on the fly
+      raw_index = decode_secondary_index(i);
+    }
+    assert(entry_at(raw_index)->is_secondary_entry(), "not a secondary entry");
+    return entry_at(raw_index);
+  }
+  // Given a primary or secondary index, fetch the corresponding primary entry.
+  // Indirect through the secondary entry, if the index is encoded as a secondary index.
+  // The index must not be byte-swapped.
   ConstantPoolCacheEntry* main_entry_at(int i) const {
-    ConstantPoolCacheEntry* e;
+    int primary_index = i;
     if (is_secondary_index(i)) {
       // run through an extra level of indirection:
-      i = decode_secondary_index(i);
-      e = entry_at(i);
-      i = e->main_entry_index();
+      int raw_index = decode_secondary_index(i);
+      primary_index = entry_at(raw_index)->main_entry_index();
     }
-    e = entry_at(i);
-    assert(!e->is_secondary_entry(), "only one level of indirection");
-    return e;
+    assert(!entry_at(primary_index)->is_secondary_entry(), "only one level of indirection");
+    return entry_at(primary_index);
   }
 
   // GC support
@@ -359,6 +380,12 @@
 
   // Code generation
   static ByteSize base_offset()                  { return in_ByteSize(sizeof(constantPoolCacheOopDesc)); }
+  static ByteSize entry_offset(int raw_index) {
+    int index = raw_index;
+    if (is_secondary_index(raw_index))
+      index = decode_secondary_index(raw_index);
+    return (base_offset() + ConstantPoolCacheEntry::size_in_bytes() * index);
+  }
 
   // RedefineClasses() API support:
   // If any entry of this constantPoolCache points to any of
--- a/hotspot/src/share/vm/oops/generateOopMap.cpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/share/vm/oops/generateOopMap.cpp	Wed Jul 05 17:04:56 2017 +0200
@@ -1556,13 +1556,13 @@
     case Bytecodes::_getfield:          do_field(true,  false, itr->get_index_big(), itr->bci()); break;
     case Bytecodes::_putfield:          do_field(false, false, itr->get_index_big(), itr->bci()); break;
 
-    case Bytecodes::_invokevirtual:
-    case Bytecodes::_invokespecial:     do_method(false, false, itr->get_index_big(), itr->bci()); break;
-    case Bytecodes::_invokestatic:      do_method(true,  false, itr->get_index_big(), itr->bci()); break;
-    case Bytecodes::_invokedynamic:     do_method(false, true,  itr->get_index_int(), itr->bci()); break;
-    case Bytecodes::_invokeinterface:   do_method(false, true,  itr->get_index_big(), itr->bci()); break;
-    case Bytecodes::_newarray:
-    case Bytecodes::_anewarray:         pp_new_ref(vCTS, itr->bci()); break;
+   case Bytecodes::_invokevirtual:
+   case Bytecodes::_invokespecial:     do_method(false, false, itr->get_index_big(), itr->bci()); break;
+   case Bytecodes::_invokestatic:      do_method(true,  false, itr->get_index_big(), itr->bci()); break;
+    case Bytecodes::_invokedynamic:     do_method(true,  false, itr->get_index_int(), itr->bci()); break;
+   case Bytecodes::_invokeinterface:   do_method(false, true,  itr->get_index_big(), itr->bci()); break;
+   case Bytecodes::_newarray:
+   case Bytecodes::_anewarray:         pp_new_ref(vCTS, itr->bci()); break;
     case Bytecodes::_checkcast:         do_checkcast(); break;
     case Bytecodes::_arraylength:
     case Bytecodes::_instanceof:        pp(rCTS, vCTS); break;
@@ -1900,11 +1900,9 @@
 }
 
 void GenerateOopMap::do_method(int is_static, int is_interface, int idx, int bci) {
-  // Dig up signature for field in constant pool
-  constantPoolOop cp    = _method->constants();
-  int nameAndTypeIdx    = cp->name_and_type_ref_index_at(idx);
-  int signatureIdx      = cp->signature_ref_index_at(nameAndTypeIdx);  // @@@@@
-  symbolOop signature   = cp->symbol_at(signatureIdx);
+ // Dig up signature for field in constant pool
+  constantPoolOop cp  = _method->constants();
+  symbolOop signature = cp->signature_ref_at(idx);
 
   // Parse method signature
   CellTypeState out[4];
--- a/hotspot/src/share/vm/oops/instanceKlass.cpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/share/vm/oops/instanceKlass.cpp	Wed Jul 05 17:04:56 2017 +0200
@@ -2045,8 +2045,9 @@
     // As we walk along, look for equalities between outer1 and class2.
     // Eventually, the walks will terminate as outer1 stops
     // at the top-level class around the original class.
-    symbolOop ignore_name;
-    klassOop next = outer1->compute_enclosing_class(ignore_name, CHECK_false);
+    bool ignore_inner_is_member;
+    klassOop next = outer1->compute_enclosing_class(&ignore_inner_is_member,
+                                                    CHECK_false);
     if (next == NULL)  break;
     if (next == class2())  return true;
     outer1 = instanceKlassHandle(THREAD, next);
@@ -2055,8 +2056,9 @@
   // Now do the same for class2.
   instanceKlassHandle outer2 = class2;
   for (;;) {
-    symbolOop ignore_name;
-    klassOop next = outer2->compute_enclosing_class(ignore_name, CHECK_false);
+    bool ignore_inner_is_member;
+    klassOop next = outer2->compute_enclosing_class(&ignore_inner_is_member,
+                                                    CHECK_false);
     if (next == NULL)  break;
     // Might as well check the new outer against all available values.
     if (next == class1())  return true;
--- a/hotspot/src/share/vm/oops/instanceKlass.hpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/share/vm/oops/instanceKlass.hpp	Wed Jul 05 17:04:56 2017 +0200
@@ -337,12 +337,12 @@
   static bool is_same_class_package(oop class_loader1, symbolOop class_name1, oop class_loader2, symbolOop class_name2);
 
   // find an enclosing class (defined where original code was, in jvm.cpp!)
-  klassOop compute_enclosing_class(symbolOop& simple_name_result, TRAPS) {
+  klassOop compute_enclosing_class(bool* inner_is_member, TRAPS) {
     instanceKlassHandle self(THREAD, this->as_klassOop());
-    return compute_enclosing_class_impl(self, simple_name_result, THREAD);
+    return compute_enclosing_class_impl(self, inner_is_member, THREAD);
   }
   static klassOop compute_enclosing_class_impl(instanceKlassHandle self,
-                                               symbolOop& simple_name_result, TRAPS);
+                                               bool* inner_is_member, TRAPS);
 
   // tell if two classes have the same enclosing class (at package level)
   bool is_same_package_member(klassOop class2, TRAPS) {
--- a/hotspot/src/share/vm/oops/instanceKlassKlass.cpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/share/vm/oops/instanceKlassKlass.cpp	Wed Jul 05 17:04:56 2017 +0200
@@ -317,6 +317,11 @@
     pm->claim_or_forward_breadth(sg_addr);
   }
 
+  oop* bsm_addr = ik->adr_bootstrap_method();
+  if (PSScavenge::should_scavenge(bsm_addr)) {
+    pm->claim_or_forward_breadth(bsm_addr);
+  }
+
   klassKlass::oop_copy_contents(pm, obj);
 }
 
@@ -345,6 +350,11 @@
     pm->claim_or_forward_depth(sg_addr);
   }
 
+  oop* bsm_addr = ik->adr_bootstrap_method();
+  if (PSScavenge::should_scavenge(bsm_addr)) {
+    pm->claim_or_forward_depth(bsm_addr);
+  }
+
   klassKlass::oop_copy_contents(pm, obj);
 }
 
--- a/hotspot/src/share/vm/oops/instanceRefKlass.cpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/share/vm/oops/instanceRefKlass.cpp	Wed Jul 05 17:04:56 2017 +0200
@@ -78,9 +78,9 @@
 
 #ifndef SERIALGC
 template <class T>
-static void specialized_oop_follow_contents(instanceRefKlass* ref,
-                                            ParCompactionManager* cm,
-                                            oop obj) {
+void specialized_oop_follow_contents(instanceRefKlass* ref,
+                                     ParCompactionManager* cm,
+                                     oop obj) {
   T* referent_addr = (T*)java_lang_ref_Reference::referent_addr(obj);
   T heap_oop = oopDesc::load_heap_oop(referent_addr);
   debug_only(
--- a/hotspot/src/share/vm/oops/objArrayKlass.cpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/share/vm/oops/objArrayKlass.cpp	Wed Jul 05 17:04:56 2017 +0200
@@ -127,16 +127,14 @@
           // pointer delta is scaled to number of elements (length field in
           // objArrayOop) which we assume is 32 bit.
           assert(pd == (size_t)(int)pd, "length field overflow");
-          const size_t done_word_len = objArrayOopDesc::array_size((int)pd);
-          bs->write_ref_array(MemRegion((HeapWord*)dst, done_word_len));
+          bs->write_ref_array((HeapWord*)dst, pd);
           THROW(vmSymbols::java_lang_ArrayStoreException());
           return;
         }
       }
     }
   }
-  const size_t word_len = objArrayOopDesc::array_size(length);
-  bs->write_ref_array(MemRegion((HeapWord*)dst, word_len));
+  bs->write_ref_array((HeapWord*)dst, length);
 }
 
 void objArrayKlass::copy_array(arrayOop s, int src_pos, arrayOop d,
--- a/hotspot/src/share/vm/oops/objArrayOop.hpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/share/vm/oops/objArrayOop.hpp	Wed Jul 05 17:04:56 2017 +0200
@@ -37,6 +37,32 @@
     return &((T*)base())[index];
   }
 
+private:
+  // Give size of objArrayOop in HeapWords minus the header
+  static int array_size(int length) {
+    const int OopsPerHeapWord = HeapWordSize/heapOopSize;
+    assert(OopsPerHeapWord >= 1 && (HeapWordSize % heapOopSize == 0),
+           "Else the following (new) computation would be in error");
+#ifdef ASSERT
+    // The old code is left in for sanity-checking; it'll
+    // go away pretty soon. XXX
+    // Without UseCompressedOops, this is simply:
+    // oop->length() * HeapWordsPerOop;
+    // With narrowOops, HeapWordsPerOop is 1/2 or equal 0 as an integer.
+    // The oop elements are aligned up to wordSize
+    const int HeapWordsPerOop = heapOopSize/HeapWordSize;
+    int old_res;
+    if (HeapWordsPerOop > 0) {
+      old_res = length * HeapWordsPerOop;
+    } else {
+      old_res = align_size_up(length, OopsPerHeapWord)/OopsPerHeapWord;
+    }
+#endif  // ASSERT
+    int res = ((uint)length + OopsPerHeapWord - 1)/OopsPerHeapWord;
+    assert(res == old_res, "Inconsistency between old and new.");
+    return res;
+  }
+
  public:
   // Returns the offset of the first element.
   static int base_offset_in_bytes() {
@@ -67,27 +93,14 @@
   // Sizing
   static int header_size()    { return arrayOopDesc::header_size(T_OBJECT); }
   int object_size()           { return object_size(length()); }
-  int array_size()            { return array_size(length()); }
 
   static int object_size(int length) {
     // This returns the object size in HeapWords.
-    return align_object_size(header_size() + array_size(length));
-  }
-
-  // Give size of objArrayOop in HeapWords minus the header
-  static int array_size(int length) {
-    // Without UseCompressedOops, this is simply:
-    // oop->length() * HeapWordsPerOop;
-    // With narrowOops, HeapWordsPerOop is 1/2 or equal 0 as an integer.
-    // The oop elements are aligned up to wordSize
-    const int HeapWordsPerOop = heapOopSize/HeapWordSize;
-    if (HeapWordsPerOop > 0) {
-      return length * HeapWordsPerOop;
-    } else {
-      const int OopsPerHeapWord = HeapWordSize/heapOopSize;
-      int word_len = align_size_up(length, OopsPerHeapWord)/OopsPerHeapWord;
-      return word_len;
-    }
+    uint asz = array_size(length);
+    uint osz = align_object_size(header_size() + asz);
+    assert(osz >= asz,   "no overflow");
+    assert((int)osz > 0, "no overflow");
+    return (int)osz;
   }
 
   // special iterators for index ranges, returns size of object
--- a/hotspot/src/share/vm/oops/oop.hpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/share/vm/oops/oop.hpp	Wed Jul 05 17:04:56 2017 +0200
@@ -30,13 +30,12 @@
 // no virtual functions allowed
 
 // store into oop with store check
-template <class T> void oop_store(T* p, oop v);
-template <class T> void oop_store(volatile T* p, oop v);
+template <class T> inline void oop_store(T* p, oop v);
+template <class T> inline void oop_store(volatile T* p, oop v);
 
 // store into oop without store check
-template <class T> void oop_store_without_check(T* p, oop v);
-template <class T> void oop_store_without_check(volatile T* p, oop v);
-
+template <class T> inline void oop_store_without_check(T* p, oop v);
+template <class T> inline void oop_store_without_check(volatile T* p, oop v);
 
 extern bool always_do_update_barrier;
 
--- a/hotspot/src/share/vm/opto/c2_globals.cpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/share/vm/opto/c2_globals.cpp	Wed Jul 05 17:04:56 2017 +0200
@@ -25,4 +25,4 @@
 # include "incls/_precompiled.incl"
 # include "incls/_c2_globals.cpp.incl"
 
-C2_FLAGS(MATERIALIZE_DEVELOPER_FLAG, MATERIALIZE_PD_DEVELOPER_FLAG, MATERIALIZE_PRODUCT_FLAG, MATERIALIZE_PD_PRODUCT_FLAG, MATERIALIZE_DIAGNOSTIC_FLAG, MATERIALIZE_NOTPRODUCT_FLAG)
+C2_FLAGS(MATERIALIZE_DEVELOPER_FLAG, MATERIALIZE_PD_DEVELOPER_FLAG, MATERIALIZE_PRODUCT_FLAG, MATERIALIZE_PD_PRODUCT_FLAG, MATERIALIZE_DIAGNOSTIC_FLAG, MATERIALIZE_EXPERIMENTAL_FLAG, MATERIALIZE_NOTPRODUCT_FLAG)
--- a/hotspot/src/share/vm/opto/c2_globals.hpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/share/vm/opto/c2_globals.hpp	Wed Jul 05 17:04:56 2017 +0200
@@ -26,7 +26,7 @@
 // Defines all globals flags used by the server compiler.
 //
 
-#define C2_FLAGS(develop, develop_pd, product, product_pd, diagnostic, notproduct) \
+#define C2_FLAGS(develop, develop_pd, product, product_pd, diagnostic, experimental, notproduct) \
                                                                             \
   notproduct(intx, CompileZapFirst, 0,                                      \
           "If +ZapDeadCompiledLocals, "                                     \
@@ -394,6 +394,12 @@
   product(bool, UseOptoBiasInlining, true,                                  \
           "Generate biased locking code in C2 ideal graph")                 \
                                                                             \
+  product(bool, OptimizeStringConcat, false,                                \
+          "Optimize the construction of Strings by StringBuilder")          \
+                                                                            \
+  notproduct(bool, PrintOptimizeStringConcat, false,                        \
+          "Print information about transformations performed on Strings")   \
+                                                                            \
   product(intx, ValueSearchLimit, 1000,                                     \
           "Recursion limit in PhaseMacroExpand::value_from_mem_phi")        \
                                                                             \
@@ -413,4 +419,4 @@
   product(bool, BlockLayoutRotateLoops, true,                               \
           "Allow back branches to be fall throughs in the block layour")    \
 
-C2_FLAGS(DECLARE_DEVELOPER_FLAG, DECLARE_PD_DEVELOPER_FLAG, DECLARE_PRODUCT_FLAG, DECLARE_PD_PRODUCT_FLAG, DECLARE_DIAGNOSTIC_FLAG, DECLARE_NOTPRODUCT_FLAG)
+C2_FLAGS(DECLARE_DEVELOPER_FLAG, DECLARE_PD_DEVELOPER_FLAG, DECLARE_PRODUCT_FLAG, DECLARE_PD_PRODUCT_FLAG, DECLARE_DIAGNOSTIC_FLAG, DECLARE_EXPERIMENTAL_FLAG, DECLARE_NOTPRODUCT_FLAG)
--- a/hotspot/src/share/vm/opto/callGenerator.cpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/share/vm/opto/callGenerator.cpp	Wed Jul 05 17:04:56 2017 +0200
@@ -98,12 +98,21 @@
 //---------------------------DirectCallGenerator------------------------------
 // Internal class which handles all out-of-line calls w/o receiver type checks.
 class DirectCallGenerator : public CallGenerator {
-public:
-  DirectCallGenerator(ciMethod* method)
-    : CallGenerator(method)
+ private:
+  CallStaticJavaNode* _call_node;
+  // Force separate memory and I/O projections for the exceptional
+  // paths to facilitate late inlinig.
+  bool                _separate_io_proj;
+
+ public:
+  DirectCallGenerator(ciMethod* method, bool separate_io_proj)
+    : CallGenerator(method),
+      _separate_io_proj(separate_io_proj)
   {
   }
   virtual JVMState* generate(JVMState* jvms);
+
+  CallStaticJavaNode* call_node() const { return _call_node; }
 };
 
 JVMState* DirectCallGenerator::generate(JVMState* jvms) {
@@ -129,9 +138,10 @@
     call->set_optimized_virtual(true);
   }
   kit.set_arguments_for_java_call(call);
-  kit.set_edges_for_java_call(call);
-  Node* ret = kit.set_results_for_java_call(call);
+  kit.set_edges_for_java_call(call, false, _separate_io_proj);
+  Node* ret = kit.set_results_for_java_call(call, _separate_io_proj);
   kit.push_node(method()->return_type()->basic_type(), ret);
+  _call_node = call;  // Save the call node in case we need it later
   return kit.transfer_exceptions_into_jvms();
 }
 
@@ -238,9 +248,9 @@
   return new ParseGenerator(m, expected_uses, true);
 }
 
-CallGenerator* CallGenerator::for_direct_call(ciMethod* m) {
+CallGenerator* CallGenerator::for_direct_call(ciMethod* m, bool separate_io_proj) {
   assert(!m->is_abstract(), "for_direct_call mismatch");
-  return new DirectCallGenerator(m);
+  return new DirectCallGenerator(m, separate_io_proj);
 }
 
 CallGenerator* CallGenerator::for_virtual_call(ciMethod* m, int vtable_index) {
@@ -248,6 +258,108 @@
   return new VirtualCallGenerator(m, vtable_index);
 }
 
+// Allow inlining decisions to be delayed
+class LateInlineCallGenerator : public DirectCallGenerator {
+  CallGenerator* _inline_cg;
+
+ public:
+  LateInlineCallGenerator(ciMethod* method, CallGenerator* inline_cg) :
+    DirectCallGenerator(method, true), _inline_cg(inline_cg) {}
+
+  virtual bool      is_late_inline() const { return true; }
+
+  // Convert the CallStaticJava into an inline
+  virtual void do_late_inline();
+
+  JVMState* generate(JVMState* jvms) {
+    // Record that this call site should be revisited once the main
+    // parse is finished.
+    Compile::current()->add_late_inline(this);
+
+    // Emit the CallStaticJava and request separate projections so
+    // that the late inlining logic can distinguish between fall
+    // through and exceptional uses of the memory and io projections
+    // as is done for allocations and macro expansion.
+    return DirectCallGenerator::generate(jvms);
+  }
+
+};
+
+
+void LateInlineCallGenerator::do_late_inline() {
+  // Can't inline it
+  if (call_node() == NULL || call_node()->outcnt() == 0 ||
+      call_node()->in(0) == NULL || call_node()->in(0)->is_top())
+    return;
+
+  CallStaticJavaNode* call = call_node();
+
+  // Make a clone of the JVMState that appropriate to use for driving a parse
+  Compile* C = Compile::current();
+  JVMState* jvms     = call->jvms()->clone_shallow(C);
+  uint size = call->req();
+  SafePointNode* map = new (C, size) SafePointNode(size, jvms);
+  for (uint i1 = 0; i1 < size; i1++) {
+    map->init_req(i1, call->in(i1));
+  }
+
+  // Make sure the state is a MergeMem for parsing.
+  if (!map->in(TypeFunc::Memory)->is_MergeMem()) {
+    map->set_req(TypeFunc::Memory, MergeMemNode::make(C, map->in(TypeFunc::Memory)));
+  }
+
+  // Make enough space for the expression stack and transfer the incoming arguments
+  int nargs    = method()->arg_size();
+  jvms->set_map(map);
+  map->ensure_stack(jvms, jvms->method()->max_stack());
+  if (nargs > 0) {
+    for (int i1 = 0; i1 < nargs; i1++) {
+      map->set_req(i1 + jvms->argoff(), call->in(TypeFunc::Parms + i1));
+    }
+  }
+
+  CompileLog* log = C->log();
+  if (log != NULL) {
+    log->head("late_inline method='%d'", log->identify(method()));
+    JVMState* p = jvms;
+    while (p != NULL) {
+      log->elem("jvms bci='%d' method='%d'", p->bci(), log->identify(p->method()));
+      p = p->caller();
+    }
+    log->tail("late_inline");
+  }
+
+  // Setup default node notes to be picked up by the inlining
+  Node_Notes* old_nn = C->default_node_notes();
+  if (old_nn != NULL) {
+    Node_Notes* entry_nn = old_nn->clone(C);
+    entry_nn->set_jvms(jvms);
+    C->set_default_node_notes(entry_nn);
+  }
+
+  // Now perform the inling using the synthesized JVMState
+  JVMState* new_jvms = _inline_cg->generate(jvms);
+  if (new_jvms == NULL)  return;  // no change
+  if (C->failing())      return;
+
+  // Capture any exceptional control flow
+  GraphKit kit(new_jvms);
+
+  // Find the result object
+  Node* result = C->top();
+  int   result_size = method()->return_type()->size();
+  if (result_size != 0 && !kit.stopped()) {
+    result = (result_size == 1) ? kit.pop() : kit.pop_pair();
+  }
+
+  kit.replace_call(call, result);
+}
+
+
+CallGenerator* CallGenerator::for_late_inline(ciMethod* method, CallGenerator* inline_cg) {
+  return new LateInlineCallGenerator(method, inline_cg);
+}
+
 
 //---------------------------WarmCallGenerator--------------------------------
 // Internal class which handles initial deferral of inlining decisions.
@@ -315,70 +427,7 @@
 }
 
 void WarmCallInfo::make_hot() {
-  Compile* C = Compile::current();
-  // Replace the callnode with something better.
-  CallJavaNode* call = this->call()->as_CallJava();
-  ciMethod* method   = call->method();
-  int       nargs    = method->arg_size();
-  JVMState* jvms     = call->jvms()->clone_shallow(C);
-  uint size = TypeFunc::Parms + MAX2(2, nargs);
-  SafePointNode* map = new (C, size) SafePointNode(size, jvms);
-  for (uint i1 = 0; i1 < (uint)(TypeFunc::Parms + nargs); i1++) {
-    map->init_req(i1, call->in(i1));
-  }
-  jvms->set_map(map);
-  jvms->set_offsets(map->req());
-  jvms->set_locoff(TypeFunc::Parms);
-  jvms->set_stkoff(TypeFunc::Parms);
-  GraphKit kit(jvms);
-
-  JVMState* new_jvms = _hot_cg->generate(kit.jvms());
-  if (new_jvms == NULL)  return;  // no change
-  if (C->failing())      return;
-
-  kit.set_jvms(new_jvms);
-  Node* res = C->top();
-  int   res_size = method->return_type()->size();
-  if (res_size != 0) {
-    kit.inc_sp(-res_size);
-    res = kit.argument(0);
-  }
-  GraphKit ekit(kit.combine_and_pop_all_exception_states()->jvms());
-
-  // Replace the call:
-  for (DUIterator i = call->outs(); call->has_out(i); i++) {
-    Node* n = call->out(i);
-    Node* nn = NULL;  // replacement
-    if (n->is_Proj()) {
-      ProjNode* nproj = n->as_Proj();
-      assert(nproj->_con < (uint)(TypeFunc::Parms + (res_size ? 1 : 0)), "sane proj");
-      if (nproj->_con == TypeFunc::Parms) {
-        nn = res;
-      } else {
-        nn = kit.map()->in(nproj->_con);
-      }
-      if (nproj->_con == TypeFunc::I_O) {
-        for (DUIterator j = nproj->outs(); nproj->has_out(j); j++) {
-          Node* e = nproj->out(j);
-          if (e->Opcode() == Op_CreateEx) {
-            e->replace_by(ekit.argument(0));
-          } else if (e->Opcode() == Op_Catch) {
-            for (DUIterator k = e->outs(); e->has_out(k); k++) {
-              CatchProjNode* p = e->out(j)->as_CatchProj();
-              if (p->is_handler_proj()) {
-                p->replace_by(ekit.control());
-              } else {
-                p->replace_by(kit.control());
-              }
-            }
-          }
-        }
-      }
-    }
-    NOT_PRODUCT(if (!nn)  n->dump(2));
-    assert(nn != NULL, "don't know what to do with this user");
-    n->replace_by(nn);
-  }
+  Unimplemented();
 }
 
 void WarmCallInfo::make_cold() {
--- a/hotspot/src/share/vm/opto/callGenerator.hpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/share/vm/opto/callGenerator.hpp	Wed Jul 05 17:04:56 2017 +0200
@@ -57,6 +57,13 @@
   // is_trap: Does not return to the caller.  (E.g., uncommon trap.)
   virtual bool      is_trap() const             { return false; }
 
+  // is_late_inline: supports conversion of call into an inline
+  virtual bool      is_late_inline() const      { return false; }
+  // Replace the call with an inline version of the code
+  virtual void do_late_inline() { ShouldNotReachHere(); }
+
+  virtual CallStaticJavaNode* call_node() const { ShouldNotReachHere(); return NULL; }
+
   // Note:  It is possible for a CG to be both inline and virtual.
   // (The hashCode intrinsic does a vtable check and an inlined fast path.)
 
@@ -92,9 +99,12 @@
   static CallGenerator* for_osr(ciMethod* m, int osr_bci);
 
   // How to generate vanilla out-of-line call sites:
-  static CallGenerator* for_direct_call(ciMethod* m);   // static, special
+  static CallGenerator* for_direct_call(ciMethod* m, bool separate_io_projs = false);   // static, special
   static CallGenerator* for_virtual_call(ciMethod* m, int vtable_index);  // virtual, interface
 
+  // How to generate a replace a direct call with an inline version
+  static CallGenerator* for_late_inline(ciMethod* m, CallGenerator* inline_cg);
+
   // How to make a call but defer the decision whether to inline or not.
   static CallGenerator* for_warm_call(WarmCallInfo* ci,
                                       CallGenerator* if_cold,
--- a/hotspot/src/share/vm/opto/callnode.cpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/share/vm/opto/callnode.cpp	Wed Jul 05 17:04:56 2017 +0200
@@ -693,6 +693,84 @@
 }
 
 
+void CallNode::extract_projections(CallProjections* projs, bool separate_io_proj) {
+  projs->fallthrough_proj      = NULL;
+  projs->fallthrough_catchproj = NULL;
+  projs->fallthrough_ioproj    = NULL;
+  projs->catchall_ioproj       = NULL;
+  projs->catchall_catchproj    = NULL;
+  projs->fallthrough_memproj   = NULL;
+  projs->catchall_memproj      = NULL;
+  projs->resproj               = NULL;
+  projs->exobj                 = NULL;
+
+  for (DUIterator_Fast imax, i = fast_outs(imax); i < imax; i++) {
+    ProjNode *pn = fast_out(i)->as_Proj();
+    if (pn->outcnt() == 0) continue;
+    switch (pn->_con) {
+    case TypeFunc::Control:
+      {
+        // For Control (fallthrough) and I_O (catch_all_index) we have CatchProj -> Catch -> Proj
+        projs->fallthrough_proj = pn;
+        DUIterator_Fast jmax, j = pn->fast_outs(jmax);
+        const Node *cn = pn->fast_out(j);
+        if (cn->is_Catch()) {
+          ProjNode *cpn = NULL;
+          for (DUIterator_Fast kmax, k = cn->fast_outs(kmax); k < kmax; k++) {
+            cpn = cn->fast_out(k)->as_Proj();
+            assert(cpn->is_CatchProj(), "must be a CatchProjNode");
+            if (cpn->_con == CatchProjNode::fall_through_index)
+              projs->fallthrough_catchproj = cpn;
+            else {
+              assert(cpn->_con == CatchProjNode::catch_all_index, "must be correct index.");
+              projs->catchall_catchproj = cpn;
+            }
+          }
+        }
+        break;
+      }
+    case TypeFunc::I_O:
+      if (pn->_is_io_use)
+        projs->catchall_ioproj = pn;
+      else
+        projs->fallthrough_ioproj = pn;
+      for (DUIterator j = pn->outs(); pn->has_out(j); j++) {
+        Node* e = pn->out(j);
+        if (e->Opcode() == Op_CreateEx && e->in(0)->is_CatchProj()) {
+          assert(projs->exobj == NULL, "only one");
+          projs->exobj = e;
+        }
+      }
+      break;
+    case TypeFunc::Memory:
+      if (pn->_is_io_use)
+        projs->catchall_memproj = pn;
+      else
+        projs->fallthrough_memproj = pn;
+      break;
+    case TypeFunc::Parms:
+      projs->resproj = pn;
+      break;
+    default:
+      assert(false, "unexpected projection from allocation node.");
+    }
+  }
+
+  // The resproj may not exist because the result couuld be ignored
+  // and the exception object may not exist if an exception handler
+  // swallows the exception but all the other must exist and be found.
+  assert(projs->fallthrough_proj      != NULL, "must be found");
+  assert(projs->fallthrough_catchproj != NULL, "must be found");
+  assert(projs->fallthrough_memproj   != NULL, "must be found");
+  assert(projs->fallthrough_ioproj    != NULL, "must be found");
+  assert(projs->catchall_catchproj    != NULL, "must be found");
+  if (separate_io_proj) {
+    assert(projs->catchall_memproj      != NULL, "must be found");
+    assert(projs->catchall_ioproj       != NULL, "must be found");
+  }
+}
+
+
 //=============================================================================
 uint CallJavaNode::size_of() const { return sizeof(*this); }
 uint CallJavaNode::cmp( const Node &n ) const {
--- a/hotspot/src/share/vm/opto/callnode.hpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/share/vm/opto/callnode.hpp	Wed Jul 05 17:04:56 2017 +0200
@@ -470,6 +470,23 @@
 #endif
 };
 
+
+// Simple container for the outgoing projections of a call.  Useful
+// for serious surgery on calls.
+class CallProjections : public StackObj {
+public:
+  Node* fallthrough_proj;
+  Node* fallthrough_catchproj;
+  Node* fallthrough_memproj;
+  Node* fallthrough_ioproj;
+  Node* catchall_catchproj;
+  Node* catchall_memproj;
+  Node* catchall_ioproj;
+  Node* resproj;
+  Node* exobj;
+};
+
+
 //------------------------------CallNode---------------------------------------
 // Call nodes now subsume the function of debug nodes at callsites, so they
 // contain the functionality of a full scope chain of debug nodes.
@@ -521,6 +538,11 @@
   // or returns NULL if there is no one.
   Node *result_cast();
 
+  // Collect all the interesting edges from a call for use in
+  // replacing the call by something else.  Used by macro expansion
+  // and the late inlining support.
+  void extract_projections(CallProjections* projs, bool separate_io_proj);
+
   virtual uint match_edge(uint idx) const;
 
 #ifndef PRODUCT
@@ -529,6 +551,7 @@
 #endif
 };
 
+
 //------------------------------CallJavaNode-----------------------------------
 // Make a static or dynamic subroutine call node using Java calling
 // convention.  (The "Java" calling convention is the compiler's calling
--- a/hotspot/src/share/vm/opto/compile.cpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/share/vm/opto/compile.cpp	Wed Jul 05 17:04:56 2017 +0200
@@ -224,6 +224,32 @@
 }
 
 
+void Compile::gvn_replace_by(Node* n, Node* nn) {
+  for (DUIterator_Last imin, i = n->last_outs(imin); i >= imin; ) {
+    Node* use = n->last_out(i);
+    bool is_in_table = initial_gvn()->hash_delete(use);
+    uint uses_found = 0;
+    for (uint j = 0; j < use->len(); j++) {
+      if (use->in(j) == n) {
+        if (j < use->req())
+          use->set_req(j, nn);
+        else
+          use->set_prec(j, nn);
+        uses_found++;
+      }
+    }
+    if (is_in_table) {
+      // reinsert into table
+      initial_gvn()->hash_find_insert(use);
+    }
+    record_for_igvn(use);
+    i -= uses_found;    // we deleted 1 or more copies of this edge
+  }
+}
+
+
+
+
 // Identify all nodes that are reachable from below, useful.
 // Use breadth-first pass that records state in a Unique_Node_List,
 // recursive traversal is slower.
@@ -554,6 +580,28 @@
       rethrow_exceptions(kit.transfer_exceptions_into_jvms());
     }
 
+    if (!failing() && has_stringbuilder()) {
+      {
+        // remove useless nodes to make the usage analysis simpler
+        ResourceMark rm;
+        PhaseRemoveUseless pru(initial_gvn(), &for_igvn);
+      }
+
+      {
+        ResourceMark rm;
+        print_method("Before StringOpts", 3);
+        PhaseStringOpts pso(initial_gvn(), &for_igvn);
+        print_method("After StringOpts", 3);
+      }
+
+      // now inline anything that we skipped the first time around
+      while (_late_inlines.length() > 0) {
+        CallGenerator* cg = _late_inlines.pop();
+        cg->do_late_inline();
+      }
+    }
+    assert(_late_inlines.length() == 0, "should have been processed");
+
     print_method("Before RemoveUseless", 3);
 
     // Remove clutter produced by parsing.
@@ -820,6 +868,7 @@
   _fixed_slots = 0;
   set_has_split_ifs(false);
   set_has_loops(has_method() && method()->has_loops()); // first approximation
+  set_has_stringbuilder(false);
   _deopt_happens = true;  // start out assuming the worst
   _trap_can_recompile = false;  // no traps emitted yet
   _major_progress = true; // start out assuming good things will happen
@@ -1803,6 +1852,7 @@
           !n->is_Phi() &&       // a few noisely useless nodes
           !n->is_Proj() &&
           !n->is_MachTemp() &&
+          !n->is_SafePointScalarObject() &&
           !n->is_Catch() &&     // Would be nice to print exception table targets
           !n->is_MergeMem() &&  // Not very interesting
           !n->is_top() &&       // Debug info table constants
@@ -2240,6 +2290,30 @@
     break;
   }
 
+  case Op_Proj: {
+    if (OptimizeStringConcat) {
+      ProjNode* p = n->as_Proj();
+      if (p->_is_io_use) {
+        // Separate projections were used for the exception path which
+        // are normally removed by a late inline.  If it wasn't inlined
+        // then they will hang around and should just be replaced with
+        // the original one.
+        Node* proj = NULL;
+        // Replace with just one
+        for (SimpleDUIterator i(p->in(0)); i.has_next(); i.next()) {
+          Node *use = i.get();
+          if (use->is_Proj() && p != use && use->as_Proj()->_con == p->_con) {
+            proj = use;
+            break;
+          }
+        }
+        assert(p != NULL, "must be found");
+        p->subsume_by(proj);
+      }
+    }
+    break;
+  }
+
   case Op_Phi:
     if (n->as_Phi()->bottom_type()->isa_narrowoop()) {
       // The EncodeP optimization may create Phi with the same edges
--- a/hotspot/src/share/vm/opto/compile.hpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/share/vm/opto/compile.hpp	Wed Jul 05 17:04:56 2017 +0200
@@ -149,6 +149,7 @@
   bool                  _has_loops;             // True if the method _may_ have some loops
   bool                  _has_split_ifs;         // True if the method _may_ have some split-if
   bool                  _has_unsafe_access;     // True if the method _may_ produce faults in unsafe loads or stores.
+  bool                  _has_stringbuilder;     // True StringBuffers or StringBuilders are allocated
   uint                  _trap_hist[trapHistLength];  // Cumulative traps
   bool                  _trap_can_recompile;    // Have we emitted a recompiling trap?
   uint                  _decompile_count;       // Cumulative decompilation counts.
@@ -219,6 +220,9 @@
   Unique_Node_List*     _for_igvn;              // Initial work-list for next round of Iterative GVN
   WarmCallInfo*         _warm_calls;            // Sorted work-list for heat-based inlining.
 
+  GrowableArray<CallGenerator*> _late_inlines;  // List of CallGenerators to be revisited after
+                                                // main parsing has finished.
+
   // Matching, CFG layout, allocation, code generation
   PhaseCFG*             _cfg;                   // Results of CFG finding
   bool                  _select_24_bit_instr;   // We selected an instruction with a 24-bit result
@@ -298,6 +302,8 @@
   void          set_has_split_ifs(bool z)       { _has_split_ifs = z; }
   bool              has_unsafe_access() const   { return _has_unsafe_access; }
   void          set_has_unsafe_access(bool z)   { _has_unsafe_access = z; }
+  bool              has_stringbuilder() const   { return _has_stringbuilder; }
+  void          set_has_stringbuilder(bool z)   { _has_stringbuilder = z; }
   void          set_trap_count(uint r, uint c)  { assert(r < trapHistLength, "oob");        _trap_hist[r] = c; }
   uint              trap_count(uint r) const    { assert(r < trapHistLength, "oob"); return _trap_hist[r]; }
   bool              trap_can_recompile() const  { return _trap_can_recompile; }
@@ -475,6 +481,7 @@
   // Decide how to build a call.
   // The profile factor is a discount to apply to this site's interp. profile.
   CallGenerator*    call_generator(ciMethod* call_method, int vtable_index, bool call_is_virtual, JVMState* jvms, bool allow_inline, float profile_factor);
+  bool should_delay_inlining(ciMethod* call_method, JVMState* jvms);
 
   // Report if there were too many traps at a current method and bci.
   // Report if a trap was recorded, and/or PerMethodTrapLimit was exceeded.
@@ -495,6 +502,11 @@
   void          set_initial_gvn(PhaseGVN *gvn)           { _initial_gvn = gvn; }
   void          set_for_igvn(Unique_Node_List *for_igvn) { _for_igvn = for_igvn; }
 
+  // Replace n by nn using initial_gvn, calling hash_delete and
+  // record_for_igvn as needed.
+  void gvn_replace_by(Node* n, Node* nn);
+
+
   void              identify_useful_nodes(Unique_Node_List &useful);
   void              remove_useless_nodes  (Unique_Node_List &useful);
 
@@ -502,6 +514,9 @@
   void          set_warm_calls(WarmCallInfo* l) { _warm_calls = l; }
   WarmCallInfo* pop_warm_call();
 
+  // Record this CallGenerator for inlining at the end of parsing.
+  void              add_late_inline(CallGenerator* cg) { _late_inlines.push(cg); }
+
   // Matching, CFG layout, allocation, code generation
   PhaseCFG*         cfg()                       { return _cfg; }
   bool              select_24_bit_instr() const { return _select_24_bit_instr; }
--- a/hotspot/src/share/vm/opto/doCall.cpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/share/vm/opto/doCall.cpp	Wed Jul 05 17:04:56 2017 +0200
@@ -128,6 +128,12 @@
 
       if (allow_inline) {
         CallGenerator* cg = CallGenerator::for_inline(call_method, expected_uses);
+        if (require_inline && cg != NULL && should_delay_inlining(call_method, jvms)) {
+          // Delay the inlining of this method to give us the
+          // opportunity to perform some high level optimizations
+          // first.
+          return CallGenerator::for_late_inline(call_method, cg);
+        }
         if (cg == NULL) {
           // Fall through.
         } else if (require_inline || !InlineWarmCalls) {
@@ -225,10 +231,63 @@
   } else {
     // Class Hierarchy Analysis or Type Profile reveals a unique target,
     // or it is a static or special call.
-    return CallGenerator::for_direct_call(call_method);
+    return CallGenerator::for_direct_call(call_method, should_delay_inlining(call_method, jvms));
   }
 }
 
+// Return true for methods that shouldn't be inlined early so that
+// they are easier to analyze and optimize as intrinsics.
+bool Compile::should_delay_inlining(ciMethod* call_method, JVMState* jvms) {
+  if (has_stringbuilder()) {
+
+    if ((call_method->holder() == C->env()->StringBuilder_klass() ||
+         call_method->holder() == C->env()->StringBuffer_klass()) &&
+        (jvms->method()->holder() == C->env()->StringBuilder_klass() ||
+         jvms->method()->holder() == C->env()->StringBuffer_klass())) {
+      // Delay SB calls only when called from non-SB code
+      return false;
+    }
+
+    switch (call_method->intrinsic_id()) {
+      case vmIntrinsics::_StringBuilder_void:
+      case vmIntrinsics::_StringBuilder_int:
+      case vmIntrinsics::_StringBuilder_String:
+      case vmIntrinsics::_StringBuilder_append_char:
+      case vmIntrinsics::_StringBuilder_append_int:
+      case vmIntrinsics::_StringBuilder_append_String:
+      case vmIntrinsics::_StringBuilder_toString:
+      case vmIntrinsics::_StringBuffer_void:
+      case vmIntrinsics::_StringBuffer_int:
+      case vmIntrinsics::_StringBuffer_String:
+      case vmIntrinsics::_StringBuffer_append_char:
+      case vmIntrinsics::_StringBuffer_append_int:
+      case vmIntrinsics::_StringBuffer_append_String:
+      case vmIntrinsics::_StringBuffer_toString:
+      case vmIntrinsics::_Integer_toString:
+        return true;
+
+      case vmIntrinsics::_String_String:
+        {
+          Node* receiver = jvms->map()->in(jvms->argoff() + 1);
+          if (receiver->is_Proj() && receiver->in(0)->is_CallStaticJava()) {
+            CallStaticJavaNode* csj = receiver->in(0)->as_CallStaticJava();
+            ciMethod* m = csj->method();
+            if (m != NULL &&
+                (m->intrinsic_id() == vmIntrinsics::_StringBuffer_toString ||
+                 m->intrinsic_id() == vmIntrinsics::_StringBuilder_toString))
+              // Delay String.<init>(new SB())
+              return true;
+          }
+          return false;
+        }
+
+      default:
+        return false;
+    }
+  }
+  return false;
+}
+
 
 // uncommon-trap call-sites where callee is unloaded, uninitialized or will not link
 bool Parse::can_not_compile_call_site(ciMethod *dest_method, ciInstanceKlass* klass) {
--- a/hotspot/src/share/vm/opto/escape.cpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/share/vm/opto/escape.cpp	Wed Jul 05 17:04:56 2017 +0200
@@ -537,11 +537,13 @@
   }
 
   const TypeOopPtr *tinst = base_t->add_offset(t->offset())->is_oopptr();
-  // Do NOT remove the next call: ensure an new alias index is allocated
-  // for the instance type
+  // Do NOT remove the next line: ensure a new alias index is allocated
+  // for the instance type. Note: C++ will not remove it since the call
+  // has side effect.
   int alias_idx = _compile->get_alias_index(tinst);
   igvn->set_type(addp, tinst);
   // record the allocation in the node map
+  assert(ptnode_adr(addp->_idx)->_node != NULL, "should be registered");
   set_map(addp->_idx, get_map(base->_idx));
 
   // Set addp's Base and Address to 'base'.
@@ -617,9 +619,14 @@
   const TypePtr *atype = C->get_adr_type(alias_idx);
   result = PhiNode::make(orig_phi->in(0), NULL, Type::MEMORY, atype);
   C->copy_node_notes_to(result, orig_phi);
-  set_map_phi(orig_phi->_idx, result);
   igvn->set_type(result, result->bottom_type());
   record_for_optimizer(result);
+
+  debug_only(Node* pn = ptnode_adr(orig_phi->_idx)->_node;)
+  assert(pn == NULL || pn == orig_phi, "wrong node");
+  set_map(orig_phi->_idx, result);
+  ptnode_adr(orig_phi->_idx)->_node = orig_phi;
+
   new_created = true;
   return result;
 }
@@ -710,6 +717,81 @@
 }
 
 //
+// Move memory users to their memory slices.
+//
+void ConnectionGraph::move_inst_mem(Node* n, GrowableArray<PhiNode *>  &orig_phis, PhaseGVN *igvn) {
+  Compile* C = _compile;
+
+  const TypePtr* tp = igvn->type(n->in(MemNode::Address))->isa_ptr();
+  assert(tp != NULL, "ptr type");
+  int alias_idx = C->get_alias_index(tp);
+  int general_idx = C->get_general_index(alias_idx);
+
+  // Move users first
+  for (DUIterator_Fast imax, i = n->fast_outs(imax); i < imax; i++) {
+    Node* use = n->fast_out(i);
+    if (use->is_MergeMem()) {
+      MergeMemNode* mmem = use->as_MergeMem();
+      assert(n == mmem->memory_at(alias_idx), "should be on instance memory slice");
+      if (n != mmem->memory_at(general_idx) || alias_idx == general_idx) {
+        continue; // Nothing to do
+      }
+      // Replace previous general reference to mem node.
+      uint orig_uniq = C->unique();
+      Node* m = find_inst_mem(n, general_idx, orig_phis, igvn);
+      assert(orig_uniq == C->unique(), "no new nodes");
+      mmem->set_memory_at(general_idx, m);
+      --imax;
+      --i;
+    } else if (use->is_MemBar()) {
+      assert(!use->is_Initialize(), "initializing stores should not be moved");
+      if (use->req() > MemBarNode::Precedent &&
+          use->in(MemBarNode::Precedent) == n) {
+        // Don't move related membars.
+        record_for_optimizer(use);
+        continue;
+      }
+      tp = use->as_MemBar()->adr_type()->isa_ptr();
+      if (tp != NULL && C->get_alias_index(tp) == alias_idx ||
+          alias_idx == general_idx) {
+        continue; // Nothing to do
+      }
+      // Move to general memory slice.
+      uint orig_uniq = C->unique();
+      Node* m = find_inst_mem(n, general_idx, orig_phis, igvn);
+      assert(orig_uniq == C->unique(), "no new nodes");
+      igvn->hash_delete(use);
+      imax -= use->replace_edge(n, m);
+      igvn->hash_insert(use);
+      record_for_optimizer(use);
+      --i;
+#ifdef ASSERT
+    } else if (use->is_Mem()) {
+      if (use->Opcode() == Op_StoreCM && use->in(MemNode::OopStore) == n) {
+        // Don't move related cardmark.
+        continue;
+      }
+      // Memory nodes should have new memory input.
+      tp = igvn->type(use->in(MemNode::Address))->isa_ptr();
+      assert(tp != NULL, "ptr type");
+      int idx = C->get_alias_index(tp);
+      assert(get_map(use->_idx) != NULL || idx == alias_idx,
+             "Following memory nodes should have new memory input or be on the same memory slice");
+    } else if (use->is_Phi()) {
+      // Phi nodes should be split and moved already.
+      tp = use->as_Phi()->adr_type()->isa_ptr();
+      assert(tp != NULL, "ptr type");
+      int idx = C->get_alias_index(tp);
+      assert(idx == alias_idx, "Following Phi nodes should be on the same memory slice");
+    } else {
+      use->dump();
+      assert(false, "should not be here");
+#endif
+    }
+  }
+}
+
+//
 // Search memory chain of "mem" to find a MemNode whose address
 // is the specified alias index.
 //
@@ -774,10 +856,18 @@
                C->get_alias_index(result->as_Phi()->adr_type()) != alias_idx) {
       Node *un = result->as_Phi()->unique_input(phase);
       if (un != NULL) {
+        orig_phis.append_if_missing(result->as_Phi());
         result = un;
       } else {
         break;
       }
+    } else if (result->is_ClearArray()) {
+      if (!ClearArrayNode::step_through(&result, (uint)tinst->instance_id(), phase)) {
+        // Can not bypass initialization of the instance
+        // we are looking for.
+        break;
+      }
+      // Otherwise skip it (the call updated 'result' value).
     } else if (result->Opcode() == Op_SCMemProj) {
       assert(result->in(0)->is_LoadStore(), "sanity");
       const Type *at = phase->type(result->in(0)->in(MemNode::Address));
@@ -807,7 +897,6 @@
   return result;
 }
 
-
 //
 //  Convert the types of unescaped object to instance types where possible,
 //  propagate the new type information through the graph, and update memory
@@ -899,12 +988,13 @@
 //
 void ConnectionGraph::split_unique_types(GrowableArray<Node *>  &alloc_worklist) {
   GrowableArray<Node *>  memnode_worklist;
-  GrowableArray<Node *>  mergemem_worklist;
   GrowableArray<PhiNode *>  orig_phis;
+
   PhaseGVN  *igvn = _compile->initial_gvn();
   uint new_index_start = (uint) _compile->num_alias_types();
-  VectorSet visited(Thread::current()->resource_area());
-  VectorSet ptset(Thread::current()->resource_area());
+  Arena* arena = Thread::current()->resource_area();
+  VectorSet visited(arena);
+  VectorSet ptset(arena);
 
 
   //  Phase 1:  Process possible allocations from alloc_worklist.
@@ -980,6 +1070,8 @@
       //   - non-escaping
       //   - eligible to be a unique type
       //   - not determined to be ineligible by escape analysis
+      assert(ptnode_adr(alloc->_idx)->_node != NULL &&
+             ptnode_adr(n->_idx)->_node != NULL, "should be registered");
       set_map(alloc->_idx, n);
       set_map(n->_idx, alloc);
       const TypeOopPtr *t = igvn->type(n)->isa_oopptr();
@@ -1024,7 +1116,7 @@
               alloc_worklist.append_if_missing(addp2);
             }
             alloc_worklist.append_if_missing(use);
-          } else if (use->is_Initialize()) {
+          } else if (use->is_MemBar()) {
             memnode_worklist.append_if_missing(use);
           }
         }
@@ -1034,10 +1126,12 @@
       PointsTo(ptset, get_addp_base(n), igvn);
       assert(ptset.Size() == 1, "AddP address is unique");
       uint elem = ptset.getelem(); // Allocation node's index
-      if (elem == _phantom_object)
+      if (elem == _phantom_object) {
+        assert(false, "escaped allocation");
         continue; // Assume the value was set outside this method.
+      }
       Node *base = get_map(elem);  // CheckCastPP node
-      if (!split_AddP(n, base, igvn)) continue; // wrong type
+      if (!split_AddP(n, base, igvn)) continue; // wrong type from dead path
       tinst = igvn->type(base)->isa_oopptr();
     } else if (n->is_Phi() ||
                n->is_CheckCastPP() ||
@@ -1052,8 +1146,10 @@
       PointsTo(ptset, n, igvn);
       if (ptset.Size() == 1) {
         uint elem = ptset.getelem(); // Allocation node's index
-        if (elem == _phantom_object)
+        if (elem == _phantom_object) {
+          assert(false, "escaped allocation");
           continue; // Assume the value was set outside this method.
+        }
         Node *val = get_map(elem);   // CheckCastPP node
         TypeNode *tn = n->as_Type();
         tinst = igvn->type(val)->isa_oopptr();
@@ -1068,8 +1164,7 @@
           tn_t = tn_type->isa_oopptr();
         }
 
-        if (tn_t != NULL &&
-            tinst->cast_to_instance_id(TypeOopPtr::InstanceBot)->higher_equal(tn_t)) {
+        if (tn_t != NULL && tinst->klass()->is_subtype_of(tn_t->klass())) {
           if (tn_type->isa_narrowoop()) {
             tn_type = tinst->make_narrowoop();
           } else {
@@ -1081,33 +1176,25 @@
           igvn->hash_insert(tn);
           record_for_optimizer(n);
         } else {
-          continue; // wrong type
+          assert(tn_type == TypePtr::NULL_PTR ||
+                 tn_t != NULL && !tinst->klass()->is_subtype_of(tn_t->klass()),
+                 "unexpected type");
+          continue; // Skip dead path with different type
         }
       }
     } else {
+      debug_only(n->dump();)
+      assert(false, "EA: unexpected node");
       continue;
     }
-    // push users on appropriate worklist
+    // push allocation's users on appropriate worklist
     for (DUIterator_Fast imax, i = n->fast_outs(imax); i < imax; i++) {
       Node *use = n->fast_out(i);
       if(use->is_Mem() && use->in(MemNode::Address) == n) {
-        memnode_worklist.append_if_missing(use);
-      } else if (use->is_Initialize()) {
+        // Load/store to instance's field
         memnode_worklist.append_if_missing(use);
-      } else if (use->is_MergeMem()) {
-        mergemem_worklist.append_if_missing(use);
-      } else if (use->is_SafePoint() && tinst != NULL) {
-        // Look for MergeMem nodes for calls which reference unique allocation
-        // (through CheckCastPP nodes) even for debug info.
-        Node* m = use->in(TypeFunc::Memory);
-        uint iid = tinst->instance_id();
-        while (m->is_Proj() && m->in(0)->is_SafePoint() &&
-               m->in(0) != use && !m->in(0)->_idx != iid) {
-          m = m->in(0)->in(TypeFunc::Memory);
-        }
-        if (m->is_MergeMem()) {
-          mergemem_worklist.append_if_missing(m);
-        }
+      } else if (use->is_MemBar()) {
+        memnode_worklist.append_if_missing(use);
       } else if (use->is_AddP() && use->outcnt() > 0) { // No dead nodes
         Node* addp2 = find_second_addp(use, n);
         if (addp2 != NULL) {
@@ -1120,6 +1207,29 @@
                  use->is_DecodeN() ||
                  (use->is_ConstraintCast() && use->Opcode() == Op_CastPP)) {
         alloc_worklist.append_if_missing(use);
+#ifdef ASSERT
+      } else if (use->is_Mem()) {
+        assert(use->in(MemNode::Address) != n, "EA: missing allocation reference path");
+      } else if (use->is_MergeMem()) {
+        assert(_mergemem_worklist.contains(use->as_MergeMem()), "EA: missing MergeMem node in the worklist");
+      } else if (use->is_SafePoint()) {
+        // Look for MergeMem nodes for calls which reference unique allocation
+        // (through CheckCastPP nodes) even for debug info.
+        Node* m = use->in(TypeFunc::Memory);
+        if (m->is_MergeMem()) {
+          assert(_mergemem_worklist.contains(m->as_MergeMem()), "EA: missing MergeMem node in the worklist");
+        }
+      } else {
+        uint op = use->Opcode();
+        if (!(op == Op_CmpP || op == Op_Conv2B ||
+              op == Op_CastP2X || op == Op_StoreCM ||
+              op == Op_FastLock || op == Op_AryEq || op == Op_StrComp ||
+              op == Op_StrEquals || op == Op_StrIndexOf)) {
+          n->dump();
+          use->dump();
+          assert(false, "EA: missing allocation reference path");
+        }
+#endif
       }
     }
 
@@ -1137,19 +1247,16 @@
     Node *n = memnode_worklist.pop();
     if (visited.test_set(n->_idx))
       continue;
-    if (n->is_Phi()) {
-      assert(n->as_Phi()->adr_type() != TypePtr::BOTTOM, "narrow memory slice required");
-      // we don't need to do anything, but the users must be pushed if we haven't processed
-      // this Phi before
-    } else if (n->is_Initialize()) {
-      // we don't need to do anything, but the users of the memory projection must be pushed
-      n = n->as_Initialize()->proj_out(TypeFunc::Memory);
+    if (n->is_Phi() || n->is_ClearArray()) {
+      // we don't need to do anything, but the users must be pushed
+    } else if (n->is_MemBar()) { // Initialize, MemBar nodes
+      // we don't need to do anything, but the users must be pushed
+      n = n->as_MemBar()->proj_out(TypeFunc::Memory);
       if (n == NULL)
         continue;
     } else {
       assert(n->is_Mem(), "memory node required.");
       Node *addr = n->in(MemNode::Address);
-      assert(addr->is_AddP(), "AddP required");
       const Type *addr_t = igvn->type(addr);
       if (addr_t == Type::TOP)
         continue;
@@ -1161,6 +1268,10 @@
         return;
       }
       if (mem != n->in(MemNode::Memory)) {
+        // We delay the memory edge update since we need old one in
+        // MergeMem code below when instances memory slices are separated.
+        debug_only(Node* pn = ptnode_adr(n->_idx)->_node;)
+        assert(pn == NULL || pn == n, "wrong node");
         set_map(n->_idx, mem);
         ptnode_adr(n->_idx)->_node = n;
       }
@@ -1181,36 +1292,55 @@
     // push user on appropriate worklist
     for (DUIterator_Fast imax, i = n->fast_outs(imax); i < imax; i++) {
       Node *use = n->fast_out(i);
-      if (use->is_Phi()) {
+      if (use->is_Phi() || use->is_ClearArray()) {
         memnode_worklist.append_if_missing(use);
       } else if(use->is_Mem() && use->in(MemNode::Memory) == n) {
+        if (use->Opcode() == Op_StoreCM) // Ignore cardmark stores
+          continue;
         memnode_worklist.append_if_missing(use);
-      } else if (use->is_Initialize()) {
+      } else if (use->is_MemBar()) {
         memnode_worklist.append_if_missing(use);
+#ifdef ASSERT
+      } else if(use->is_Mem()) {
+        assert(use->in(MemNode::Memory) != n, "EA: missing memory path");
       } else if (use->is_MergeMem()) {
-        mergemem_worklist.append_if_missing(use);
+        assert(_mergemem_worklist.contains(use->as_MergeMem()), "EA: missing MergeMem node in the worklist");
+      } else {
+        uint op = use->Opcode();
+        if (!(op == Op_StoreCM ||
+              (op == Op_CallLeaf && use->as_CallLeaf()->_name != NULL &&
+               strcmp(use->as_CallLeaf()->_name, "g1_wb_pre") == 0) ||
+              op == Op_AryEq || op == Op_StrComp ||
+              op == Op_StrEquals || op == Op_StrIndexOf)) {
+          n->dump();
+          use->dump();
+          assert(false, "EA: missing memory path");
+        }
+#endif
       }
     }
   }
 
   //  Phase 3:  Process MergeMem nodes from mergemem_worklist.
-  //            Walk each memory moving the first node encountered of each
+  //            Walk each memory slice moving the first node encountered of each
   //            instance type to the the input corresponding to its alias index.
-  while (mergemem_worklist.length() != 0) {
-    Node *n = mergemem_worklist.pop();
-    assert(n->is_MergeMem(), "MergeMem node required.");
-    if (visited.test_set(n->_idx))
-      continue;
-    MergeMemNode *nmm = n->as_MergeMem();
+  uint length = _mergemem_worklist.length();
+  for( uint next = 0; next < length; ++next ) {
+    MergeMemNode* nmm = _mergemem_worklist.at(next);
+    assert(!visited.test_set(nmm->_idx), "should not be visited before");
     // Note: we don't want to use MergeMemStream here because we only want to
-    //  scan inputs which exist at the start, not ones we add during processing.
+    // scan inputs which exist at the start, not ones we add during processing.
+    // Note 2: MergeMem may already contains instance memory slices added
+    // during find_inst_mem() call when memory nodes were processed above.
+    igvn->hash_delete(nmm);
     uint nslices = nmm->req();
-    igvn->hash_delete(nmm);
     for (uint i = Compile::AliasIdxRaw+1; i < nslices; i++) {
       Node* mem = nmm->in(i);
       Node* cur = NULL;
       if (mem == NULL || mem->is_top())
         continue;
+      // First, update mergemem by moving memory nodes to corresponding slices
+      // if their type became more precise since this mergemem was created.
       while (mem->is_Mem()) {
         const Type *at = igvn->type(mem->in(MemNode::Address));
         if (at != Type::TOP) {
@@ -1229,7 +1359,7 @@
       }
       nmm->set_memory_at(i, (cur != NULL) ? cur : mem);
       // Find any instance of the current type if we haven't encountered
-      // a value of the instance along the chain.
+      // already a memory slice of the instance along the memory chain.
       for (uint ni = new_index_start; ni < new_index_end; ni++) {
         if((uint)_compile->get_general_index(ni) == i) {
           Node *m = (ni >= nmm->req()) ? nmm->empty_memory() : nmm->in(ni);
@@ -1245,11 +1375,11 @@
     }
     // Find the rest of instances values
     for (uint ni = new_index_start; ni < new_index_end; ni++) {
-      const TypeOopPtr *tinst = igvn->C->get_adr_type(ni)->isa_oopptr();
+      const TypeOopPtr *tinst = _compile->get_adr_type(ni)->isa_oopptr();
       Node* result = step_through_mergemem(nmm, ni, tinst);
       if (result == nmm->base_memory()) {
         // Didn't find instance memory, search through general slice recursively.
-        result = nmm->memory_at(igvn->C->get_general_index(ni));
+        result = nmm->memory_at(_compile->get_general_index(ni));
         result = find_inst_mem(result, ni, orig_phis, igvn);
         if (_compile->failing()) {
           return;
@@ -1259,41 +1389,6 @@
     }
     igvn->hash_insert(nmm);
     record_for_optimizer(nmm);
-
-    // Propagate new memory slices to following MergeMem nodes.
-    for (DUIterator_Fast imax, i = n->fast_outs(imax); i < imax; i++) {
-      Node *use = n->fast_out(i);
-      if (use->is_Call()) {
-        CallNode* in = use->as_Call();
-        if (in->proj_out(TypeFunc::Memory) != NULL) {
-          Node* m = in->proj_out(TypeFunc::Memory);
-          for (DUIterator_Fast jmax, j = m->fast_outs(jmax); j < jmax; j++) {
-            Node* mm = m->fast_out(j);
-            if (mm->is_MergeMem()) {
-              mergemem_worklist.append_if_missing(mm);
-            }
-          }
-        }
-        if (use->is_Allocate()) {
-          use = use->as_Allocate()->initialization();
-          if (use == NULL) {
-            continue;
-          }
-        }
-      }
-      if (use->is_Initialize()) {
-        InitializeNode* in = use->as_Initialize();
-        if (in->proj_out(TypeFunc::Memory) != NULL) {
-          Node* m = in->proj_out(TypeFunc::Memory);
-          for (DUIterator_Fast jmax, j = m->fast_outs(jmax); j < jmax; j++) {
-            Node* mm = m->fast_out(j);
-            if (mm->is_MergeMem()) {
-              mergemem_worklist.append_if_missing(mm);
-            }
-          }
-        }
-      }
-    }
   }
 
   //  Phase 4:  Update the inputs of non-instance memory Phis and
@@ -1322,19 +1417,48 @@
   }
 
   // Update the memory inputs of MemNodes with the value we computed
-  // in Phase 2.
+  // in Phase 2 and move stores memory users to corresponding memory slices.
+#ifdef ASSERT
+  visited.Clear();
+  Node_Stack old_mems(arena, _compile->unique() >> 2);
+#endif
   for (uint i = 0; i < nodes_size(); i++) {
     Node *nmem = get_map(i);
     if (nmem != NULL) {
       Node *n = ptnode_adr(i)->_node;
-      if (n != NULL && n->is_Mem()) {
+      assert(n != NULL, "sanity");
+      if (n->is_Mem()) {
+#ifdef ASSERT
+        Node* old_mem = n->in(MemNode::Memory);
+        if (!visited.test_set(old_mem->_idx)) {
+          old_mems.push(old_mem, old_mem->outcnt());
+        }
+#endif
+        assert(n->in(MemNode::Memory) != nmem, "sanity");
+        if (!n->is_Load()) {
+          // Move memory users of a store first.
+          move_inst_mem(n, orig_phis, igvn);
+        }
+        // Now update memory input
         igvn->hash_delete(n);
         n->set_req(MemNode::Memory, nmem);
         igvn->hash_insert(n);
         record_for_optimizer(n);
+      } else {
+        assert(n->is_Allocate() || n->is_CheckCastPP() ||
+               n->is_AddP() || n->is_Phi(), "unknown node used for set_map()");
       }
     }
   }
+#ifdef ASSERT
+  // Verify that memory was split correctly
+  while (old_mems.is_nonempty()) {
+    Node* old_mem = old_mems.node();
+    uint  old_cnt = old_mems.index();
+    old_mems.pop();
+    assert(old_cnt = old_mem->outcnt(), "old mem could be lost");
+  }
+#endif
 }
 
 bool ConnectionGraph::has_candidates(Compile *C) {
@@ -1381,8 +1505,20 @@
         ptnode_adr(n->_idx)->node_type() == PointsToNode::JavaObject) {
       has_allocations = true;
     }
-    if(n->is_AddP())
-      cg_worklist.append(n->_idx);
+    if(n->is_AddP()) {
+      // Collect address nodes which directly reference an allocation.
+      // Use them during stage 3 below to build initial connection graph
+      // field edges. Other field edges could be added after StoreP/LoadP
+      // nodes are processed during stage 4 below.
+      Node* base = get_addp_base(n);
+      if(base->is_Proj() && base->in(0)->is_Allocate()) {
+        cg_worklist.append(n->_idx);
+      }
+    } else if (n->is_MergeMem()) {
+      // Collect all MergeMem nodes to add memory slices for
+      // scalar replaceable objects in split_unique_types().
+      _mergemem_worklist.append(n->as_MergeMem());
+    }
     for (DUIterator_Fast imax, i = n->fast_outs(imax); i < imax; i++) {
       Node* m = n->fast_out(i);   // Get user
       worklist_init.push(m);
@@ -1423,12 +1559,13 @@
     }
   }
 
-  VectorSet ptset(Thread::current()->resource_area());
+  Arena* arena = Thread::current()->resource_area();
+  VectorSet ptset(arena);
   GrowableArray<uint>  deferred_edges;
-  VectorSet visited(Thread::current()->resource_area());
+  VectorSet visited(arena);
 
-  // 5. Remove deferred edges from the graph and collect
-  //    information needed for type splitting.
+  // 5. Remove deferred edges from the graph and adjust
+  //    escape state of nonescaping objects.
   cg_length = cg_worklist.length();
   for( uint next = 0; next < cg_length; ++next ) {
     int ni = cg_worklist.at(next);
@@ -1438,98 +1575,9 @@
       remove_deferred(ni, &deferred_edges, &visited);
       Node *n = ptn->_node;
       if (n->is_AddP()) {
-        // Search for objects which are not scalar replaceable.
-        // Mark their escape state as ArgEscape to propagate the state
-        // to referenced objects.
-        // Note: currently there are no difference in compiler optimizations
-        // for ArgEscape objects and NoEscape objects which are not
-        // scalar replaceable.
-
-        int offset = ptn->offset();
-        Node *base = get_addp_base(n);
-        ptset.Clear();
-        PointsTo(ptset, base, igvn);
-        int ptset_size = ptset.Size();
-
-        // Check if a field's initializing value is recorded and add
-        // a corresponding NULL field's value if it is not recorded.
-        // Connection Graph does not record a default initialization by NULL
-        // captured by Initialize node.
-        //
-        // Note: it will disable scalar replacement in some cases:
-        //
-        //    Point p[] = new Point[1];
-        //    p[0] = new Point(); // Will be not scalar replaced
-        //
-        // but it will save us from incorrect optimizations in next cases:
-        //
-        //    Point p[] = new Point[1];
-        //    if ( x ) p[0] = new Point(); // Will be not scalar replaced
-        //
-        // Without a control flow analysis we can't distinguish above cases.
-        //
-        if (offset != Type::OffsetBot && ptset_size == 1) {
-          uint elem = ptset.getelem(); // Allocation node's index
-          // It does not matter if it is not Allocation node since
-          // only non-escaping allocations are scalar replaced.
-          if (ptnode_adr(elem)->_node->is_Allocate() &&
-              ptnode_adr(elem)->escape_state() == PointsToNode::NoEscape) {
-            AllocateNode* alloc = ptnode_adr(elem)->_node->as_Allocate();
-            InitializeNode* ini = alloc->initialization();
-            Node* value = NULL;
-            if (ini != NULL) {
-              BasicType ft = UseCompressedOops ? T_NARROWOOP : T_OBJECT;
-              Node* store = ini->find_captured_store(offset, type2aelembytes(ft), igvn);
-              if (store != NULL && store->is_Store())
-                value = store->in(MemNode::ValueIn);
-            }
-            if (value == NULL || value != ptnode_adr(value->_idx)->_node) {
-              // A field's initializing value was not recorded. Add NULL.
-              uint null_idx = UseCompressedOops ? _noop_null : _oop_null;
-              add_pointsto_edge(ni, null_idx);
-            }
-          }
-        }
-
-        // An object is not scalar replaceable if the field which may point
-        // to it has unknown offset (unknown element of an array of objects).
-        //
-        if (offset == Type::OffsetBot) {
-          uint e_cnt = ptn->edge_count();
-          for (uint ei = 0; ei < e_cnt; ei++) {
-            uint npi = ptn->edge_target(ei);
-            set_escape_state(npi, PointsToNode::ArgEscape);
-            ptnode_adr(npi)->_scalar_replaceable = false;
-          }
-        }
-
-        // Currently an object is not scalar replaceable if a LoadStore node
-        // access its field since the field value is unknown after it.
-        //
-        bool has_LoadStore = false;
-        for (DUIterator_Fast imax, i = n->fast_outs(imax); i < imax; i++) {
-          Node *use = n->fast_out(i);
-          if (use->is_LoadStore()) {
-            has_LoadStore = true;
-            break;
-          }
-        }
-        // An object is not scalar replaceable if the address points
-        // to unknown field (unknown element for arrays, offset is OffsetBot).
-        //
-        // Or the address may point to more then one object. This may produce
-        // the false positive result (set scalar_replaceable to false)
-        // since the flow-insensitive escape analysis can't separate
-        // the case when stores overwrite the field's value from the case
-        // when stores happened on different control branches.
-        //
-        if (ptset_size > 1 || ptset_size != 0 &&
-            (has_LoadStore || offset == Type::OffsetBot)) {
-          for( VectorSetI j(&ptset); j.test(); ++j ) {
-            set_escape_state(j.elem, PointsToNode::ArgEscape);
-            ptnode_adr(j.elem)->_scalar_replaceable = false;
-          }
-        }
+        // Search for objects which are not scalar replaceable
+        // and adjust their escape state.
+        verify_escape_state(ni, ptset, igvn);
       }
     }
   }
@@ -1646,6 +1694,150 @@
   return has_non_escaping_obj;
 }
 
+// Search for objects which are not scalar replaceable.
+void ConnectionGraph::verify_escape_state(int nidx, VectorSet& ptset, PhaseTransform* phase) {
+  PointsToNode* ptn = ptnode_adr(nidx);
+  Node* n = ptn->_node;
+  assert(n->is_AddP(), "Should be called for AddP nodes only");
+  // Search for objects which are not scalar replaceable.
+  // Mark their escape state as ArgEscape to propagate the state
+  // to referenced objects.
+  // Note: currently there are no difference in compiler optimizations
+  // for ArgEscape objects and NoEscape objects which are not
+  // scalar replaceable.
+
+  Compile* C = _compile;
+
+  int offset = ptn->offset();
+  Node* base = get_addp_base(n);
+  ptset.Clear();
+  PointsTo(ptset, base, phase);
+  int ptset_size = ptset.Size();
+
+  // Check if a oop field's initializing value is recorded and add
+  // a corresponding NULL field's value if it is not recorded.
+  // Connection Graph does not record a default initialization by NULL
+  // captured by Initialize node.
+  //
+  // Note: it will disable scalar replacement in some cases:
+  //
+  //    Point p[] = new Point[1];
+  //    p[0] = new Point(); // Will be not scalar replaced
+  //
+  // but it will save us from incorrect optimizations in next cases:
+  //
+  //    Point p[] = new Point[1];
+  //    if ( x ) p[0] = new Point(); // Will be not scalar replaced
+  //
+  // Do a simple control flow analysis to distinguish above cases.
+  //
+  if (offset != Type::OffsetBot && ptset_size == 1) {
+    uint elem = ptset.getelem(); // Allocation node's index
+    // It does not matter if it is not Allocation node since
+    // only non-escaping allocations are scalar replaced.
+    if (ptnode_adr(elem)->_node->is_Allocate() &&
+        ptnode_adr(elem)->escape_state() == PointsToNode::NoEscape) {
+      AllocateNode* alloc = ptnode_adr(elem)->_node->as_Allocate();
+      InitializeNode* ini = alloc->initialization();
+
+      // Check only oop fields.
+      const Type* adr_type = n->as_AddP()->bottom_type();
+      BasicType basic_field_type = T_INT;
+      if (adr_type->isa_instptr()) {
+        ciField* field = C->alias_type(adr_type->isa_instptr())->field();
+        if (field != NULL) {
+          basic_field_type = field->layout_type();
+        } else {
+          // Ignore non field load (for example, klass load)
+        }
+      } else if (adr_type->isa_aryptr()) {
+        const Type* elemtype = adr_type->isa_aryptr()->elem();
+        basic_field_type = elemtype->array_element_basic_type();
+      } else {
+        // Raw pointers are used for initializing stores so skip it.
+        assert(adr_type->isa_rawptr() && base->is_Proj() &&
+               (base->in(0) == alloc),"unexpected pointer type");
+      }
+      if (basic_field_type == T_OBJECT ||
+          basic_field_type == T_NARROWOOP ||
+          basic_field_type == T_ARRAY) {
+        Node* value = NULL;
+        if (ini != NULL) {
+          BasicType ft = UseCompressedOops ? T_NARROWOOP : T_OBJECT;
+          Node* store = ini->find_captured_store(offset, type2aelembytes(ft), phase);
+          if (store != NULL && store->is_Store()) {
+            value = store->in(MemNode::ValueIn);
+          } else if (ptn->edge_count() > 0) { // Are there oop stores?
+            // Check for a store which follows allocation without branches.
+            // For example, a volatile field store is not collected
+            // by Initialize node. TODO: it would be nice to use idom() here.
+            for (DUIterator_Fast imax, i = n->fast_outs(imax); i < imax; i++) {
+              store = n->fast_out(i);
+              if (store->is_Store() && store->in(0) != NULL) {
+                Node* ctrl = store->in(0);
+                while(!(ctrl == ini || ctrl == alloc || ctrl == NULL ||
+                        ctrl == C->root() || ctrl == C->top() || ctrl->is_Region() ||
+                        ctrl->is_IfTrue() || ctrl->is_IfFalse())) {
+                   ctrl = ctrl->in(0);
+                }
+                if (ctrl == ini || ctrl == alloc) {
+                  value = store->in(MemNode::ValueIn);
+                  break;
+                }
+              }
+            }
+          }
+        }
+        if (value == NULL || value != ptnode_adr(value->_idx)->_node) {
+          // A field's initializing value was not recorded. Add NULL.
+          uint null_idx = UseCompressedOops ? _noop_null : _oop_null;
+          add_pointsto_edge(nidx, null_idx);
+        }
+      }
+    }
+  }
+
+  // An object is not scalar replaceable if the field which may point
+  // to it has unknown offset (unknown element of an array of objects).
+  //
+  if (offset == Type::OffsetBot) {
+    uint e_cnt = ptn->edge_count();
+    for (uint ei = 0; ei < e_cnt; ei++) {
+      uint npi = ptn->edge_target(ei);
+      set_escape_state(npi, PointsToNode::ArgEscape);
+      ptnode_adr(npi)->_scalar_replaceable = false;
+    }
+  }
+
+  // Currently an object is not scalar replaceable if a LoadStore node
+  // access its field since the field value is unknown after it.
+  //
+  bool has_LoadStore = false;
+  for (DUIterator_Fast imax, i = n->fast_outs(imax); i < imax; i++) {
+    Node *use = n->fast_out(i);
+    if (use->is_LoadStore()) {
+      has_LoadStore = true;
+      break;
+    }
+  }
+  // An object is not scalar replaceable if the address points
+  // to unknown field (unknown element for arrays, offset is OffsetBot).
+  //
+  // Or the address may point to more then one object. This may produce
+  // the false positive result (set scalar_replaceable to false)
+  // since the flow-insensitive escape analysis can't separate
+  // the case when stores overwrite the field's value from the case
+  // when stores happened on different control branches.
+  //
+  if (ptset_size > 1 || ptset_size != 0 &&
+      (has_LoadStore || offset == Type::OffsetBot)) {
+    for( VectorSetI j(&ptset); j.test(); ++j ) {
+      set_escape_state(j.elem, PointsToNode::ArgEscape);
+      ptnode_adr(j.elem)->_scalar_replaceable = false;
+    }
+  }
+}
+
 void ConnectionGraph::process_call_arguments(CallNode *call, PhaseTransform *phase) {
 
     switch (call->Opcode()) {
@@ -1657,6 +1849,7 @@
       assert(false, "should be done already");
       break;
 #endif
+    case Op_CallLeaf:
     case Op_CallLeafNoFP:
     {
       // Stub calls, objects do not escape but they are not scale replaceable.
@@ -1667,9 +1860,23 @@
         const Type* at = d->field_at(i);
         Node *arg = call->in(i)->uncast();
         const Type *aat = phase->type(arg);
-        if (!arg->is_top() && at->isa_ptr() && aat->isa_ptr()) {
+        if (!arg->is_top() && at->isa_ptr() && aat->isa_ptr() &&
+            ptnode_adr(arg->_idx)->escape_state() < PointsToNode::ArgEscape) {
+
           assert(aat == Type::TOP || aat == TypePtr::NULL_PTR ||
                  aat->isa_ptr() != NULL, "expecting an Ptr");
+#ifdef ASSERT
+          if (!(call->Opcode() == Op_CallLeafNoFP &&
+                call->as_CallLeaf()->_name != NULL &&
+                (strstr(call->as_CallLeaf()->_name, "arraycopy")  != 0) ||
+                call->as_CallLeaf()->_name != NULL &&
+                (strcmp(call->as_CallLeaf()->_name, "g1_wb_pre")  == 0 ||
+                 strcmp(call->as_CallLeaf()->_name, "g1_wb_post") == 0 ))
+          ) {
+            call->dump();
+            assert(false, "EA: unexpected CallLeaf");
+          }
+#endif
           set_escape_state(arg->_idx, PointsToNode::ArgEscape);
           if (arg->is_AddP()) {
             //
@@ -1706,9 +1913,10 @@
         for (uint i = TypeFunc::Parms; i < d->cnt(); i++) {
           const Type* at = d->field_at(i);
           int k = i - TypeFunc::Parms;
+          Node *arg = call->in(i)->uncast();
 
-          if (at->isa_oopptr() != NULL) {
-            Node *arg = call->in(i)->uncast();
+          if (at->isa_oopptr() != NULL &&
+              ptnode_adr(arg->_idx)->escape_state() < PointsToNode::ArgEscape) {
 
             bool global_escapes = false;
             bool fields_escapes = false;
@@ -1942,20 +2150,23 @@
       record_for_optimizer(n);
       _processed.set(n->_idx);
     } else {
-      // Have to process call's arguments first.
+      // Don't mark as processed since call's arguments have to be processed.
       PointsToNode::NodeType nt = PointsToNode::UnknownType;
+      PointsToNode::EscapeState es = PointsToNode::UnknownEscape;
 
       // Check if a call returns an object.
       const TypeTuple *r = n->as_Call()->tf()->range();
-      if (n->is_CallStaticJava() && r->cnt() > TypeFunc::Parms &&
+      if (r->cnt() > TypeFunc::Parms &&
+          r->field_at(TypeFunc::Parms)->isa_ptr() &&
           n->as_Call()->proj_out(TypeFunc::Parms) != NULL) {
-        // Note:  use isa_ptr() instead of isa_oopptr() here because
-        //        the _multianewarray functions return a TypeRawPtr.
-        if (r->field_at(TypeFunc::Parms)->isa_ptr() != NULL) {
-          nt = PointsToNode::JavaObject;
+        nt = PointsToNode::JavaObject;
+        if (!n->is_CallStaticJava()) {
+          // Since the called mathod is statically unknown assume
+          // the worst case that the returned value globally escapes.
+          es = PointsToNode::GlobalEscape;
         }
       }
-      add_node(n, nt, PointsToNode::UnknownEscape, false);
+      add_node(n, nt, es, false);
     }
     return;
   }
@@ -2088,18 +2299,27 @@
     }
     case Op_Proj:
     {
-      // we are only interested in the result projection from a call
+      // we are only interested in the oop result projection from a call
       if (n->as_Proj()->_con == TypeFunc::Parms && n->in(0)->is_Call() ) {
-        add_node(n, PointsToNode::LocalVar, PointsToNode::UnknownEscape, false);
-        process_call_result(n->as_Proj(), phase);
-        if (!_processed.test(n->_idx)) {
-          // The call's result may need to be processed later if the call
-          // returns it's argument and the argument is not processed yet.
-          _delayed_worklist.push(n);
+        const TypeTuple *r = n->in(0)->as_Call()->tf()->range();
+        assert(r->cnt() > TypeFunc::Parms, "sanity");
+        if (r->field_at(TypeFunc::Parms)->isa_ptr() != NULL) {
+          add_node(n, PointsToNode::LocalVar, PointsToNode::UnknownEscape, false);
+          int ti = n->in(0)->_idx;
+          // The call may not be registered yet (since not all its inputs are registered)
+          // if this is the projection from backbranch edge of Phi.
+          if (ptnode_adr(ti)->node_type() != PointsToNode::UnknownType) {
+            process_call_result(n->as_Proj(), phase);
+          }
+          if (!_processed.test(n->_idx)) {
+            // The call's result may need to be processed later if the call
+            // returns it's argument and the argument is not processed yet.
+            _delayed_worklist.push(n);
+          }
+          break;
         }
-      } else {
-        _processed.set(n->_idx);
       }
+      _processed.set(n->_idx);
       break;
     }
     case Op_Return:
@@ -2160,6 +2380,15 @@
       }
       break;
     }
+    case Op_AryEq:
+    case Op_StrComp:
+    case Op_StrEquals:
+    case Op_StrIndexOf:
+    {
+      // char[] arrays passed to string intrinsics are not scalar replaceable.
+      add_node(n, PointsToNode::UnknownType, PointsToNode::UnknownEscape, false);
+      break;
+    }
     case Op_ThreadLocal:
     {
       add_node(n, PointsToNode::JavaObject, PointsToNode::ArgEscape, true);
@@ -2174,6 +2403,7 @@
 
 void ConnectionGraph::build_connection_graph(Node *n, PhaseTransform *phase) {
   uint n_idx = n->_idx;
+  assert(ptnode_adr(n_idx)->_node != NULL, "node should be registered");
 
   // Don't set processed bit for AddP, LoadP, StoreP since
   // they may need more then one pass to process.
@@ -2211,6 +2441,7 @@
     case Op_DecodeN:
     {
       int ti = n->in(1)->_idx;
+      assert(ptnode_adr(ti)->node_type() != PointsToNode::UnknownType, "all nodes should be registered");
       if (ptnode_adr(ti)->node_type() == PointsToNode::JavaObject) {
         add_pointsto_edge(n_idx, ti);
       } else {
@@ -2250,7 +2481,6 @@
 #endif
 
       Node* adr = n->in(MemNode::Address)->uncast();
-      const Type *adr_type = phase->type(adr);
       Node* adr_base;
       if (adr->is_AddP()) {
         adr_base = get_addp_base(adr);
@@ -2302,13 +2532,19 @@
     }
     case Op_Proj:
     {
-      // we are only interested in the result projection from a call
+      // we are only interested in the oop result projection from a call
       if (n->as_Proj()->_con == TypeFunc::Parms && n->in(0)->is_Call() ) {
-        process_call_result(n->as_Proj(), phase);
-        assert(_processed.test(n_idx), "all call results should be processed");
-      } else {
-        assert(false, "Op_Proj");
+        assert(ptnode_adr(n->in(0)->_idx)->node_type() != PointsToNode::UnknownType,
+               "all nodes should be registered");
+        const TypeTuple *r = n->in(0)->as_Call()->tf()->range();
+        assert(r->cnt() > TypeFunc::Parms, "sanity");
+        if (r->field_at(TypeFunc::Parms)->isa_ptr() != NULL) {
+          process_call_result(n->as_Proj(), phase);
+          assert(_processed.test(n_idx), "all call results should be processed");
+          break;
+        }
       }
+      assert(false, "Op_Proj");
       break;
     }
     case Op_Return:
@@ -2320,6 +2556,7 @@
       }
 #endif
       int ti = n->in(TypeFunc::Parms)->_idx;
+      assert(ptnode_adr(ti)->node_type() != PointsToNode::UnknownType, "node should be registered");
       if (ptnode_adr(ti)->node_type() == PointsToNode::JavaObject) {
         add_pointsto_edge(n_idx, ti);
       } else {
@@ -2354,14 +2591,38 @@
       }
       break;
     }
+    case Op_AryEq:
+    case Op_StrComp:
+    case Op_StrEquals:
+    case Op_StrIndexOf:
+    {
+      // char[] arrays passed to string intrinsic do not escape but
+      // they are not scalar replaceable. Adjust escape state for them.
+      // Start from in(2) edge since in(1) is memory edge.
+      for (uint i = 2; i < n->req(); i++) {
+        Node* adr = n->in(i)->uncast();
+        const Type *at = phase->type(adr);
+        if (!adr->is_top() && at->isa_ptr()) {
+          assert(at == Type::TOP || at == TypePtr::NULL_PTR ||
+                 at->isa_ptr() != NULL, "expecting an Ptr");
+          if (adr->is_AddP()) {
+            adr = get_addp_base(adr);
+          }
+          // Mark as ArgEscape everything "adr" could point to.
+          set_escape_state(adr->_idx, PointsToNode::ArgEscape);
+        }
+      }
+      _processed.set(n_idx);
+      break;
+    }
     case Op_ThreadLocal:
     {
       assert(false, "Op_ThreadLocal");
       break;
     }
     default:
-      ;
-      // nothing to do
+      // This method should be called only for EA specific nodes.
+      ShouldNotReachHere();
   }
 }
 
--- a/hotspot/src/share/vm/opto/escape.hpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/share/vm/opto/escape.hpp	Wed Jul 05 17:04:56 2017 +0200
@@ -210,6 +210,8 @@
   Unique_Node_List  _delayed_worklist; // Nodes to be processed before
                                        // the call build_connection_graph().
 
+  GrowableArray<MergeMemNode *>  _mergemem_worklist; // List of all MergeMem nodes
+
   VectorSet                _processed; // Records which nodes have been
                                        // processed.
 
@@ -289,7 +291,7 @@
   bool split_AddP(Node *addp, Node *base,  PhaseGVN  *igvn);
   PhiNode *create_split_phi(PhiNode *orig_phi, int alias_idx, GrowableArray<PhiNode *>  &orig_phi_worklist, PhaseGVN  *igvn, bool &new_created);
   PhiNode *split_memory_phi(PhiNode *orig_phi, int alias_idx, GrowableArray<PhiNode *>  &orig_phi_worklist, PhaseGVN  *igvn);
-  Node *find_mem(Node *mem, int alias_idx, PhaseGVN  *igvn);
+  void  move_inst_mem(Node* n, GrowableArray<PhiNode *>  &orig_phis, PhaseGVN *igvn);
   Node *find_inst_mem(Node *mem, int alias_idx,GrowableArray<PhiNode *>  &orig_phi_worklist,  PhaseGVN  *igvn);
 
   // Propagate unique types created for unescaped allocated objects
@@ -298,7 +300,6 @@
 
   // manage entries in _node_map
   void  set_map(int idx, Node *n)        { _node_map.map(idx, n); }
-  void  set_map_phi(int idx, PhiNode *p) { _node_map.map(idx, (Node *) p); }
   Node *get_map(int idx)                 { return _node_map[idx]; }
   PhiNode *get_map_phi(int idx) {
     Node *phi = _node_map[idx];
@@ -315,6 +316,9 @@
   // Set the escape state of a node
   void set_escape_state(uint ni, PointsToNode::EscapeState es);
 
+  // Search for objects which are not scalar replaceable.
+  void verify_escape_state(int nidx, VectorSet& ptset, PhaseTransform* phase);
+
 public:
   ConnectionGraph(Compile *C);
 
--- a/hotspot/src/share/vm/opto/graphKit.cpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/share/vm/opto/graphKit.cpp	Wed Jul 05 17:04:56 2017 +0200
@@ -1351,8 +1351,8 @@
 }
 
 //------------------------------set_all_memory_call----------------------------
-void GraphKit::set_all_memory_call(Node* call) {
-  Node* newmem = _gvn.transform( new (C, 1) ProjNode(call, TypeFunc::Memory) );
+void GraphKit::set_all_memory_call(Node* call, bool separate_io_proj) {
+  Node* newmem = _gvn.transform( new (C, 1) ProjNode(call, TypeFunc::Memory, separate_io_proj) );
   set_all_memory(newmem);
 }
 
@@ -1573,7 +1573,7 @@
 //---------------------------set_edges_for_java_call---------------------------
 // Connect a newly created call into the current JVMS.
 // A return value node (if any) is returned from set_edges_for_java_call.
-void GraphKit::set_edges_for_java_call(CallJavaNode* call, bool must_throw) {
+void GraphKit::set_edges_for_java_call(CallJavaNode* call, bool must_throw, bool separate_io_proj) {
 
   // Add the predefined inputs:
   call->init_req( TypeFunc::Control, control() );
@@ -1595,13 +1595,13 @@
   // Re-use the current map to produce the result.
 
   set_control(_gvn.transform(new (C, 1) ProjNode(call, TypeFunc::Control)));
-  set_i_o(    _gvn.transform(new (C, 1) ProjNode(call, TypeFunc::I_O    )));
-  set_all_memory_call(xcall);
+  set_i_o(    _gvn.transform(new (C, 1) ProjNode(call, TypeFunc::I_O    , separate_io_proj)));
+  set_all_memory_call(xcall, separate_io_proj);
 
   //return xcall;   // no need, caller already has it
 }
 
-Node* GraphKit::set_results_for_java_call(CallJavaNode* call) {
+Node* GraphKit::set_results_for_java_call(CallJavaNode* call, bool separate_io_proj) {
   if (stopped())  return top();  // maybe the call folded up?
 
   // Capture the return value, if any.
@@ -1614,8 +1614,15 @@
   // Note:  Since any out-of-line call can produce an exception,
   // we always insert an I_O projection from the call into the result.
 
-  make_slow_call_ex(call, env()->Throwable_klass(), false);
-
+  make_slow_call_ex(call, env()->Throwable_klass(), separate_io_proj);
+
+  if (separate_io_proj) {
+    // The caller requested separate projections be used by the fall
+    // through and exceptional paths, so replace the projections for
+    // the fall through path.
+    set_i_o(_gvn.transform( new (C, 1) ProjNode(call, TypeFunc::I_O) ));
+    set_all_memory(_gvn.transform( new (C, 1) ProjNode(call, TypeFunc::Memory) ));
+  }
   return ret;
 }
 
@@ -1678,6 +1685,64 @@
   }
 }
 
+
+// Replace the call with the current state of the kit.
+void GraphKit::replace_call(CallNode* call, Node* result) {
+  JVMState* ejvms = NULL;
+  if (has_exceptions()) {
+    ejvms = transfer_exceptions_into_jvms();
+  }
+
+  SafePointNode* final_state = stop();
+
+  // Find all the needed outputs of this call
+  CallProjections callprojs;
+  call->extract_projections(&callprojs, true);
+
+  // Replace all the old call edges with the edges from the inlining result
+  C->gvn_replace_by(callprojs.fallthrough_catchproj, final_state->in(TypeFunc::Control));
+  C->gvn_replace_by(callprojs.fallthrough_memproj,   final_state->in(TypeFunc::Memory));
+  C->gvn_replace_by(callprojs.fallthrough_ioproj,    final_state->in(TypeFunc::I_O));
+
+  // Replace the result with the new result if it exists and is used
+  if (callprojs.resproj != NULL && result != NULL) {
+    C->gvn_replace_by(callprojs.resproj, result);
+  }
+
+  if (ejvms == NULL) {
+    // No exception edges to simply kill off those paths
+    C->gvn_replace_by(callprojs.catchall_catchproj, C->top());
+    C->gvn_replace_by(callprojs.catchall_memproj,   C->top());
+    C->gvn_replace_by(callprojs.catchall_ioproj,    C->top());
+
+    // Replace the old exception object with top
+    if (callprojs.exobj != NULL) {
+      C->gvn_replace_by(callprojs.exobj, C->top());
+    }
+  } else {
+    GraphKit ekit(ejvms);
+
+    // Load my combined exception state into the kit, with all phis transformed:
+    SafePointNode* ex_map = ekit.combine_and_pop_all_exception_states();
+
+    Node* ex_oop = ekit.use_exception_state(ex_map);
+
+    C->gvn_replace_by(callprojs.catchall_catchproj, ekit.control());
+    C->gvn_replace_by(callprojs.catchall_memproj,   ekit.reset_memory());
+    C->gvn_replace_by(callprojs.catchall_ioproj,    ekit.i_o());
+
+    // Replace the old exception object with the newly created one
+    if (callprojs.exobj != NULL) {
+      C->gvn_replace_by(callprojs.exobj, ex_oop);
+    }
+  }
+
+  // Disconnect the call from the graph
+  call->disconnect_inputs(NULL);
+  C->gvn_replace_by(call, C->top());
+}
+
+
 //------------------------------increment_counter------------------------------
 // for statistics: increment a VM counter by 1
 
@@ -3459,4 +3524,3 @@
   sync_kit(ideal);
 }
 #undef __
-
--- a/hotspot/src/share/vm/opto/graphKit.hpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/share/vm/opto/graphKit.hpp	Wed Jul 05 17:04:56 2017 +0200
@@ -279,6 +279,34 @@
   }
   Node* basic_plus_adr(Node* base, Node* ptr, Node* offset);
 
+
+  // Some convenient shortcuts for common nodes
+  Node* IfTrue(IfNode* iff)                   { return _gvn.transform(new (C,1) IfTrueNode(iff));      }
+  Node* IfFalse(IfNode* iff)                  { return _gvn.transform(new (C,1) IfFalseNode(iff));     }
+
+  Node* AddI(Node* l, Node* r)                { return _gvn.transform(new (C,3) AddINode(l, r));       }
+  Node* SubI(Node* l, Node* r)                { return _gvn.transform(new (C,3) SubINode(l, r));       }
+  Node* MulI(Node* l, Node* r)                { return _gvn.transform(new (C,3) MulINode(l, r));       }
+  Node* DivI(Node* ctl, Node* l, Node* r)     { return _gvn.transform(new (C,3) DivINode(ctl, l, r));  }
+
+  Node* AndI(Node* l, Node* r)                { return _gvn.transform(new (C,3) AndINode(l, r));       }
+  Node* OrI(Node* l, Node* r)                 { return _gvn.transform(new (C,3) OrINode(l, r));        }
+  Node* XorI(Node* l, Node* r)                { return _gvn.transform(new (C,3) XorINode(l, r));       }
+
+  Node* MaxI(Node* l, Node* r)                { return _gvn.transform(new (C,3) MaxINode(l, r));       }
+  Node* MinI(Node* l, Node* r)                { return _gvn.transform(new (C,3) MinINode(l, r));       }
+
+  Node* LShiftI(Node* l, Node* r)             { return _gvn.transform(new (C,3) LShiftINode(l, r));    }
+  Node* RShiftI(Node* l, Node* r)             { return _gvn.transform(new (C,3) RShiftINode(l, r));    }
+  Node* URShiftI(Node* l, Node* r)            { return _gvn.transform(new (C,3) URShiftINode(l, r));   }
+
+  Node* CmpI(Node* l, Node* r)                { return _gvn.transform(new (C,3) CmpINode(l, r));       }
+  Node* CmpL(Node* l, Node* r)                { return _gvn.transform(new (C,3) CmpLNode(l, r));       }
+  Node* CmpP(Node* l, Node* r)                { return _gvn.transform(new (C,3) CmpPNode(l, r));       }
+  Node* Bool(Node* cmp, BoolTest::mask relop) { return _gvn.transform(new (C,2) BoolNode(cmp, relop)); }
+
+  Node* AddP(Node* b, Node* a, Node* o)       { return _gvn.transform(new (C,4) AddPNode(b, a, o));    }
+
   // Convert between int and long, and size_t.
   // (See macros ConvI2X, etc., in type.hpp for ConvI2X, etc.)
   Node* ConvI2L(Node* offset);
@@ -400,7 +428,7 @@
   void set_all_memory(Node* newmem);
 
   // Create a memory projection from the call, then set_all_memory.
-  void set_all_memory_call(Node* call);
+  void set_all_memory_call(Node* call, bool separate_io_proj = false);
 
   // Create a LoadNode, reading from the parser's memory state.
   // (Note:  require_atomic_access is useful only with T_LONG.)
@@ -543,12 +571,12 @@
   // Transform the call, and update the basics: control, i_o, memory.
   // (The next step is usually to call set_results_for_java_call.)
   void set_edges_for_java_call(CallJavaNode* call,
-                               bool must_throw = false);
+                               bool must_throw = false, bool separate_io_proj = false);
 
   // Finish up a java call that was started by set_edges_for_java_call.
   // Call add_exception on any throw arising from the call.
   // Return the call result (transformed).
-  Node* set_results_for_java_call(CallJavaNode* call);
+  Node* set_results_for_java_call(CallJavaNode* call, bool separate_io_proj = false);
 
   // Similar to set_edges_for_java_call, but simplified for runtime calls.
   void  set_predefined_output_for_runtime_call(Node* call) {
@@ -559,6 +587,11 @@
                                                const TypePtr* hook_mem);
   Node* set_predefined_input_for_runtime_call(SafePointNode* call);
 
+  // Replace the call with the current state of the kit.  Requires
+  // that the call was generated with separate io_projs so that
+  // exceptional control flow can be handled properly.
+  void replace_call(CallNode* call, Node* result);
+
   // helper functions for statistics
   void increment_counter(address counter_addr);   // increment a debug counter
   void increment_counter(Node*   counter_addr);   // increment a debug counter
--- a/hotspot/src/share/vm/opto/lcm.cpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/share/vm/opto/lcm.cpp	Wed Jul 05 17:04:56 2017 +0200
@@ -616,8 +616,9 @@
           assert(cfg->_bbs[oop_store->_idx]->_dom_depth <= this->_dom_depth, "oop_store must dominate card-mark");
         }
       }
-      if( n->is_Mach() && n->as_Mach()->ideal_Opcode() == Op_MemBarAcquire &&
-          n->req() > TypeFunc::Parms ) {
+      if( n->is_Mach() && n->req() > TypeFunc::Parms &&
+          (n->as_Mach()->ideal_Opcode() == Op_MemBarAcquire ||
+           n->as_Mach()->ideal_Opcode() == Op_MemBarVolatile) ) {
         // MemBarAcquire could be created without Precedent edge.
         // del_req() replaces the specified edge with the last input edge
         // and then removes the last edge. If the specified edge > number of
--- a/hotspot/src/share/vm/opto/loopnode.cpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/share/vm/opto/loopnode.cpp	Wed Jul 05 17:04:56 2017 +0200
@@ -1279,7 +1279,8 @@
     // Visit all children, looking for Phis
     for (DUIterator i = cl->outs(); cl->has_out(i); i++) {
       Node *out = cl->out(i);
-      if (!out->is_Phi() || out == phi)  continue; // Looking for other phis
+      // Look for other phis (secondary IVs). Skip dead ones
+      if (!out->is_Phi() || out == phi || !phase->has_node(out)) continue;
       PhiNode* phi2 = out->as_Phi();
       Node *incr2 = phi2->in( LoopNode::LoopBackControl );
       // Look for induction variables of the form:  X += constant
--- a/hotspot/src/share/vm/opto/macro.cpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/share/vm/opto/macro.cpp	Wed Jul 05 17:04:56 2017 +0200
@@ -316,6 +316,21 @@
         assert(adr_idx == Compile::AliasIdxRaw, "address must match or be raw");
       }
       mem = mem->in(MemNode::Memory);
+    } else if (mem->is_ClearArray()) {
+      if (!ClearArrayNode::step_through(&mem, alloc->_idx, phase)) {
+        // Can not bypass initialization of the instance
+        // we are looking.
+        debug_only(intptr_t offset;)
+        assert(alloc == AllocateNode::Ideal_allocation(mem->in(3), phase, offset), "sanity");
+        InitializeNode* init = alloc->as_Allocate()->initialization();
+        // We are looking for stored value, return Initialize node
+        // or memory edge from Allocate node.
+        if (init != NULL)
+          return init;
+        else
+          return alloc->in(TypeFunc::Memory); // It will produce zero value (see callers).
+      }
+      // Otherwise skip it (the call updated 'mem' value).
     } else if (mem->Opcode() == Op_SCMemProj) {
       assert(mem->in(0)->is_LoadStore(), "sanity");
       const TypePtr* atype = mem->in(0)->in(MemNode::Address)->bottom_type()->is_ptr();
@@ -823,6 +838,18 @@
           Node *n = use->last_out(k);
           uint oc2 = use->outcnt();
           if (n->is_Store()) {
+#ifdef ASSERT
+            // Verify that there is no dependent MemBarVolatile nodes,
+            // they should be removed during IGVN, see MemBarNode::Ideal().
+            for (DUIterator_Fast pmax, p = n->fast_outs(pmax);
+                                       p < pmax; p++) {
+              Node* mb = n->fast_out(p);
+              assert(mb->is_Initialize() || !mb->is_MemBar() ||
+                     mb->req() <= MemBarNode::Precedent ||
+                     mb->in(MemBarNode::Precedent) != n,
+                     "MemBarVolatile should be eliminated for non-escaping object");
+            }
+#endif
             _igvn.replace_node(n, n->in(MemNode::Memory));
           } else {
             eliminate_card_mark(n);
@@ -912,15 +939,29 @@
     return false;
   }
 
+  CompileLog* log = C->log();
+  if (log != NULL) {
+    Node* klass = alloc->in(AllocateNode::KlassNode);
+    const TypeKlassPtr* tklass = _igvn.type(klass)->is_klassptr();
+    log->head("eliminate_allocation type='%d'",
+              log->identify(tklass->klass()));
+    JVMState* p = alloc->jvms();
+    while (p != NULL) {
+      log->elem("jvms bci='%d' method='%d'", p->bci(), log->identify(p->method()));
+      p = p->caller();
+    }
+    log->tail("eliminate_allocation");
+  }
+
   process_users_of_allocation(alloc);
 
 #ifndef PRODUCT
-if (PrintEliminateAllocations) {
-  if (alloc->is_AllocateArray())
-    tty->print_cr("++++ Eliminated: %d AllocateArray", alloc->_idx);
-  else
-    tty->print_cr("++++ Eliminated: %d Allocate", alloc->_idx);
-}
+  if (PrintEliminateAllocations) {
+    if (alloc->is_AllocateArray())
+      tty->print_cr("++++ Eliminated: %d AllocateArray", alloc->_idx);
+    else
+      tty->print_cr("++++ Eliminated: %d Allocate", alloc->_idx);
+  }
 #endif
 
   return true;
@@ -1639,6 +1680,18 @@
       } // if (!oldbox->is_eliminated())
   } // if (alock->is_Lock() && !lock->is_coarsened())
 
+  CompileLog* log = C->log();
+  if (log != NULL) {
+    log->head("eliminate_lock lock='%d'",
+              alock->is_Lock());
+    JVMState* p = alock->jvms();
+    while (p != NULL) {
+      log->elem("jvms bci='%d' method='%d'", p->bci(), log->identify(p->method()));
+      p = p->caller();
+    }
+    log->tail("eliminate_lock");
+  }
+
   #ifndef PRODUCT
   if (PrintEliminateLocks) {
     if (alock->is_Lock()) {
--- a/hotspot/src/share/vm/opto/matcher.cpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/share/vm/opto/matcher.cpp	Wed Jul 05 17:04:56 2017 +0200
@@ -1832,67 +1832,23 @@
       case Op_Binary:         // These are introduced in the Post_Visit state.
         ShouldNotReachHere();
         break;
-      case Op_StoreB:         // Do match these, despite no ideal reg
-      case Op_StoreC:
-      case Op_StoreCM:
-      case Op_StoreD:
-      case Op_StoreF:
-      case Op_StoreI:
-      case Op_StoreL:
-      case Op_StoreP:
-      case Op_StoreN:
-      case Op_Store16B:
-      case Op_Store8B:
-      case Op_Store4B:
-      case Op_Store8C:
-      case Op_Store4C:
-      case Op_Store2C:
-      case Op_Store4I:
-      case Op_Store2I:
-      case Op_Store2L:
-      case Op_Store4F:
-      case Op_Store2F:
-      case Op_Store2D:
       case Op_ClearArray:
       case Op_SafePoint:
         mem_op = true;
         break;
-      case Op_LoadB:
-      case Op_LoadUS:
-      case Op_LoadD:
-      case Op_LoadF:
-      case Op_LoadI:
-      case Op_LoadKlass:
-      case Op_LoadNKlass:
-      case Op_LoadL:
-      case Op_LoadS:
-      case Op_LoadP:
-      case Op_LoadN:
-      case Op_LoadRange:
-      case Op_LoadD_unaligned:
-      case Op_LoadL_unaligned:
-      case Op_Load16B:
-      case Op_Load8B:
-      case Op_Load4B:
-      case Op_Load4C:
-      case Op_Load2C:
-      case Op_Load8C:
-      case Op_Load8S:
-      case Op_Load4S:
-      case Op_Load2S:
-      case Op_Load4I:
-      case Op_Load2I:
-      case Op_Load2L:
-      case Op_Load4F:
-      case Op_Load2F:
-      case Op_Load2D:
-        mem_op = true;
-        // Must be root of match tree due to prior load conflict
-        if( C->subsume_loads() == false ) {
-          set_shared(n);
+      default:
+        if( n->is_Store() ) {
+          // Do match stores, despite no ideal reg
+          mem_op = true;
+          break;
+        }
+        if( n->is_Mem() ) { // Loads and LoadStores
+          mem_op = true;
+          // Loads must be root of match tree due to prior load conflict
+          if( C->subsume_loads() == false )
+            set_shared(n);
         }
         // Fall into default case
-      default:
         if( !n->ideal_reg() )
           set_dontcare(n);  // Unmatchable Nodes
       } // end_switch
@@ -1913,15 +1869,15 @@
           continue; // for(int i = ...)
         }
 
-        // Clone addressing expressions as they are "free" in most instructions
+        if( mop == Op_AddP && m->in(AddPNode::Base)->Opcode() == Op_DecodeN ) {
+          // Bases used in addresses must be shared but since
+          // they are shared through a DecodeN they may appear
+          // to have a single use so force sharing here.
+          set_shared(m->in(AddPNode::Base)->in(1));
+        }
+
+        // Clone addressing expressions as they are "free" in memory access instructions
         if( mem_op && i == MemNode::Address && mop == Op_AddP ) {
-          if (m->in(AddPNode::Base)->Opcode() == Op_DecodeN) {
-            // Bases used in addresses must be shared but since
-            // they are shared through a DecodeN they may appear
-            // to have a single use so force sharing here.
-            set_shared(m->in(AddPNode::Base)->in(1));
-          }
-
           // Some inputs for address expression are not put on stack
           // to avoid marking them as shared and forcing them into register
           // if they are used only in address expressions.
--- a/hotspot/src/share/vm/opto/memnode.cpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/share/vm/opto/memnode.cpp	Wed Jul 05 17:04:56 2017 +0200
@@ -123,6 +123,13 @@
       } else {
         assert(false, "unexpected projection");
       }
+    } else if (result->is_ClearArray()) {
+      if (!ClearArrayNode::step_through(&result, instance_id, phase)) {
+        // Can not bypass initialization of the instance
+        // we are looking for.
+        break;
+      }
+      // Otherwise skip it (the call updated 'result' value).
     } else if (result->is_MergeMem()) {
       result = step_through_mergemem(phase, result->as_MergeMem(), t_adr, NULL, tty);
     }
@@ -255,6 +262,13 @@
     return NodeSentinel; // caller will return NULL
   }
 
+  // Do NOT remove or optimize the next lines: ensure a new alias index
+  // is allocated for an oop pointer type before Escape Analysis.
+  // Note: C++ will not remove it since the call has side effect.
+  if ( t_adr->isa_oopptr() ) {
+    int alias_idx = phase->C->get_alias_index(t_adr->is_ptr());
+  }
+
 #ifdef ASSERT
   Node* base = NULL;
   if (address->is_AddP())
@@ -530,6 +544,15 @@
       } else if (mem->is_Proj() && mem->in(0)->is_MemBar()) {
         mem = mem->in(0)->in(TypeFunc::Memory);
         continue;           // (a) advance through independent MemBar memory
+      } else if (mem->is_ClearArray()) {
+        if (ClearArrayNode::step_through(&mem, (uint)addr_t->instance_id(), phase)) {
+          // (the call updated 'mem' value)
+          continue;         // (a) advance through independent allocation memory
+        } else {
+          // Can not bypass initialization of the instance
+          // we are looking for.
+          return mem;
+        }
       } else if (mem->is_MergeMem()) {
         int alias_idx = phase->C->get_alias_index(adr_type());
         mem = mem->as_MergeMem()->memory_at(alias_idx);
@@ -1496,6 +1519,8 @@
       }
     }
   } else if (tp->base() == Type::InstPtr) {
+    const TypeInstPtr* tinst = tp->is_instptr();
+    ciKlass* klass = tinst->klass();
     assert( off != Type::OffsetBot ||
             // arrays can be cast to Objects
             tp->is_oopptr()->klass()->is_java_lang_Object() ||
@@ -1503,6 +1528,25 @@
             phase->C->has_unsafe_access(),
             "Field accesses must be precise" );
     // For oop loads, we expect the _type to be precise
+    if (OptimizeStringConcat && klass == phase->C->env()->String_klass() &&
+        adr->is_AddP() && off != Type::OffsetBot) {
+      // For constant Strings treat the fields as compile time constants.
+      Node* base = adr->in(AddPNode::Base);
+      if (base->Opcode() == Op_ConP) {
+        const TypeOopPtr* t = phase->type(base)->isa_oopptr();
+        ciObject* string = t->const_oop();
+        ciConstant constant = string->as_instance()->field_value_by_offset(off);
+        if (constant.basic_type() == T_INT) {
+          return TypeInt::make(constant.as_int());
+        } else if (constant.basic_type() == T_ARRAY) {
+          if (adr->bottom_type()->is_ptr_to_narrowoop()) {
+            return TypeNarrowOop::make_from_constant(constant.as_object());
+          } else {
+            return TypeOopPtr::make_from_constant(constant.as_object());
+          }
+        }
+      }
+    }
   } else if (tp->base() == Type::KlassPtr) {
     assert( off != Type::OffsetBot ||
             // arrays can be cast to Objects
@@ -2426,6 +2470,31 @@
   return mem;
 }
 
+//----------------------------step_through----------------------------------
+// Return allocation input memory edge if it is different instance
+// or itself if it is the one we are looking for.
+bool ClearArrayNode::step_through(Node** np, uint instance_id, PhaseTransform* phase) {
+  Node* n = *np;
+  assert(n->is_ClearArray(), "sanity");
+  intptr_t offset;
+  AllocateNode* alloc = AllocateNode::Ideal_allocation(n->in(3), phase, offset);
+  // This method is called only before Allocate nodes are expanded during
+  // macro nodes expansion. Before that ClearArray nodes are only generated
+  // in LibraryCallKit::generate_arraycopy() which follows allocations.
+  assert(alloc != NULL, "should have allocation");
+  if (alloc->_idx == instance_id) {
+    // Can not bypass initialization of the instance we are looking for.
+    return false;
+  }
+  // Otherwise skip it.
+  InitializeNode* init = alloc->initialization();
+  if (init != NULL)
+    *np = init->in(TypeFunc::Memory);
+  else
+    *np = alloc->in(TypeFunc::Memory);
+  return true;
+}
+
 //----------------------------clear_memory-------------------------------------
 // Generate code to initialize object storage to zero.
 Node* ClearArrayNode::clear_memory(Node* ctl, Node* mem, Node* dest,
@@ -2599,7 +2668,30 @@
 // Return a node which is more "ideal" than the current node.  Strip out
 // control copies
 Node *MemBarNode::Ideal(PhaseGVN *phase, bool can_reshape) {
-  return remove_dead_region(phase, can_reshape) ? this : NULL;
+  if (remove_dead_region(phase, can_reshape)) return this;
+
+  // Eliminate volatile MemBars for scalar replaced objects.
+  if (can_reshape && req() == (Precedent+1) &&
+      (Opcode() == Op_MemBarAcquire || Opcode() == Op_MemBarVolatile)) {
+    // Volatile field loads and stores.
+    Node* my_mem = in(MemBarNode::Precedent);
+    if (my_mem != NULL && my_mem->is_Mem()) {
+      const TypeOopPtr* t_oop = my_mem->in(MemNode::Address)->bottom_type()->isa_oopptr();
+      // Check for scalar replaced object reference.
+      if( t_oop != NULL && t_oop->is_known_instance_field() &&
+          t_oop->offset() != Type::OffsetBot &&
+          t_oop->offset() != Type::OffsetTop) {
+        // Replace MemBar projections by its inputs.
+        PhaseIterGVN* igvn = phase->is_IterGVN();
+        igvn->replace_node(proj_out(TypeFunc::Memory), in(TypeFunc::Memory));
+        igvn->replace_node(proj_out(TypeFunc::Control), in(TypeFunc::Control));
+        // Must return either the original node (now dead) or a new node
+        // (Do not return a top here, since that would break the uniqueness of top.)
+        return new (phase->C, 1) ConINode(TypeInt::ZERO);
+      }
+    }
+  }
+  return NULL;
 }
 
 //------------------------------Value------------------------------------------
--- a/hotspot/src/share/vm/opto/memnode.hpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/share/vm/opto/memnode.hpp	Wed Jul 05 17:04:56 2017 +0200
@@ -717,7 +717,10 @@
 //------------------------------ClearArray-------------------------------------
 class ClearArrayNode: public Node {
 public:
-  ClearArrayNode( Node *ctrl, Node *arymem, Node *word_cnt, Node *base ) : Node(ctrl,arymem,word_cnt,base) {}
+  ClearArrayNode( Node *ctrl, Node *arymem, Node *word_cnt, Node *base )
+    : Node(ctrl,arymem,word_cnt,base) {
+    init_class_id(Class_ClearArray);
+  }
   virtual int         Opcode() const;
   virtual const Type *bottom_type() const { return Type::MEMORY; }
   // ClearArray modifies array elements, and so affects only the
@@ -743,6 +746,9 @@
                             Node* start_offset,
                             Node* end_offset,
                             PhaseGVN* phase);
+  // Return allocation input memory edge if it is different instance
+  // or itself if it is the one we are looking for.
+  static bool step_through(Node** np, uint instance_id, PhaseTransform* phase);
 };
 
 //------------------------------StrComp-------------------------------------
--- a/hotspot/src/share/vm/opto/node.hpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/share/vm/opto/node.hpp	Wed Jul 05 17:04:56 2017 +0200
@@ -47,6 +47,7 @@
 class CatchNode;
 class CatchProjNode;
 class CheckCastPPNode;
+class ClearArrayNode;
 class CmpNode;
 class CodeBuffer;
 class ConstraintCastNode;
@@ -599,8 +600,9 @@
     DEFINE_CLASS_ID(BoxLock,  Node, 10)
     DEFINE_CLASS_ID(Add,      Node, 11)
     DEFINE_CLASS_ID(Mul,      Node, 12)
+    DEFINE_CLASS_ID(ClearArray, Node, 13)
 
-    _max_classes  = ClassMask_Mul
+    _max_classes  = ClassMask_ClearArray
   };
   #undef DEFINE_CLASS_ID
 
@@ -661,18 +663,25 @@
     return (_flags & Flag_is_Call) != 0;
   }
 
+  CallNode* isa_Call() const {
+    return is_Call() ? as_Call() : NULL;
+  }
+
   CallNode *as_Call() const { // Only for CallNode (not for MachCallNode)
     assert((_class_id & ClassMask_Call) == Class_Call, "invalid node class");
     return (CallNode*)this;
   }
 
-  #define DEFINE_CLASS_QUERY(type) \
-  bool is_##type() const { \
+  #define DEFINE_CLASS_QUERY(type)                           \
+  bool is_##type() const {                                   \
     return ((_class_id & ClassMask_##type) == Class_##type); \
-  } \
-  type##Node *as_##type() const { \
-    assert(is_##type(), "invalid node class"); \
-    return (type##Node*)this; \
+  }                                                          \
+  type##Node *as_##type() const {                            \
+    assert(is_##type(), "invalid node class");               \
+    return (type##Node*)this;                                \
+  }                                                          \
+  type##Node* isa_##type() const {                           \
+    return (is_##type()) ? as_##type() : NULL;               \
   }
 
   DEFINE_CLASS_QUERY(AbstractLock)
@@ -691,6 +700,7 @@
   DEFINE_CLASS_QUERY(CatchProj)
   DEFINE_CLASS_QUERY(CheckCastPP)
   DEFINE_CLASS_QUERY(ConstraintCast)
+  DEFINE_CLASS_QUERY(ClearArray)
   DEFINE_CLASS_QUERY(CMove)
   DEFINE_CLASS_QUERY(Cmp)
   DEFINE_CLASS_QUERY(CountedLoop)
@@ -1249,6 +1259,24 @@
 #undef I_VDUI_ONLY
 #undef VDUI_ONLY
 
+// An Iterator that truly follows the iterator pattern.  Doesn't
+// support deletion but could be made to.
+//
+//   for (SimpleDUIterator i(n); i.has_next(); i.next()) {
+//     Node* m = i.get();
+//
+class SimpleDUIterator : public StackObj {
+ private:
+  Node* node;
+  DUIterator_Fast i;
+  DUIterator_Fast imax;
+ public:
+  SimpleDUIterator(Node* n): node(n), i(n->fast_outs(imax)) {}
+  bool has_next() { return i < imax; }
+  void next() { i++; }
+  Node* get() { return node->fast_out(i); }
+};
+
 
 //-----------------------------------------------------------------------------
 // Map dense integer indices to Nodes.  Uses classic doubling-array trick.
@@ -1290,6 +1318,12 @@
 public:
   Node_List() : Node_Array(Thread::current()->resource_area()), _cnt(0) {}
   Node_List(Arena *a) : Node_Array(a), _cnt(0) {}
+  bool contains(Node* n) {
+    for (uint e = 0; e < size(); e++) {
+      if (at(e) == n) return true;
+    }
+    return false;
+  }
   void insert( uint i, Node *n ) { Node_Array::insert(i,n); _cnt++; }
   void remove( uint i ) { Node_Array::remove(i); _cnt--; }
   void push( Node *b ) { map(_cnt++,b); }
--- a/hotspot/src/share/vm/opto/parse1.cpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/share/vm/opto/parse1.cpp	Wed Jul 05 17:04:56 2017 +0200
@@ -231,12 +231,13 @@
 
   // Use the raw liveness computation to make sure that unexpected
   // values don't propagate into the OSR frame.
-  MethodLivenessResult live_locals = method()->raw_liveness_at_bci(osr_bci());
+  MethodLivenessResult live_locals = method()->liveness_at_bci(osr_bci());
   if (!live_locals.is_valid()) {
     // Degenerate or breakpointed method.
     C->record_method_not_compilable("OSR in empty or breakpointed method");
     return;
   }
+  MethodLivenessResult raw_live_locals = method()->raw_liveness_at_bci(osr_bci());
 
   // Extract the needed locals from the interpreter frame.
   Node *locals_addr = basic_plus_adr(osr_buf, osr_buf, (max_locals-1)*wordSize);
@@ -316,6 +317,10 @@
         continue;
       }
     }
+    if (type->basic_type() == T_ADDRESS && !raw_live_locals.at(index)) {
+      // Skip type check for dead address locals
+      continue;
+    }
     set_local(index, check_interpreter_type(l, type, bad_type_exit));
   }
 
--- a/hotspot/src/share/vm/opto/parse3.cpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/share/vm/opto/parse3.cpp	Wed Jul 05 17:04:56 2017 +0200
@@ -240,19 +240,19 @@
     // membar is dependent on the store, keeping any other membars generated
     // below from floating up past the store.
     int adr_idx = C->get_alias_index(adr_type);
-    insert_mem_bar_volatile(Op_MemBarVolatile, adr_idx);
+    insert_mem_bar_volatile(Op_MemBarVolatile, adr_idx, store);
 
     // Now place a membar for AliasIdxBot for the unknown yet-to-be-parsed
     // volatile alias indices. Skip this if the membar is redundant.
     if (adr_idx != Compile::AliasIdxBot) {
-      insert_mem_bar_volatile(Op_MemBarVolatile, Compile::AliasIdxBot);
+      insert_mem_bar_volatile(Op_MemBarVolatile, Compile::AliasIdxBot, store);
     }
 
     // Finally, place alias-index-specific membars for each volatile index
     // that isn't the adr_idx membar. Typically there's only 1 or 2.
     for( int i = Compile::AliasIdxRaw; i < C->num_alias_types(); i++ ) {
       if (i != adr_idx && C->alias_type(i)->is_volatile()) {
-        insert_mem_bar_volatile(Op_MemBarVolatile, i);
+        insert_mem_bar_volatile(Op_MemBarVolatile, i, store);
       }
     }
   }
--- a/hotspot/src/share/vm/opto/parseHelper.cpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/share/vm/opto/parseHelper.cpp	Wed Jul 05 17:04:56 2017 +0200
@@ -221,6 +221,14 @@
 
   // Push resultant oop onto stack
   push(obj);
+
+  // Keep track of whether opportunities exist for StringBuilder
+  // optimizations.
+  if (OptimizeStringConcat &&
+      (klass == C->env()->StringBuilder_klass() ||
+       klass == C->env()->StringBuffer_klass())) {
+    C->set_has_stringbuilder(true);
+  }
 }
 
 #ifndef PRODUCT
--- a/hotspot/src/share/vm/opto/phase.hpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/share/vm/opto/phase.hpp	Wed Jul 05 17:04:56 2017 +0200
@@ -44,6 +44,7 @@
     BlockLayout,                // Linear ordering of blocks
     Register_Allocation,        // Register allocation, duh
     LIVE,                       // Dragon-book LIVE range problem
+    StringOpts,                 // StringBuilder related optimizations
     Interference_Graph,         // Building the IFG
     Coalesce,                   // Coalescing copies
     Ideal_Loop,                 // Find idealized trip-counted loops
--- a/hotspot/src/share/vm/opto/phaseX.hpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/share/vm/opto/phaseX.hpp	Wed Jul 05 17:04:56 2017 +0200
@@ -345,7 +345,11 @@
   Node  *hash_find(const Node *n) { return _table.hash_find(n); }
 
   // Used after parsing to eliminate values that are no longer in program
-  void   remove_useless_nodes(VectorSet &useful) { _table.remove_useless_nodes(useful); }
+  void   remove_useless_nodes(VectorSet &useful) {
+    _table.remove_useless_nodes(useful);
+    // this may invalidate cached cons so reset the cache
+    init_con_caches();
+  }
 
   virtual ConNode* uncached_makecon(const Type* t);  // override from PhaseTransform
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/opto/stringopts.cpp	Wed Jul 05 17:04:56 2017 +0200
@@ -0,0 +1,1395 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ *
+ */
+
+#include "incls/_precompiled.incl"
+#include "incls/_stringopts.cpp.incl"
+
+#define __ kit.
+
+class StringConcat : public ResourceObj {
+ private:
+  PhaseStringOpts*    _stringopts;
+  Node*               _string_alloc;
+  AllocateNode*       _begin;          // The allocation the begins the pattern
+  CallStaticJavaNode* _end;            // The final call of the pattern.  Will either be
+                                       // SB.toString or or String.<init>(SB.toString)
+  bool                _multiple;       // indicates this is a fusion of two or more
+                                       // separate StringBuilders
+
+  Node*               _arguments;      // The list of arguments to be concatenated
+  GrowableArray<int>  _mode;           // into a String along with a mode flag
+                                       // indicating how to treat the value.
+
+  Node_List           _control;        // List of control nodes that will be deleted
+  Node_List           _uncommon_traps; // Uncommon traps that needs to be rewritten
+                                       // to restart at the initial JVMState.
+ public:
+  // Mode for converting arguments to Strings
+  enum {
+    StringMode,
+    IntMode,
+    CharMode
+  };
+
+  StringConcat(PhaseStringOpts* stringopts, CallStaticJavaNode* end):
+    _end(end),
+    _begin(NULL),
+    _multiple(false),
+    _string_alloc(NULL),
+    _stringopts(stringopts) {
+    _arguments = new (_stringopts->C, 1) Node(1);
+    _arguments->del_req(0);
+  }
+
+  bool validate_control_flow();
+
+  void merge_add() {
+#if 0
+    // XXX This is place holder code for reusing an existing String
+    // allocation but the logic for checking the state safety is
+    // probably inadequate at the moment.
+    CallProjections endprojs;
+    sc->end()->extract_projections(&endprojs, false);
+    if (endprojs.resproj != NULL) {
+      for (SimpleDUIterator i(endprojs.resproj); i.has_next(); i.next()) {
+        CallStaticJavaNode *use = i.get()->isa_CallStaticJava();
+        if (use != NULL && use->method() != NULL &&
+            use->method()->holder() == C->env()->String_klass() &&
+            use->method()->name() == ciSymbol::object_initializer_name() &&
+            use->in(TypeFunc::Parms + 1) == endprojs.resproj) {
+          // Found useless new String(sb.toString()) so reuse the newly allocated String
+          // when creating the result instead of allocating a new one.
+          sc->set_string_alloc(use->in(TypeFunc::Parms));
+          sc->set_end(use);
+        }
+      }
+    }
+#endif
+  }
+
+  StringConcat* merge(StringConcat* other, Node* arg);
+
+  void set_allocation(AllocateNode* alloc) {
+    _begin = alloc;
+  }
+
+  void append(Node* value, int mode) {
+    _arguments->add_req(value);
+    _mode.append(mode);
+  }
+  void push(Node* value, int mode) {
+    _arguments->ins_req(0, value);
+    _mode.insert_before(0, mode);
+  }
+  void push_string(Node* value) {
+    push(value, StringMode);
+  }
+  void push_int(Node* value) {
+    push(value, IntMode);
+  }
+  void push_char(Node* value) {
+    push(value, CharMode);
+  }
+
+  Node* argument(int i) {
+    return _arguments->in(i);
+  }
+  void set_argument(int i, Node* value) {
+    _arguments->set_req(i, value);
+  }
+  int num_arguments() {
+    return _mode.length();
+  }
+  int mode(int i) {
+    return _mode.at(i);
+  }
+  void add_control(Node* ctrl) {
+    assert(!_control.contains(ctrl), "only push once");
+    _control.push(ctrl);
+  }
+  CallStaticJavaNode* end() { return _end; }
+  AllocateNode* begin() { return _begin; }
+  Node* string_alloc() { return _string_alloc; }
+
+  void eliminate_unneeded_control();
+  void eliminate_initialize(InitializeNode* init);
+  void eliminate_call(CallNode* call);
+
+  void maybe_log_transform() {
+    CompileLog* log = _stringopts->C->log();
+    if (log != NULL) {
+      log->head("replace_string_concat arguments='%d' string_alloc='%d' multiple='%d'",
+                num_arguments(),
+                _string_alloc != NULL,
+                _multiple);
+      JVMState* p = _begin->jvms();
+      while (p != NULL) {
+        log->elem("jvms bci='%d' method='%d'", p->bci(), log->identify(p->method()));
+        p = p->caller();
+      }
+      log->tail("replace_string_concat");
+    }
+  }
+
+  void convert_uncommon_traps(GraphKit& kit, const JVMState* jvms) {
+    for (uint u = 0; u < _uncommon_traps.size(); u++) {
+      Node* uct = _uncommon_traps.at(u);
+
+      // Build a new call using the jvms state of the allocate
+      address call_addr = SharedRuntime::uncommon_trap_blob()->instructions_begin();
+      const TypeFunc* call_type = OptoRuntime::uncommon_trap_Type();
+      int size = call_type->domain()->cnt();
+      const TypePtr* no_memory_effects = NULL;
+      Compile* C = _stringopts->C;
+      CallStaticJavaNode* call = new (C, size) CallStaticJavaNode(call_type, call_addr, "uncommon_trap",
+                                                                  jvms->bci(), no_memory_effects);
+      for (int e = 0; e < TypeFunc::Parms; e++) {
+        call->init_req(e, uct->in(e));
+      }
+      // Set the trap request to record intrinsic failure if this trap
+      // is taken too many times.  Ideally we would handle then traps by
+      // doing the original bookkeeping in the MDO so that if it caused
+      // the code to be thrown out we could still recompile and use the
+      // optimization.  Failing the uncommon traps doesn't really mean
+      // that the optimization is a bad idea but there's no other way to
+      // do the MDO updates currently.
+      int trap_request = Deoptimization::make_trap_request(Deoptimization::Reason_intrinsic,
+                                                           Deoptimization::Action_make_not_entrant);
+      call->init_req(TypeFunc::Parms, __ intcon(trap_request));
+      kit.add_safepoint_edges(call);
+
+      _stringopts->gvn()->transform(call);
+      C->gvn_replace_by(uct, call);
+      uct->disconnect_inputs(NULL);
+    }
+  }
+
+  void cleanup() {
+    // disconnect the hook node
+    _arguments->disconnect_inputs(NULL);
+  }
+};
+
+
+void StringConcat::eliminate_unneeded_control() {
+  eliminate_initialize(begin()->initialization());
+  for (uint i = 0; i < _control.size(); i++) {
+    Node* n = _control.at(i);
+    if (n->is_Call()) {
+      if (n != _end) {
+        eliminate_call(n->as_Call());
+      }
+    } else if (n->is_IfTrue()) {
+      Compile* C = _stringopts->C;
+      C->gvn_replace_by(n, n->in(0)->in(0));
+      C->gvn_replace_by(n->in(0), C->top());
+    }
+  }
+}
+
+
+StringConcat* StringConcat::merge(StringConcat* other, Node* arg) {
+  StringConcat* result = new StringConcat(_stringopts, _end);
+  for (uint x = 0; x < _control.size(); x++) {
+    Node* n = _control.at(x);
+    if (n->is_Call()) {
+      result->_control.push(n);
+    }
+  }
+  for (uint x = 0; x < other->_control.size(); x++) {
+    Node* n = other->_control.at(x);
+    if (n->is_Call()) {
+      result->_control.push(n);
+    }
+  }
+  assert(result->_control.contains(other->_end), "what?");
+  assert(result->_control.contains(_begin), "what?");
+  for (int x = 0; x < num_arguments(); x++) {
+    if (argument(x) == arg) {
+      // replace the toString result with the all the arguments that
+      // made up the other StringConcat
+      for (int y = 0; y < other->num_arguments(); y++) {
+        result->append(other->argument(y), other->mode(y));
+      }
+    } else {
+      result->append(argument(x), mode(x));
+    }
+  }
+  result->set_allocation(other->_begin);
+  result->_multiple = true;
+  return result;
+}
+
+
+void StringConcat::eliminate_call(CallNode* call) {
+  Compile* C = _stringopts->C;
+  CallProjections projs;
+  call->extract_projections(&projs, false);
+  if (projs.fallthrough_catchproj != NULL) {
+    C->gvn_replace_by(projs.fallthrough_catchproj, call->in(TypeFunc::Control));
+  }
+  if (projs.fallthrough_memproj != NULL) {
+    C->gvn_replace_by(projs.fallthrough_memproj, call->in(TypeFunc::Memory));
+  }
+  if (projs.catchall_memproj != NULL) {
+    C->gvn_replace_by(projs.catchall_memproj, C->top());
+  }
+  if (projs.fallthrough_ioproj != NULL) {
+    C->gvn_replace_by(projs.fallthrough_ioproj, call->in(TypeFunc::I_O));
+  }
+  if (projs.catchall_ioproj != NULL) {
+    C->gvn_replace_by(projs.catchall_ioproj, C->top());
+  }
+  if (projs.catchall_catchproj != NULL) {
+    // EA can't cope with the partially collapsed graph this
+    // creates so put it on the worklist to be collapsed later.
+    for (SimpleDUIterator i(projs.catchall_catchproj); i.has_next(); i.next()) {
+      Node *use = i.get();
+      int opc = use->Opcode();
+      if (opc == Op_CreateEx || opc == Op_Region) {
+        _stringopts->record_dead_node(use);
+      }
+    }
+    C->gvn_replace_by(projs.catchall_catchproj, C->top());
+  }
+  if (projs.resproj != NULL) {
+    C->gvn_replace_by(projs.resproj, C->top());
+  }
+  C->gvn_replace_by(call, C->top());
+}
+
+void StringConcat::eliminate_initialize(InitializeNode* init) {
+  Compile* C = _stringopts->C;
+
+  // Eliminate Initialize node.
+  assert(init->outcnt() <= 2, "only a control and memory projection expected");
+  assert(init->req() <= InitializeNode::RawStores, "no pending inits");
+  Node *ctrl_proj = init->proj_out(TypeFunc::Control);
+  if (ctrl_proj != NULL) {
+    C->gvn_replace_by(ctrl_proj, init->in(TypeFunc::Control));
+  }
+  Node *mem_proj = init->proj_out(TypeFunc::Memory);
+  if (mem_proj != NULL) {
+    Node *mem = init->in(TypeFunc::Memory);
+    C->gvn_replace_by(mem_proj, mem);
+  }
+  C->gvn_replace_by(init, C->top());
+  init->disconnect_inputs(NULL);
+}
+
+Node_List PhaseStringOpts::collect_toString_calls() {
+  Node_List string_calls;
+  Node_List worklist;
+
+  _visited.Clear();
+
+  // Prime the worklist
+  for (uint i = 1; i < C->root()->len(); i++) {
+    Node* n = C->root()->in(i);
+    if (n != NULL && !_visited.test_set(n->_idx)) {
+      worklist.push(n);
+    }
+  }
+
+  while (worklist.size() > 0) {
+    Node* ctrl = worklist.pop();
+    if (ctrl->is_CallStaticJava()) {
+      CallStaticJavaNode* csj = ctrl->as_CallStaticJava();
+      ciMethod* m = csj->method();
+      if (m != NULL &&
+          (m->intrinsic_id() == vmIntrinsics::_StringBuffer_toString ||
+           m->intrinsic_id() == vmIntrinsics::_StringBuilder_toString)) {
+        string_calls.push(csj);
+      }
+    }
+    if (ctrl->in(0) != NULL && !_visited.test_set(ctrl->in(0)->_idx)) {
+      worklist.push(ctrl->in(0));
+    }
+    if (ctrl->is_Region()) {
+      for (uint i = 1; i < ctrl->len(); i++) {
+        if (ctrl->in(i) != NULL && !_visited.test_set(ctrl->in(i)->_idx)) {
+          worklist.push(ctrl->in(i));
+        }
+      }
+    }
+  }
+  return string_calls;
+}
+
+
+StringConcat* PhaseStringOpts::build_candidate(CallStaticJavaNode* call) {
+  ciMethod* m = call->method();
+  ciSymbol* string_sig;
+  ciSymbol* int_sig;
+  ciSymbol* char_sig;
+  if (m->holder() == C->env()->StringBuilder_klass()) {
+    string_sig = ciSymbol::String_StringBuilder_signature();
+    int_sig = ciSymbol::int_StringBuilder_signature();
+    char_sig = ciSymbol::char_StringBuilder_signature();
+  } else if (m->holder() == C->env()->StringBuffer_klass()) {
+    string_sig = ciSymbol::String_StringBuffer_signature();
+    int_sig = ciSymbol::int_StringBuffer_signature();
+    char_sig = ciSymbol::char_StringBuffer_signature();
+  } else {
+    return NULL;
+  }
+#ifndef PRODUCT
+  if (PrintOptimizeStringConcat) {
+    tty->print("considering toString call in ");
+    call->jvms()->dump_spec(tty); tty->cr();
+  }
+#endif
+
+  StringConcat* sc = new StringConcat(this, call);
+
+  AllocateNode* alloc = NULL;
+  InitializeNode* init = NULL;
+
+  // possible opportunity for StringBuilder fusion
+  CallStaticJavaNode* cnode = call;
+  while (cnode) {
+    Node* recv = cnode->in(TypeFunc::Parms)->uncast();
+    if (recv->is_Proj()) {
+      recv = recv->in(0);
+    }
+    cnode = recv->isa_CallStaticJava();
+    if (cnode == NULL) {
+      alloc = recv->isa_Allocate();
+      if (alloc == NULL) {
+        break;
+      }
+      // Find the constructor call
+      Node* result = alloc->result_cast();
+      if (result == NULL || !result->is_CheckCastPP()) {
+        // strange looking allocation
+#ifndef PRODUCT
+        if (PrintOptimizeStringConcat) {
+          tty->print("giving up because allocation looks strange ");
+          alloc->jvms()->dump_spec(tty); tty->cr();
+        }
+#endif
+        break;
+      }
+      Node* constructor = NULL;
+      for (SimpleDUIterator i(result); i.has_next(); i.next()) {
+        CallStaticJavaNode *use = i.get()->isa_CallStaticJava();
+        if (use != NULL && use->method() != NULL &&
+            use->method()->name() == ciSymbol::object_initializer_name() &&
+            use->method()->holder() == m->holder()) {
+          // Matched the constructor.
+          ciSymbol* sig = use->method()->signature()->as_symbol();
+          if (sig == ciSymbol::void_method_signature() ||
+              sig == ciSymbol::int_void_signature() ||
+              sig == ciSymbol::string_void_signature()) {
+            if (sig == ciSymbol::string_void_signature()) {
+              // StringBuilder(String) so pick this up as the first argument
+              assert(use->in(TypeFunc::Parms + 1) != NULL, "what?");
+              sc->push_string(use->in(TypeFunc::Parms + 1));
+            }
+            // The int variant takes an initial size for the backing
+            // array so just treat it like the void version.
+            constructor = use;
+          } else {
+#ifndef PRODUCT
+            if (PrintOptimizeStringConcat) {
+              tty->print("unexpected constructor signature: %s", sig->as_utf8());
+            }
+#endif
+          }
+          break;
+        }
+      }
+      if (constructor == NULL) {
+        // couldn't find constructor
+#ifndef PRODUCT
+        if (PrintOptimizeStringConcat) {
+          tty->print("giving up because couldn't find constructor ");
+          alloc->jvms()->dump_spec(tty);
+        }
+#endif
+        break;
+      }
+
+      // Walked all the way back and found the constructor call so see
+      // if this call converted into a direct string concatenation.
+      sc->add_control(call);
+      sc->add_control(constructor);
+      sc->add_control(alloc);
+      sc->set_allocation(alloc);
+      if (sc->validate_control_flow()) {
+        return sc;
+      } else {
+        return NULL;
+      }
+    } else if (cnode->method() == NULL) {
+      break;
+    } else if (cnode->method()->holder() == m->holder() &&
+               cnode->method()->name() == ciSymbol::append_name() &&
+               (cnode->method()->signature()->as_symbol() == string_sig ||
+                cnode->method()->signature()->as_symbol() == char_sig ||
+                cnode->method()->signature()->as_symbol() == int_sig)) {
+      sc->add_control(cnode);
+      Node* arg = cnode->in(TypeFunc::Parms + 1);
+      if (cnode->method()->signature()->as_symbol() == int_sig) {
+        sc->push_int(arg);
+      } else if (cnode->method()->signature()->as_symbol() == char_sig) {
+        sc->push_char(arg);
+      } else {
+        if (arg->is_Proj() && arg->in(0)->is_CallStaticJava()) {
+          CallStaticJavaNode* csj = arg->in(0)->as_CallStaticJava();
+          if (csj->method() != NULL &&
+              csj->method()->holder() == C->env()->Integer_klass() &&
+              csj->method()->name() == ciSymbol::toString_name()) {
+            sc->add_control(csj);
+            sc->push_int(csj->in(TypeFunc::Parms));
+            continue;
+          }
+        }
+        sc->push_string(arg);
+      }
+      continue;
+    } else {
+      // some unhandled signature
+#ifndef PRODUCT
+      if (PrintOptimizeStringConcat) {
+        tty->print("giving up because encountered unexpected signature ");
+        cnode->tf()->dump(); tty->cr();
+        cnode->in(TypeFunc::Parms + 1)->dump();
+      }
+#endif
+      break;
+    }
+  }
+  return NULL;
+}
+
+
+PhaseStringOpts::PhaseStringOpts(PhaseGVN* gvn, Unique_Node_List*):
+  Phase(StringOpts),
+  _gvn(gvn),
+  _visited(Thread::current()->resource_area()) {
+
+  assert(OptimizeStringConcat, "shouldn't be here");
+
+  size_table_field = C->env()->Integer_klass()->get_field_by_name(ciSymbol::make("sizeTable"),
+                                                                  ciSymbol::make("[I"), true);
+  if (size_table_field == NULL) {
+    // Something wrong so give up.
+    assert(false, "why can't we find Integer.sizeTable?");
+    return;
+  }
+
+  // Collect the types needed to talk about the various slices of memory
+  const TypeInstPtr* string_type = TypeInstPtr::make(TypePtr::NotNull, C->env()->String_klass(),
+                                                     false, NULL, 0);
+
+  const TypePtr* value_field_type = string_type->add_offset(java_lang_String::value_offset_in_bytes());
+  const TypePtr* offset_field_type = string_type->add_offset(java_lang_String::offset_offset_in_bytes());
+  const TypePtr* count_field_type = string_type->add_offset(java_lang_String::count_offset_in_bytes());
+
+  value_field_idx = C->get_alias_index(value_field_type);
+  count_field_idx = C->get_alias_index(count_field_type);
+  offset_field_idx = C->get_alias_index(offset_field_type);
+  char_adr_idx = C->get_alias_index(TypeAryPtr::CHARS);
+
+  // For each locally allocated StringBuffer see if the usages can be
+  // collapsed into a single String construction.
+
+  // Run through the list of allocation looking for SB.toString to see
+  // if it's possible to fuse the usage of the SB into a single String
+  // construction.
+  GrowableArray<StringConcat*> concats;
+  Node_List toStrings = collect_toString_calls();
+  while (toStrings.size() > 0) {
+    StringConcat* sc = build_candidate(toStrings.pop()->as_CallStaticJava());
+    if (sc != NULL) {
+      concats.push(sc);
+    }
+  }
+
+  // try to coalesce separate concats
+ restart:
+  for (int c = 0; c < concats.length(); c++) {
+    StringConcat* sc = concats.at(c);
+    for (int i = 0; i < sc->num_arguments(); i++) {
+      Node* arg = sc->argument(i);
+      if (arg->is_Proj() && arg->in(0)->is_CallStaticJava()) {
+        CallStaticJavaNode* csj = arg->in(0)->as_CallStaticJava();
+        if (csj->method() != NULL &&
+            (csj->method()->holder() == C->env()->StringBuffer_klass() ||
+             csj->method()->holder() == C->env()->StringBuilder_klass()) &&
+            csj->method()->name() == ciSymbol::toString_name()) {
+          for (int o = 0; o < concats.length(); o++) {
+            if (c == o) continue;
+            StringConcat* other = concats.at(o);
+            if (other->end() == csj) {
+#ifndef PRODUCT
+              if (PrintOptimizeStringConcat) {
+                tty->print_cr("considering stacked concats");
+              }
+#endif
+
+              StringConcat* merged = sc->merge(other, arg);
+              if (merged->validate_control_flow()) {
+#ifndef PRODUCT
+                if (PrintOptimizeStringConcat) {
+                  tty->print_cr("stacking would succeed");
+                }
+#endif
+                if (c < o) {
+                  concats.remove_at(o);
+                  concats.at_put(c, merged);
+                } else {
+                  concats.remove_at(c);
+                  concats.at_put(o, merged);
+                }
+                goto restart;
+              } else {
+#ifndef PRODUCT
+                if (PrintOptimizeStringConcat) {
+                  tty->print_cr("stacking would fail");
+                }
+#endif
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+
+
+  for (int c = 0; c < concats.length(); c++) {
+    StringConcat* sc = concats.at(c);
+    replace_string_concat(sc);
+  }
+
+  remove_dead_nodes();
+}
+
+void PhaseStringOpts::record_dead_node(Node* dead) {
+  dead_worklist.push(dead);
+}
+
+void PhaseStringOpts::remove_dead_nodes() {
+  // Delete any dead nodes to make things clean enough that escape
+  // analysis doesn't get unhappy.
+  while (dead_worklist.size() > 0) {
+    Node* use = dead_worklist.pop();
+    int opc = use->Opcode();
+    switch (opc) {
+      case Op_Region: {
+        uint i = 1;
+        for (i = 1; i < use->req(); i++) {
+          if (use->in(i) != C->top()) {
+            break;
+          }
+        }
+        if (i >= use->req()) {
+          for (SimpleDUIterator i(use); i.has_next(); i.next()) {
+            Node* m = i.get();
+            if (m->is_Phi()) {
+              dead_worklist.push(m);
+            }
+          }
+          C->gvn_replace_by(use, C->top());
+        }
+        break;
+      }
+      case Op_AddP:
+      case Op_CreateEx: {
+        // Recurisvely clean up references to CreateEx so EA doesn't
+        // get unhappy about the partially collapsed graph.
+        for (SimpleDUIterator i(use); i.has_next(); i.next()) {
+          Node* m = i.get();
+          if (m->is_AddP()) {
+            dead_worklist.push(m);
+          }
+        }
+        C->gvn_replace_by(use, C->top());
+        break;
+      }
+      case Op_Phi:
+        if (use->in(0) == C->top()) {
+          C->gvn_replace_by(use, C->top());
+        }
+        break;
+    }
+  }
+}
+
+
+bool StringConcat::validate_control_flow() {
+  // We found all the calls and arguments now lets see if it's
+  // safe to transform the graph as we would expect.
+
+  // Check to see if this resulted in too many uncommon traps previously
+  if (Compile::current()->too_many_traps(_begin->jvms()->method(), _begin->jvms()->bci(),
+                        Deoptimization::Reason_intrinsic)) {
+    return false;
+  }
+
+  // Walk backwards over the control flow from toString to the
+  // allocation and make sure all the control flow is ok.  This
+  // means it's either going to be eliminated once the calls are
+  // removed or it can safely be transformed into an uncommon
+  // trap.
+
+  int null_check_count = 0;
+  Unique_Node_List ctrl_path;
+
+  assert(_control.contains(_begin), "missing");
+  assert(_control.contains(_end), "missing");
+
+  // Collect the nodes that we know about and will eliminate into ctrl_path
+  for (uint i = 0; i < _control.size(); i++) {
+    // Push the call and it's control projection
+    Node* n = _control.at(i);
+    if (n->is_Allocate()) {
+      AllocateNode* an = n->as_Allocate();
+      InitializeNode* init = an->initialization();
+      ctrl_path.push(init);
+      ctrl_path.push(init->as_Multi()->proj_out(0));
+    }
+    if (n->is_Call()) {
+      CallNode* cn = n->as_Call();
+      ctrl_path.push(cn);
+      ctrl_path.push(cn->proj_out(0));
+      ctrl_path.push(cn->proj_out(0)->unique_out());
+      ctrl_path.push(cn->proj_out(0)->unique_out()->as_Catch()->proj_out(0));
+    } else {
+      ShouldNotReachHere();
+    }
+  }
+
+  // Skip backwards through the control checking for unexpected contro flow
+  Node* ptr = _end;
+  bool fail = false;
+  while (ptr != _begin) {
+    if (ptr->is_Call() && ctrl_path.member(ptr)) {
+      ptr = ptr->in(0);
+    } else if (ptr->is_CatchProj() && ctrl_path.member(ptr)) {
+      ptr = ptr->in(0)->in(0)->in(0);
+      assert(ctrl_path.member(ptr), "should be a known piece of control");
+    } else if (ptr->is_IfTrue()) {
+      IfNode* iff = ptr->in(0)->as_If();
+      BoolNode* b = iff->in(1)->isa_Bool();
+      Node* cmp = b->in(1);
+      Node* v1 = cmp->in(1);
+      Node* v2 = cmp->in(2);
+      Node* otherproj = iff->proj_out(1 - ptr->as_Proj()->_con);
+
+      // Null check of the return of append which can simply be eliminated
+      if (b->_test._test == BoolTest::ne &&
+          v2->bottom_type() == TypePtr::NULL_PTR &&
+          v1->is_Proj() && ctrl_path.member(v1->in(0))) {
+        // NULL check of the return value of the append
+        null_check_count++;
+        if (otherproj->outcnt() == 1) {
+          CallStaticJavaNode* call = otherproj->unique_out()->isa_CallStaticJava();
+          if (call != NULL && call->_name != NULL && strcmp(call->_name, "uncommon_trap") == 0) {
+            ctrl_path.push(call);
+          }
+        }
+        _control.push(ptr);
+        ptr = ptr->in(0)->in(0);
+        continue;
+      }
+
+      // A test which leads to an uncommon trap which should be safe.
+      // Later this trap will be converted into a trap that restarts
+      // at the beginning.
+      if (otherproj->outcnt() == 1) {
+        CallStaticJavaNode* call = otherproj->unique_out()->isa_CallStaticJava();
+        if (call != NULL && call->_name != NULL && strcmp(call->_name, "uncommon_trap") == 0) {
+          // control flow leads to uct so should be ok
+          _uncommon_traps.push(call);
+          ctrl_path.push(call);
+          ptr = ptr->in(0)->in(0);
+          continue;
+        }
+      }
+
+#ifndef PRODUCT
+      // Some unexpected control flow we don't know how to handle.
+      if (PrintOptimizeStringConcat) {
+        tty->print_cr("failing with unknown test");
+        b->dump();
+        cmp->dump();
+        v1->dump();
+        v2->dump();
+        tty->cr();
+      }
+#endif
+      break;
+    } else if (ptr->is_Proj() && ptr->in(0)->is_Initialize()) {
+      ptr = ptr->in(0)->in(0);
+    } else if (ptr->is_Region()) {
+      Node* copy = ptr->as_Region()->is_copy();
+      if (copy != NULL) {
+        ptr = copy;
+        continue;
+      }
+      if (ptr->req() == 3 &&
+          ptr->in(1) != NULL && ptr->in(1)->is_Proj() &&
+          ptr->in(2) != NULL && ptr->in(2)->is_Proj() &&
+          ptr->in(1)->in(0) == ptr->in(2)->in(0) &&
+          ptr->in(1)->in(0) != NULL && ptr->in(1)->in(0)->is_If()) {
+        // Simple diamond.
+        // XXX should check for possibly merging stores.  simple data merges are ok.
+        ptr = ptr->in(1)->in(0)->in(0);
+        continue;
+      }
+#ifndef PRODUCT
+      if (PrintOptimizeStringConcat) {
+        tty->print_cr("fusion would fail for region");
+        _begin->dump();
+        ptr->dump(2);
+      }
+#endif
+      fail = true;
+      break;
+    } else {
+      // other unknown control
+      if (!fail) {
+#ifndef PRODUCT
+        if (PrintOptimizeStringConcat) {
+          tty->print_cr("fusion would fail for");
+          _begin->dump();
+        }
+#endif
+        fail = true;
+      }
+#ifndef PRODUCT
+      if (PrintOptimizeStringConcat) {
+        ptr->dump();
+      }
+#endif
+      ptr = ptr->in(0);
+    }
+  }
+#ifndef PRODUCT
+  if (PrintOptimizeStringConcat && fail) {
+    tty->cr();
+  }
+#endif
+  if (fail) return !fail;
+
+  // Validate that all these results produced are contained within
+  // this cluster of objects.  First collect all the results produced
+  // by calls in the region.
+  _stringopts->_visited.Clear();
+  Node_List worklist;
+  Node* final_result = _end->proj_out(TypeFunc::Parms);
+  for (uint i = 0; i < _control.size(); i++) {
+    CallNode* cnode = _control.at(i)->isa_Call();
+    if (cnode != NULL) {
+      _stringopts->_visited.test_set(cnode->_idx);
+    }
+    Node* result = cnode != NULL ? cnode->proj_out(TypeFunc::Parms) : NULL;
+    if (result != NULL && result != final_result) {
+      worklist.push(result);
+    }
+  }
+
+  Node* last_result = NULL;
+  while (worklist.size() > 0) {
+    Node* result = worklist.pop();
+    if (_stringopts->_visited.test_set(result->_idx))
+      continue;
+    for (SimpleDUIterator i(result); i.has_next(); i.next()) {
+      Node *use = i.get();
+      if (ctrl_path.member(use)) {
+        // already checked this
+        continue;
+      }
+      int opc = use->Opcode();
+      if (opc == Op_CmpP || opc == Op_Node) {
+        ctrl_path.push(use);
+        continue;
+      }
+      if (opc == Op_CastPP || opc == Op_CheckCastPP) {
+        for (SimpleDUIterator j(use); j.has_next(); j.next()) {
+          worklist.push(j.get());
+        }
+        worklist.push(use->in(1));
+        ctrl_path.push(use);
+        continue;
+      }
+#ifndef PRODUCT
+      if (PrintOptimizeStringConcat) {
+        if (result != last_result) {
+          last_result = result;
+          tty->print_cr("extra uses for result:");
+          last_result->dump();
+        }
+        use->dump();
+      }
+#endif
+      fail = true;
+      break;
+    }
+  }
+
+#ifndef PRODUCT
+  if (PrintOptimizeStringConcat && !fail) {
+    ttyLocker ttyl;
+    tty->cr();
+    tty->print("fusion would succeed (%d %d) for ", null_check_count, _uncommon_traps.size());
+    _begin->jvms()->dump_spec(tty); tty->cr();
+    for (int i = 0; i < num_arguments(); i++) {
+      argument(i)->dump();
+    }
+    _control.dump();
+    tty->cr();
+  }
+#endif
+
+  return !fail;
+}
+
+Node* PhaseStringOpts::fetch_static_field(GraphKit& kit, ciField* field) {
+  const TypeKlassPtr* klass_type = TypeKlassPtr::make(field->holder());
+  Node* klass_node = __ makecon(klass_type);
+  BasicType bt = field->layout_type();
+  ciType* field_klass = field->type();
+
+  const Type *type;
+  if( bt == T_OBJECT ) {
+    if (!field->type()->is_loaded()) {
+      type = TypeInstPtr::BOTTOM;
+    } else if (field->is_constant()) {
+      // This can happen if the constant oop is non-perm.
+      ciObject* con = field->constant_value().as_object();
+      // Do not "join" in the previous type; it doesn't add value,
+      // and may yield a vacuous result if the field is of interface type.
+      type = TypeOopPtr::make_from_constant(con)->isa_oopptr();
+      assert(type != NULL, "field singleton type must be consistent");
+    } else {
+      type = TypeOopPtr::make_from_klass(field_klass->as_klass());
+    }
+  } else {
+    type = Type::get_const_basic_type(bt);
+  }
+
+  return kit.make_load(NULL, kit.basic_plus_adr(klass_node, field->offset_in_bytes()),
+                       type, T_OBJECT,
+                       C->get_alias_index(klass_type->add_offset(field->offset_in_bytes())));
+}
+
+Node* PhaseStringOpts::int_stringSize(GraphKit& kit, Node* arg) {
+  RegionNode *final_merge = new (C, 3) RegionNode(3);
+  kit.gvn().set_type(final_merge, Type::CONTROL);
+  Node* final_size = new (C, 3) PhiNode(final_merge, TypeInt::INT);
+  kit.gvn().set_type(final_size, TypeInt::INT);
+
+  IfNode* iff = kit.create_and_map_if(kit.control(),
+                                      __ Bool(__ CmpI(arg, __ intcon(0x80000000)), BoolTest::ne),
+                                      PROB_FAIR, COUNT_UNKNOWN);
+  Node* is_min = __ IfFalse(iff);
+  final_merge->init_req(1, is_min);
+  final_size->init_req(1, __ intcon(11));
+
+  kit.set_control(__ IfTrue(iff));
+  if (kit.stopped()) {
+    final_merge->init_req(2, C->top());
+    final_size->init_req(2, C->top());
+  } else {
+
+    // int size = (i < 0) ? stringSize(-i) + 1 : stringSize(i);
+    RegionNode *r = new (C, 3) RegionNode(3);
+    kit.gvn().set_type(r, Type::CONTROL);
+    Node *phi = new (C, 3) PhiNode(r, TypeInt::INT);
+    kit.gvn().set_type(phi, TypeInt::INT);
+    Node *size = new (C, 3) PhiNode(r, TypeInt::INT);
+    kit.gvn().set_type(size, TypeInt::INT);
+    Node* chk = __ CmpI(arg, __ intcon(0));
+    Node* p = __ Bool(chk, BoolTest::lt);
+    IfNode* iff = kit.create_and_map_if(kit.control(), p, PROB_FAIR, COUNT_UNKNOWN);
+    Node* lessthan = __ IfTrue(iff);
+    Node* greaterequal = __ IfFalse(iff);
+    r->init_req(1, lessthan);
+    phi->init_req(1, __ SubI(__ intcon(0), arg));
+    size->init_req(1, __ intcon(1));
+    r->init_req(2, greaterequal);
+    phi->init_req(2, arg);
+    size->init_req(2, __ intcon(0));
+    kit.set_control(r);
+    C->record_for_igvn(r);
+    C->record_for_igvn(phi);
+    C->record_for_igvn(size);
+
+    // for (int i=0; ; i++)
+    //   if (x <= sizeTable[i])
+    //     return i+1;
+    RegionNode *loop = new (C, 3) RegionNode(3);
+    loop->init_req(1, kit.control());
+    kit.gvn().set_type(loop, Type::CONTROL);
+
+    Node *index = new (C, 3) PhiNode(loop, TypeInt::INT);
+    index->init_req(1, __ intcon(0));
+    kit.gvn().set_type(index, TypeInt::INT);
+    kit.set_control(loop);
+    Node* sizeTable = fetch_static_field(kit, size_table_field);
+
+    Node* value = kit.load_array_element(NULL, sizeTable, index, TypeAryPtr::INTS);
+    C->record_for_igvn(value);
+    Node* limit = __ CmpI(phi, value);
+    Node* limitb = __ Bool(limit, BoolTest::le);
+    IfNode* iff2 = kit.create_and_map_if(kit.control(), limitb, PROB_MIN, COUNT_UNKNOWN);
+    Node* lessEqual = __ IfTrue(iff2);
+    Node* greater = __ IfFalse(iff2);
+
+    loop->init_req(2, greater);
+    index->init_req(2, __ AddI(index, __ intcon(1)));
+
+    kit.set_control(lessEqual);
+    C->record_for_igvn(loop);
+    C->record_for_igvn(index);
+
+    final_merge->init_req(2, kit.control());
+    final_size->init_req(2, __ AddI(__ AddI(index, size), __ intcon(1)));
+  }
+
+  kit.set_control(final_merge);
+  C->record_for_igvn(final_merge);
+  C->record_for_igvn(final_size);
+
+  return final_size;
+}
+
+void PhaseStringOpts::int_getChars(GraphKit& kit, Node* arg, Node* char_array, Node* start, Node* end) {
+  RegionNode *final_merge = new (C, 4) RegionNode(4);
+  kit.gvn().set_type(final_merge, Type::CONTROL);
+  Node *final_mem = PhiNode::make(final_merge, kit.memory(char_adr_idx), Type::MEMORY, TypeAryPtr::CHARS);
+  kit.gvn().set_type(final_mem, Type::MEMORY);
+
+  // need to handle Integer.MIN_VALUE specially because negating doesn't make it positive
+  {
+    // i == MIN_VALUE
+    IfNode* iff = kit.create_and_map_if(kit.control(),
+                                        __ Bool(__ CmpI(arg, __ intcon(0x80000000)), BoolTest::ne),
+                                        PROB_FAIR, COUNT_UNKNOWN);
+
+    Node* old_mem = kit.memory(char_adr_idx);
+
+    kit.set_control(__ IfFalse(iff));
+    if (kit.stopped()) {
+      // Statically not equal to MIN_VALUE so this path is dead
+      final_merge->init_req(3, kit.control());
+    } else {
+      copy_string(kit, __ makecon(TypeInstPtr::make(C->env()->the_min_jint_string())),
+                  char_array, start);
+      final_merge->init_req(3, kit.control());
+      final_mem->init_req(3, kit.memory(char_adr_idx));
+    }
+
+    kit.set_control(__ IfTrue(iff));
+    kit.set_memory(old_mem, char_adr_idx);
+  }
+
+
+  // Simplified version of Integer.getChars
+
+  // int q, r;
+  // int charPos = index;
+  Node* charPos = end;
+
+  // char sign = 0;
+
+  Node* i = arg;
+  Node* sign = __ intcon(0);
+
+  // if (i < 0) {
+  //     sign = '-';
+  //     i = -i;
+  // }
+  {
+    IfNode* iff = kit.create_and_map_if(kit.control(),
+                                        __ Bool(__ CmpI(arg, __ intcon(0)), BoolTest::lt),
+                                        PROB_FAIR, COUNT_UNKNOWN);
+
+    RegionNode *merge = new (C, 3) RegionNode(3);
+    kit.gvn().set_type(merge, Type::CONTROL);
+    i = new (C, 3) PhiNode(merge, TypeInt::INT);
+    kit.gvn().set_type(i, TypeInt::INT);
+    sign = new (C, 3) PhiNode(merge, TypeInt::INT);
+    kit.gvn().set_type(sign, TypeInt::INT);
+
+    merge->init_req(1, __ IfTrue(iff));
+    i->init_req(1, __ SubI(__ intcon(0), arg));
+    sign->init_req(1, __ intcon('-'));
+    merge->init_req(2, __ IfFalse(iff));
+    i->init_req(2, arg);
+    sign->init_req(2, __ intcon(0));
+
+    kit.set_control(merge);
+
+    C->record_for_igvn(merge);
+    C->record_for_igvn(i);
+    C->record_for_igvn(sign);
+  }
+
+  // for (;;) {
+  //     q = i / 10;
+  //     r = i - ((q << 3) + (q << 1));  // r = i-(q*10) ...
+  //     buf [--charPos] = digits [r];
+  //     i = q;
+  //     if (i == 0) break;
+  // }
+
+  {
+    RegionNode *head = new (C, 3) RegionNode(3);
+    head->init_req(1, kit.control());
+    kit.gvn().set_type(head, Type::CONTROL);
+    Node *i_phi = new (C, 3) PhiNode(head, TypeInt::INT);
+    i_phi->init_req(1, i);
+    kit.gvn().set_type(i_phi, TypeInt::INT);
+    charPos = PhiNode::make(head, charPos);
+    kit.gvn().set_type(charPos, TypeInt::INT);
+    Node *mem = PhiNode::make(head, kit.memory(char_adr_idx), Type::MEMORY, TypeAryPtr::CHARS);
+    kit.gvn().set_type(mem, Type::MEMORY);
+    kit.set_control(head);
+    kit.set_memory(mem, char_adr_idx);
+
+    Node* q = __ DivI(kit.null(), i_phi, __ intcon(10));
+    Node* r = __ SubI(i_phi, __ AddI(__ LShiftI(q, __ intcon(3)),
+                                     __ LShiftI(q, __ intcon(1))));
+    Node* m1 = __ SubI(charPos, __ intcon(1));
+    Node* ch = __ AddI(r, __ intcon('0'));
+
+    Node* st = __ store_to_memory(kit.control(), kit.array_element_address(char_array, m1, T_CHAR),
+                                  ch, T_CHAR, char_adr_idx);
+
+
+    IfNode* iff = kit.create_and_map_if(head, __ Bool(__ CmpI(q, __ intcon(0)), BoolTest::ne),
+                                        PROB_FAIR, COUNT_UNKNOWN);
+    Node* ne = __ IfTrue(iff);
+    Node* eq = __ IfFalse(iff);
+
+    head->init_req(2, ne);
+    mem->init_req(2, st);
+    i_phi->init_req(2, q);
+    charPos->init_req(2, m1);
+
+    charPos = m1;
+
+    kit.set_control(eq);
+    kit.set_memory(st, char_adr_idx);
+
+    C->record_for_igvn(head);
+    C->record_for_igvn(mem);
+    C->record_for_igvn(i_phi);
+    C->record_for_igvn(charPos);
+  }
+
+  {
+    // if (sign != 0) {
+    //     buf [--charPos] = sign;
+    // }
+    IfNode* iff = kit.create_and_map_if(kit.control(),
+                                        __ Bool(__ CmpI(sign, __ intcon(0)), BoolTest::ne),
+                                        PROB_FAIR, COUNT_UNKNOWN);
+
+    final_merge->init_req(2, __ IfFalse(iff));
+    final_mem->init_req(2, kit.memory(char_adr_idx));
+
+    kit.set_control(__ IfTrue(iff));
+    if (kit.stopped()) {
+      final_merge->init_req(1, C->top());
+      final_mem->init_req(1, C->top());
+    } else {
+      Node* m1 = __ SubI(charPos, __ intcon(1));
+      Node* st = __ store_to_memory(kit.control(), kit.array_element_address(char_array, m1, T_CHAR),
+                                    sign, T_CHAR, char_adr_idx);
+
+      final_merge->init_req(1, kit.control());
+      final_mem->init_req(1, st);
+    }
+
+    kit.set_control(final_merge);
+    kit.set_memory(final_mem, char_adr_idx);
+
+    C->record_for_igvn(final_merge);
+    C->record_for_igvn(final_mem);
+  }
+}
+
+
+Node* PhaseStringOpts::copy_string(GraphKit& kit, Node* str, Node* char_array, Node* start) {
+  Node* string = str;
+  Node* offset = kit.make_load(NULL,
+                               kit.basic_plus_adr(string, string, java_lang_String::offset_offset_in_bytes()),
+                               TypeInt::INT, T_INT, offset_field_idx);
+  Node* count = kit.make_load(NULL,
+                              kit.basic_plus_adr(string, string, java_lang_String::count_offset_in_bytes()),
+                              TypeInt::INT, T_INT, count_field_idx);
+  const TypeAryPtr*  value_type = TypeAryPtr::make(TypePtr::NotNull,
+                                                   TypeAry::make(TypeInt::CHAR,TypeInt::POS),
+                                                   ciTypeArrayKlass::make(T_CHAR), true, 0);
+  Node* value = kit.make_load(NULL,
+                              kit.basic_plus_adr(string, string, java_lang_String::value_offset_in_bytes()),
+                              value_type, T_OBJECT, value_field_idx);
+
+  // copy the contents
+  if (offset->is_Con() && count->is_Con() && value->is_Con() && count->get_int() < unroll_string_copy_length) {
+    // For small constant strings just emit individual stores.
+    // A length of 6 seems like a good space/speed tradeof.
+    int c = count->get_int();
+    int o = offset->get_int();
+    const TypeOopPtr* t = kit.gvn().type(value)->isa_oopptr();
+    ciTypeArray* value_array = t->const_oop()->as_type_array();
+    for (int e = 0; e < c; e++) {
+      __ store_to_memory(kit.control(), kit.array_element_address(char_array, start, T_CHAR),
+                         __ intcon(value_array->char_at(o + e)), T_CHAR, char_adr_idx);
+      start = __ AddI(start, __ intcon(1));
+    }
+  } else {
+    Node* src_ptr = kit.array_element_address(value, offset, T_CHAR);
+    Node* dst_ptr = kit.array_element_address(char_array, start, T_CHAR);
+    Node* c = count;
+    Node* extra = NULL;
+#ifdef _LP64
+    c = __ ConvI2L(c);
+    extra = C->top();
+#endif
+    Node* call = kit.make_runtime_call(GraphKit::RC_LEAF|GraphKit::RC_NO_FP,
+                                       OptoRuntime::fast_arraycopy_Type(),
+                                       CAST_FROM_FN_PTR(address, StubRoutines::jshort_disjoint_arraycopy()),
+                                       "jshort_disjoint_arraycopy", TypeAryPtr::CHARS,
+                                       src_ptr, dst_ptr, c, extra);
+    start = __ AddI(start, count);
+  }
+  return start;
+}
+
+
+void PhaseStringOpts::replace_string_concat(StringConcat* sc) {
+  // Log a little info about the transformation
+  sc->maybe_log_transform();
+
+  // pull the JVMState of the allocation into a SafePointNode to serve as
+  // as a shim for the insertion of the new code.
+  JVMState* jvms     = sc->begin()->jvms()->clone_shallow(C);
+  uint size = sc->begin()->req();
+  SafePointNode* map = new (C, size) SafePointNode(size, jvms);
+
+  // copy the control and memory state from the final call into our
+  // new starting state.  This allows any preceeding tests to feed
+  // into the new section of code.
+  for (uint i1 = 0; i1 < TypeFunc::Parms; i1++) {
+    map->init_req(i1, sc->end()->in(i1));
+  }
+  // blow away old allocation arguments
+  for (uint i1 = TypeFunc::Parms; i1 < jvms->debug_start(); i1++) {
+    map->init_req(i1, C->top());
+  }
+  // Copy the rest of the inputs for the JVMState
+  for (uint i1 = jvms->debug_start(); i1 < sc->begin()->req(); i1++) {
+    map->init_req(i1, sc->begin()->in(i1));
+  }
+  // Make sure the memory state is a MergeMem for parsing.
+  if (!map->in(TypeFunc::Memory)->is_MergeMem()) {
+    map->set_req(TypeFunc::Memory, MergeMemNode::make(C, map->in(TypeFunc::Memory)));
+  }
+
+  jvms->set_map(map);
+  map->ensure_stack(jvms, jvms->method()->max_stack());
+
+
+  // disconnect all the old StringBuilder calls from the graph
+  sc->eliminate_unneeded_control();
+
+  // At this point all the old work has been completely removed from
+  // the graph and the saved JVMState exists at the point where the
+  // final toString call used to be.
+  GraphKit kit(jvms);
+
+  // There may be uncommon traps which are still using the
+  // intermediate states and these need to be rewritten to point at
+  // the JVMState at the beginning of the transformation.
+  sc->convert_uncommon_traps(kit, jvms);
+
+  // Now insert the logic to compute the size of the string followed
+  // by all the logic to construct array and resulting string.
+
+  Node* null_string = __ makecon(TypeInstPtr::make(C->env()->the_null_string()));
+
+  // Create a region for the overflow checks to merge into.
+  int args = MAX2(sc->num_arguments(), 1);
+  RegionNode* overflow = new (C, args) RegionNode(args);
+  kit.gvn().set_type(overflow, Type::CONTROL);
+
+  // Create a hook node to hold onto the individual sizes since they
+  // are need for the copying phase.
+  Node* string_sizes = new (C, args) Node(args);
+
+  Node* length = __ intcon(0);
+  for (int argi = 0; argi < sc->num_arguments(); argi++) {
+    Node* arg = sc->argument(argi);
+    switch (sc->mode(argi)) {
+      case StringConcat::IntMode: {
+        Node* string_size = int_stringSize(kit, arg);
+
+        // accumulate total
+        length = __ AddI(length, string_size);
+
+        // Cache this value for the use by int_toString
+        string_sizes->init_req(argi, string_size);
+        break;
+      }
+      case StringConcat::StringMode: {
+        const Type* type = kit.gvn().type(arg);
+        if (type == TypePtr::NULL_PTR) {
+          // replace the argument with the null checked version
+          arg = null_string;
+          sc->set_argument(argi, arg);
+        } else if (!type->higher_equal(TypeInstPtr::NOTNULL)) {
+          // s = s != null ? s : "null";
+          // length = length + (s.count - s.offset);
+          RegionNode *r = new (C, 3) RegionNode(3);
+          kit.gvn().set_type(r, Type::CONTROL);
+          Node *phi = new (C, 3) PhiNode(r, type->join(TypeInstPtr::NOTNULL));
+          kit.gvn().set_type(phi, phi->bottom_type());
+          Node* p = __ Bool(__ CmpP(arg, kit.null()), BoolTest::ne);
+          IfNode* iff = kit.create_and_map_if(kit.control(), p, PROB_MIN, COUNT_UNKNOWN);
+          Node* notnull = __ IfTrue(iff);
+          Node* isnull =  __ IfFalse(iff);
+          r->init_req(1, notnull);
+          phi->init_req(1, arg);
+          r->init_req(2, isnull);
+          phi->init_req(2, null_string);
+          kit.set_control(r);
+          C->record_for_igvn(r);
+          C->record_for_igvn(phi);
+          // replace the argument with the null checked version
+          arg = phi;
+          sc->set_argument(argi, arg);
+        }
+        //         Node* offset = kit.make_load(NULL, kit.basic_plus_adr(arg, arg, offset_offset),
+        //                                      TypeInt::INT, T_INT, offset_field_idx);
+        Node* count = kit.make_load(NULL, kit.basic_plus_adr(arg, arg, java_lang_String::count_offset_in_bytes()),
+                                    TypeInt::INT, T_INT, count_field_idx);
+        length = __ AddI(length, count);
+        string_sizes->init_req(argi, NULL);
+        break;
+      }
+      case StringConcat::CharMode: {
+        // one character only
+        length = __ AddI(length, __ intcon(1));
+        break;
+      }
+      default:
+        ShouldNotReachHere();
+    }
+    if (argi > 0) {
+      // Check that the sum hasn't overflowed
+      IfNode* iff = kit.create_and_map_if(kit.control(),
+                                          __ Bool(__ CmpI(length, __ intcon(0)), BoolTest::lt),
+                                          PROB_MIN, COUNT_UNKNOWN);
+      kit.set_control(__ IfFalse(iff));
+      overflow->set_req(argi, __ IfTrue(iff));
+    }
+  }
+
+  {
+    // Hook
+    PreserveJVMState pjvms(&kit);
+    kit.set_control(overflow);
+    kit.uncommon_trap(Deoptimization::Reason_intrinsic,
+                      Deoptimization::Action_make_not_entrant);
+  }
+
+  // length now contains the number of characters needed for the
+  // char[] so create a new AllocateArray for the char[]
+  Node* char_array = NULL;
+  {
+    PreserveReexecuteState preexecs(&kit);
+    // The original jvms is for an allocation of either a String or
+    // StringBuffer so no stack adjustment is necessary for proper
+    // reexecution.  If we deoptimize in the slow path the bytecode
+    // will be reexecuted and the char[] allocation will be thrown away.
+    kit.jvms()->set_should_reexecute(true);
+    char_array = kit.new_array(__ makecon(TypeKlassPtr::make(ciTypeArrayKlass::make(T_CHAR))),
+                               length, 1);
+  }
+
+  // Mark the allocation so that zeroing is skipped since the code
+  // below will overwrite the entire array
+  AllocateArrayNode* char_alloc = AllocateArrayNode::Ideal_array_allocation(char_array, _gvn);
+  char_alloc->maybe_set_complete(_gvn);
+
+  // Now copy the string representations into the final char[]
+  Node* start = __ intcon(0);
+  for (int argi = 0; argi < sc->num_arguments(); argi++) {
+    Node* arg = sc->argument(argi);
+    switch (sc->mode(argi)) {
+      case StringConcat::IntMode: {
+        Node* end = __ AddI(start, string_sizes->in(argi));
+        // getChars words backwards so pass the ending point as well as the start
+        int_getChars(kit, arg, char_array, start, end);
+        start = end;
+        break;
+      }
+      case StringConcat::StringMode: {
+        start = copy_string(kit, arg, char_array, start);
+        break;
+      }
+      case StringConcat::CharMode: {
+        __ store_to_memory(kit.control(), kit.array_element_address(char_array, start, T_CHAR),
+                           arg, T_CHAR, char_adr_idx);
+        start = __ AddI(start, __ intcon(1));
+        break;
+      }
+      default:
+        ShouldNotReachHere();
+    }
+  }
+
+  // If we're not reusing an existing String allocation then allocate one here.
+  Node* result = sc->string_alloc();
+  if (result == NULL) {
+    PreserveReexecuteState preexecs(&kit);
+    // The original jvms is for an allocation of either a String or
+    // StringBuffer so no stack adjustment is necessary for proper
+    // reexecution.
+    kit.jvms()->set_should_reexecute(true);
+    result = kit.new_instance(__ makecon(TypeKlassPtr::make(C->env()->String_klass())));
+  }
+
+  // Intialize the string
+  kit.store_to_memory(kit.control(), kit.basic_plus_adr(result, java_lang_String::offset_offset_in_bytes()),
+                      __ intcon(0), T_INT, offset_field_idx);
+  kit.store_to_memory(kit.control(), kit.basic_plus_adr(result, java_lang_String::count_offset_in_bytes()),
+                      length, T_INT, count_field_idx);
+  kit.store_to_memory(kit.control(), kit.basic_plus_adr(result, java_lang_String::value_offset_in_bytes()),
+                      char_array, T_OBJECT, value_field_idx);
+
+  // hook up the outgoing control and result
+  kit.replace_call(sc->end(), result);
+
+  // Unhook any hook nodes
+  string_sizes->disconnect_inputs(NULL);
+  sc->cleanup();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/opto/stringopts.hpp	Wed Jul 05 17:04:56 2017 +0200
@@ -0,0 +1,83 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ *
+ */
+
+class StringConcat;
+
+class PhaseStringOpts : public Phase {
+  friend class StringConcat;
+
+ private:
+  PhaseGVN* _gvn;
+
+  // List of dead nodes to clean up aggressively at the end
+  Unique_Node_List dead_worklist;
+
+  // Memory slices needed for code gen
+  int char_adr_idx;
+  int value_field_idx;
+  int count_field_idx;
+  int offset_field_idx;
+
+  // Integer.sizeTable - used for int to String conversion
+  ciField* size_table_field;
+
+  // A set for use by various stages
+  VectorSet _visited;
+
+  // Collect a list of all SB.toString calls
+  Node_List collect_toString_calls();
+
+  // Examine the use of the SB alloc to see if it can be replace with
+  // a single string construction.
+  StringConcat* build_candidate(CallStaticJavaNode* call);
+
+  // Replace all the SB calls in concat with an optimization String allocation
+  void replace_string_concat(StringConcat* concat);
+
+  // Load the value of a static field, performing any constant folding.
+  Node* fetch_static_field(GraphKit& kit, ciField* field);
+
+  // Compute the number of characters required to represent the int value
+  Node* int_stringSize(GraphKit& kit, Node* value);
+
+  // Copy the characters representing value into char_array starting at start
+  void int_getChars(GraphKit& kit, Node* value, Node* char_array, Node* start, Node* end);
+
+  // Copy of the contents of the String str into char_array starting at index start.
+  Node* copy_string(GraphKit& kit, Node* str, Node* char_array, Node* start);
+
+  // Clean up any leftover nodes
+  void record_dead_node(Node* node);
+  void remove_dead_nodes();
+
+  PhaseGVN* gvn() { return _gvn; }
+
+  enum {
+    // max length of constant string copy unrolling in copy_string
+    unroll_string_copy_length = 6
+  };
+
+ public:
+  PhaseStringOpts(PhaseGVN* gvn, Unique_Node_List* worklist);
+};
--- a/hotspot/src/share/vm/opto/superword.cpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/share/vm/opto/superword.cpp	Wed Jul 05 17:04:56 2017 +0200
@@ -1921,6 +1921,11 @@
   }
   // Match AddP(base, AddP(ptr, k*iv [+ invariant]), constant)
   Node* base = adr->in(AddPNode::Base);
+  //unsafe reference could not be aligned appropriately without runtime checking
+  if (base == NULL || base->bottom_type() == Type::TOP) {
+    assert(!valid(), "unsafe access");
+    return;
+  }
   for (int i = 0; i < 3; i++) {
     if (!scaled_iv_plus_offset(adr->in(AddPNode::Offset))) {
       assert(!valid(), "too complex");
--- a/hotspot/src/share/vm/opto/type.hpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/share/vm/opto/type.hpp	Wed Jul 05 17:04:56 2017 +0200
@@ -847,9 +847,6 @@
   // Constant pointer to array
   static const TypeAryPtr *make( PTR ptr, ciObject* o, const TypeAry *ary, ciKlass* k, bool xk, int offset, int instance_id = InstanceBot);
 
-  // Convenience
-  static const TypeAryPtr *make(ciObject* o);
-
   // Return a 'ptr' version of this type
   virtual const Type *cast_to_ptr_type(PTR ptr) const;
 
--- a/hotspot/src/share/vm/prims/jni.cpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/share/vm/prims/jni.cpp	Wed Jul 05 17:04:56 2017 +0200
@@ -3231,6 +3231,21 @@
   jint result = JNI_ERR;
   DT_RETURN_MARK(CreateJavaVM, jint, (const jint&)result);
 
+  // We're about to use Atomic::xchg for synchronization.  Some Zero
+  // platforms use the GCC builtin __sync_lock_test_and_set for this,
+  // but __sync_lock_test_and_set is not guaranteed to do what we want
+  // on all architectures.  So we check it works before relying on it.
+#if defined(ZERO) && defined(ASSERT)
+  {
+    jint a = 0xcafebabe;
+    jint b = Atomic::xchg(0xdeadbeef, &a);
+    void *c = &a;
+    void *d = Atomic::xchg_ptr(&b, &c);
+    assert(a == 0xdeadbeef && b == (jint) 0xcafebabe, "Atomic::xchg() works");
+    assert(c == &b && d == &a, "Atomic::xchg_ptr() works");
+  }
+#endif // ZERO && ASSERT
+
   // At the moment it's only possible to have one Java VM,
   // since some of the runtime state is in global variables.
 
--- a/hotspot/src/share/vm/prims/jvm.cpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/share/vm/prims/jvm.cpp	Wed Jul 05 17:04:56 2017 +0200
@@ -1318,19 +1318,20 @@
     return NULL;
   }
 
-  symbolOop simple_name = NULL;
+  bool inner_is_member = false;
   klassOop outer_klass
     = instanceKlass::cast(java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(ofClass))
-                          )->compute_enclosing_class(simple_name, CHECK_NULL);
+                          )->compute_enclosing_class(&inner_is_member, CHECK_NULL);
   if (outer_klass == NULL)  return NULL;  // already a top-level class
-  if (simple_name == NULL)  return NULL;  // an anonymous class (inside a method)
+  if (!inner_is_member)  return NULL;     // an anonymous class (inside a method)
   return (jclass) JNIHandles::make_local(env, Klass::cast(outer_klass)->java_mirror());
 }
 JVM_END
 
 // should be in instanceKlass.cpp, but is here for historical reasons
 klassOop instanceKlass::compute_enclosing_class_impl(instanceKlassHandle k,
-                                                     symbolOop& simple_name_result, TRAPS) {
+                                                     bool* inner_is_member,
+                                                     TRAPS) {
   Thread* thread = THREAD;
   const int inner_class_info_index = inner_class_inner_class_info_offset;
   const int outer_class_info_index = inner_class_outer_class_info_offset;
@@ -1347,8 +1348,7 @@
   bool found = false;
   klassOop ok;
   instanceKlassHandle outer_klass;
-  bool inner_is_member = false;
-  int simple_name_index = 0;
+  *inner_is_member = false;
 
   // Find inner_klass attribute
   for (int i = 0; i < i_length && !found; i += inner_class_next_offset) {
@@ -1364,8 +1364,7 @@
         if (found && ooff != 0) {
           ok = i_cp->klass_at(ooff, CHECK_NULL);
           outer_klass = instanceKlassHandle(thread, ok);
-          simple_name_index = noff;
-          inner_is_member = true;
+          *inner_is_member = true;
         }
       }
     }
@@ -1377,7 +1376,7 @@
     if (encl_method_class_idx != 0) {
       ok = i_cp->klass_at(encl_method_class_idx, CHECK_NULL);
       outer_klass = instanceKlassHandle(thread, ok);
-      inner_is_member = false;
+      *inner_is_member = false;
     }
   }
 
@@ -1387,9 +1386,7 @@
   // Throws an exception if outer klass has not declared k as an inner klass
   // We need evidence that each klass knows about the other, or else
   // the system could allow a spoof of an inner class to gain access rights.
-  Reflection::check_for_inner_class(outer_klass, k, inner_is_member, CHECK_NULL);
-
-  simple_name_result = (inner_is_member ? i_cp->symbol_at(simple_name_index) : symbolOop(NULL));
+  Reflection::check_for_inner_class(outer_klass, k, *inner_is_member, CHECK_NULL);
   return outer_klass();
 }
 
@@ -2257,10 +2254,8 @@
   switch (cp->tag_at(cp_index).value()) {
     case JVM_CONSTANT_InterfaceMethodref:
     case JVM_CONSTANT_Methodref:
+    case JVM_CONSTANT_NameAndType:  // for invokedynamic
       return cp->uncached_name_ref_at(cp_index)->as_utf8();
-    case JVM_CONSTANT_NameAndType:
-      // for invokedynamic
-      return cp->nt_name_ref_at(cp_index)->as_utf8();
     default:
       fatal("JVM_GetCPMethodNameUTF: illegal constant");
   }
@@ -2277,10 +2272,8 @@
   switch (cp->tag_at(cp_index).value()) {
     case JVM_CONSTANT_InterfaceMethodref:
     case JVM_CONSTANT_Methodref:
+    case JVM_CONSTANT_NameAndType:  // for invokedynamic
       return cp->uncached_signature_ref_at(cp_index)->as_utf8();
-    case JVM_CONSTANT_NameAndType:
-      // for invokedynamic
-      return cp->nt_signature_ref_at(cp_index)->as_utf8();
     default:
       fatal("JVM_GetCPMethodSignatureUTF: illegal constant");
   }
--- a/hotspot/src/share/vm/prims/jvmtiEnv.cpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/share/vm/prims/jvmtiEnv.cpp	Wed Jul 05 17:04:56 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright 2003-2007 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2003-2009 Sun Microsystems, Inc.  All Rights Reserved.
  * 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,15 +32,15 @@
  // FIXLATER: hook into JvmtiTrace
 #define TraceJVMTICalls false
 
-JvmtiEnv::JvmtiEnv() : JvmtiEnvBase() {
+JvmtiEnv::JvmtiEnv(jint version) : JvmtiEnvBase(version) {
 }
 
 JvmtiEnv::~JvmtiEnv() {
 }
 
 JvmtiEnv*
-JvmtiEnv::create_a_jvmti() {
-  return new JvmtiEnv();
+JvmtiEnv::create_a_jvmti(jint version) {
+  return new JvmtiEnv(version);
 }
 
 // VM operation class to copy jni function table at safepoint.
@@ -411,8 +411,15 @@
   if (phase == JVMTI_PHASE_ONLOAD) {
     Arguments::append_sysclasspath(segment);
     return JVMTI_ERROR_NONE;
-  } else {
-    assert(phase == JVMTI_PHASE_LIVE, "sanity check");
+  } else if (use_version_1_0_semantics()) {
+    // This JvmtiEnv requested version 1.0 semantics and this function
+    // is only allowed in the ONLOAD phase in version 1.0 so we need to
+    // return an error here.
+    return JVMTI_ERROR_WRONG_PHASE;
+  } else if (phase == JVMTI_PHASE_LIVE) {
+    // The phase is checked by the wrapper that called this function,
+    // but this thread could be racing with the thread that is
+    // terminating the VM so we check one more time.
 
     // create the zip entry
     ClassPathZipEntry* zip_entry = ClassLoader::create_class_path_zip_entry(segment);
@@ -433,6 +440,8 @@
     }
     ClassLoader::add_to_list(zip_entry);
     return JVMTI_ERROR_NONE;
+  } else {
+    return JVMTI_ERROR_WRONG_PHASE;
   }
 
 } /* end AddToBootstrapClassLoaderSearch */
@@ -451,11 +460,12 @@
       }
     }
     return JVMTI_ERROR_NONE;
-  } else {
+  } else if (phase == JVMTI_PHASE_LIVE) {
+    // The phase is checked by the wrapper that called this function,
+    // but this thread could be racing with the thread that is
+    // terminating the VM so we check one more time.
     HandleMark hm;
 
-    assert(phase == JVMTI_PHASE_LIVE, "sanity check");
-
     // create the zip entry (which will open the zip file and hence
     // check that the segment is indeed a zip file).
     ClassPathZipEntry* zip_entry = ClassLoader::create_class_path_zip_entry(segment);
@@ -504,6 +514,8 @@
     }
 
     return JVMTI_ERROR_NONE;
+  } else {
+    return JVMTI_ERROR_WRONG_PHASE;
   }
 } /* end AddToSystemClassLoaderSearch */
 
@@ -2863,6 +2875,14 @@
 // is_obsolete_ptr - pre-checked for NULL
 jvmtiError
 JvmtiEnv::IsMethodObsolete(methodOop method_oop, jboolean* is_obsolete_ptr) {
+  if (use_version_1_0_semantics() &&
+      get_capabilities()->can_redefine_classes == 0) {
+    // This JvmtiEnv requested version 1.0 semantics and this function
+    // requires the can_redefine_classes capability in version 1.0 so
+    // we need to return an error here.
+    return JVMTI_ERROR_MUST_POSSESS_CAPABILITY;
+  }
+
   if (method_oop == NULL || method_oop->is_obsolete()) {
     *is_obsolete_ptr = true;
   } else {
--- a/hotspot/src/share/vm/prims/jvmtiEnvBase.cpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/share/vm/prims/jvmtiEnvBase.cpp	Wed Jul 05 17:04:56 2017 +0200
@@ -123,7 +123,26 @@
 }
 
 
-JvmtiEnvBase::JvmtiEnvBase() : _env_event_enable() {
+bool
+JvmtiEnvBase::use_version_1_0_semantics() {
+  int major, minor, micro;
+
+  JvmtiExport::decode_version_values(_version, &major, &minor, &micro);
+  return major == 1 && minor == 0;  // micro version doesn't matter here
+}
+
+
+bool
+JvmtiEnvBase::use_version_1_1_semantics() {
+  int major, minor, micro;
+
+  JvmtiExport::decode_version_values(_version, &major, &minor, &micro);
+  return major == 1 && minor == 1;  // micro version doesn't matter here
+}
+
+
+JvmtiEnvBase::JvmtiEnvBase(jint version) : _env_event_enable() {
+  _version = version;
   _env_local_storage = NULL;
   _tag_map = NULL;
   _native_method_prefix_count = 0;
--- a/hotspot/src/share/vm/prims/jvmtiEnvBase.hpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/share/vm/prims/jvmtiEnvBase.hpp	Wed Jul 05 17:04:56 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright 2003-2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2003-2009 Sun Microsystems, Inc.  All Rights Reserved.
  * 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,6 +76,7 @@
 
   jvmtiEnv _jvmti_external;
   jint _magic;
+  jint _version;  // version value passed to JNI GetEnv()
   JvmtiEnvBase* _next;
   bool _is_retransformable;
   const void *_env_local_storage;     // per env agent allocated data.
@@ -91,7 +92,7 @@
   int    _native_method_prefix_count;
 
  protected:
-  JvmtiEnvBase();
+  JvmtiEnvBase(jint version);
   ~JvmtiEnvBase();
   void dispose();
   void env_dispose();
@@ -122,6 +123,9 @@
 
   bool is_valid();
 
+  bool use_version_1_0_semantics();  // agent asked for version 1.0
+  bool use_version_1_1_semantics();  // agent asked for version 1.1
+
   bool is_retransformable()                        { return _is_retransformable; }
 
   static ByteSize jvmti_external_offset() {
--- a/hotspot/src/share/vm/prims/jvmtiExport.cpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/share/vm/prims/jvmtiExport.cpp	Wed Jul 05 17:04:56 2017 +0200
@@ -319,7 +319,27 @@
 
 jint
 JvmtiExport::get_jvmti_interface(JavaVM *jvm, void **penv, jint version) {
-  /* To Do: add version checks */
+  // The JVMTI_VERSION_INTERFACE_JVMTI part of the version number
+  // has already been validated in JNI GetEnv().
+  int major, minor, micro;
+
+  // micro version doesn't matter here (yet?)
+  decode_version_values(version, &major, &minor, &micro);
+  switch (major) {
+  case 1:
+      switch (minor) {
+      case 0:  // version 1.0.<micro> is recognized
+      case 1:  // version 1.1.<micro> is recognized
+          break;
+
+      default:
+          return JNI_EVERSION;  // unsupported minor version number
+      }
+      break;
+
+  default:
+      return JNI_EVERSION;  // unsupported major version number
+  }
 
   if (JvmtiEnv::get_phase() == JVMTI_PHASE_LIVE) {
     JavaThread* current_thread = (JavaThread*) ThreadLocalStorage::thread();
@@ -328,13 +348,13 @@
     __ENTRY(jvmtiEnv*, JvmtiExport::get_jvmti_interface, current_thread)
     debug_only(VMNativeEntryWrapper __vew;)
 
-    JvmtiEnv *jvmti_env = JvmtiEnv::create_a_jvmti();
+    JvmtiEnv *jvmti_env = JvmtiEnv::create_a_jvmti(version);
     *penv = jvmti_env->jvmti_external();  // actual type is jvmtiEnv* -- not to be confused with JvmtiEnv*
     return JNI_OK;
 
   } else if (JvmtiEnv::get_phase() == JVMTI_PHASE_ONLOAD) {
     // not live, no thread to transition
-    JvmtiEnv *jvmti_env = JvmtiEnv::create_a_jvmti();
+    JvmtiEnv *jvmti_env = JvmtiEnv::create_a_jvmti(version);
     *penv = jvmti_env->jvmti_external();  // actual type is jvmtiEnv* -- not to be confused with JvmtiEnv*
     return JNI_OK;
 
@@ -345,6 +365,15 @@
   }
 }
 
+
+void
+JvmtiExport::decode_version_values(jint version, int * major, int * minor,
+                                   int * micro) {
+  *major = (version & JVMTI_VERSION_MASK_MAJOR) >> JVMTI_VERSION_SHIFT_MAJOR;
+  *minor = (version & JVMTI_VERSION_MASK_MINOR) >> JVMTI_VERSION_SHIFT_MINOR;
+  *micro = (version & JVMTI_VERSION_MASK_MICRO) >> JVMTI_VERSION_SHIFT_MICRO;
+}
+
 void JvmtiExport::enter_primordial_phase() {
   JvmtiEnvBase::set_phase(JVMTI_PHASE_PRIMORDIAL);
 }
--- a/hotspot/src/share/vm/prims/jvmtiExport.hpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/share/vm/prims/jvmtiExport.hpp	Wed Jul 05 17:04:56 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright 1998-2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 1998-2009 Sun Microsystems, Inc.  All Rights Reserved.
  * 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,6 +236,8 @@
   static bool is_jvmti_version(jint version)                      { return (version & JVMTI_VERSION_MASK) == JVMTI_VERSION_VALUE; }
   static bool is_jvmdi_version(jint version)                      { return (version & JVMTI_VERSION_MASK) == JVMDI_VERSION_VALUE; }
   static jint get_jvmti_interface(JavaVM *jvm, void **penv, jint version);
+  static void decode_version_values(jint version, int * major, int * minor,
+                                    int * micro);
 
   // single stepping management methods
   static void at_single_stepping_point(JavaThread *thread, methodOop method, address location) KERNEL_RETURN;
--- a/hotspot/src/share/vm/prims/jvmtiHpp.xsl	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/share/vm/prims/jvmtiHpp.xsl	Wed Jul 05 17:04:56 2017 +0200
@@ -1,6 +1,6 @@
 <?xml version="1.0"?> 
 <!--
- Copyright 2002-2005 Sun Microsystems, Inc.  All Rights Reserved.
+ Copyright 2002-2009 Sun Microsystems, Inc.  All Rights Reserved.
  DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 
  This code is free software; you can redistribute it and/or modify it
@@ -48,12 +48,12 @@
 
 private:
     
-    JvmtiEnv();
+    JvmtiEnv(jint version);
     ~JvmtiEnv();
 
 public:
 
-    static JvmtiEnv* create_a_jvmti();
+    static JvmtiEnv* create_a_jvmti(jint version);
 
 </xsl:text>
   <xsl:apply-templates select="functionsection"/>
--- a/hotspot/src/share/vm/prims/jvmtiManageCapabilities.cpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/share/vm/prims/jvmtiManageCapabilities.cpp	Wed Jul 05 17:04:56 2017 +0200
@@ -115,8 +115,10 @@
   jvmtiCapabilities jc;
 
   memset(&jc, 0, sizeof(jc));
+#ifndef CC_INTERP
   jc.can_pop_frame = 1;
   jc.can_force_early_return = 1;
+#endif // !CC_INTERP
   jc.can_get_source_debug_extension = 1;
   jc.can_access_local_variables = 1;
   jc.can_maintain_original_method_order = 1;
--- a/hotspot/src/share/vm/prims/methodHandles.cpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/share/vm/prims/methodHandles.cpp	Wed Jul 05 17:04:56 2017 +0200
@@ -2347,9 +2347,9 @@
 JVM_ENTRY(void, MH_linkCallSite(JNIEnv *env, jobject igcls, jobject site_jh, jobject target_jh)) {
   // No special action required, yet.
   oop site_oop = JNIHandles::resolve(site_jh);
-  if (site_oop == NULL || site_oop->klass() != SystemDictionary::CallSiteImpl_klass())
+  if (site_oop == NULL || site_oop->klass() != SystemDictionary::CallSite_klass())
     THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), "call site");
-  sun_dyn_CallSiteImpl::set_target(site_oop, JNIHandles::resolve(target_jh));
+  java_dyn_CallSite::set_target(site_oop, JNIHandles::resolve(target_jh));
 }
 JVM_END
 
@@ -2365,6 +2365,7 @@
 #define OBJ   LANG"Object;"
 #define CLS   LANG"Class;"
 #define STRG  LANG"String;"
+#define CST   JDYN"CallSite;"
 #define MT    JDYN"MethodType;"
 #define MH    JDYN"MethodHandle;"
 #define MHI   IDYN"MethodHandleImpl;"
@@ -2372,7 +2373,6 @@
 #define AMH   IDYN"AdapterMethodHandle;"
 #define BMH   IDYN"BoundMethodHandle;"
 #define DMH   IDYN"DirectMethodHandle;"
-#define CSTI  IDYN"CallSiteImpl;"
 
 #define CC (char*)  /*cast a literal from (const char*)*/
 #define FN_PTR(f) CAST_FROM_FN_PTR(void*, &f)
@@ -2398,7 +2398,7 @@
 
 // More entry points specifically for EnableInvokeDynamic.
 static JNINativeMethod methods2[] = {
-  {CC"linkCallSite",            CC"("CSTI MH")V",               FN_PTR(MH_linkCallSite)}
+  {CC"linkCallSite",            CC"("CST MH")V",                FN_PTR(MH_linkCallSite)}
 };
 
 
--- a/hotspot/src/share/vm/runtime/arguments.cpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/share/vm/runtime/arguments.cpp	Wed Jul 05 17:04:56 2017 +0200
@@ -37,7 +37,6 @@
 const char*  Arguments::_gc_log_filename        = NULL;
 bool   Arguments::_has_profile                  = false;
 bool   Arguments::_has_alloc_profile            = false;
-uintx  Arguments::_initial_heap_size            = 0;
 uintx  Arguments::_min_heap_size                = 0;
 Arguments::Mode Arguments::_mode                = _mixed;
 bool   Arguments::_java_compiler                = false;
@@ -182,6 +181,9 @@
   { "ProcessingToTenuringRatio",     JDK_Version::jdk(5), JDK_Version::jdk(7) },
   { "MinTrainLength",                JDK_Version::jdk(5), JDK_Version::jdk(7) },
   { "AppendRatio",         JDK_Version::jdk_update(6,10), JDK_Version::jdk(7) },
+  { "DefaultMaxRAM",       JDK_Version::jdk_update(6,18), JDK_Version::jdk(7) },
+  { "DefaultInitialRAMFraction",
+                           JDK_Version::jdk_update(6,18), JDK_Version::jdk(7) },
   { NULL, JDK_Version(0), JDK_Version(0) }
 };
 
@@ -555,6 +557,10 @@
   if (!is_neg && CommandLineFlags::uintxAtPut(name, &uintx_v, origin)) {
     return true;
   }
+  uint64_t uint64_t_v = (uint64_t) v;
+  if (!is_neg && CommandLineFlags::uint64_tAtPut(name, &uint64_t_v, origin)) {
+    return true;
+  }
   return false;
 }
 
@@ -947,7 +953,7 @@
 // UseParNewGC and not explicitly set ParallelGCThreads we
 // set it, unless this is a single cpu machine.
 void Arguments::set_parnew_gc_flags() {
-  assert(!UseSerialGC && !UseParallelGC && !UseG1GC,
+  assert(!UseSerialGC && !UseParallelOldGC && !UseParallelGC && !UseG1GC,
          "control point invariant");
   assert(UseParNewGC, "Error");
 
@@ -960,13 +966,13 @@
   if (ParallelGCThreads == 0) {
     FLAG_SET_DEFAULT(ParallelGCThreads,
                      Abstract_VM_Version::parallel_worker_threads());
-    if (FLAG_IS_DEFAULT(ParallelGCThreads) && ParallelGCThreads == 1) {
+    if (ParallelGCThreads == 1) {
       FLAG_SET_DEFAULT(UseParNewGC, false);
+      FLAG_SET_DEFAULT(ParallelGCThreads, 0);
     }
   }
-  if (!UseParNewGC) {
-    FLAG_SET_DEFAULT(ParallelGCThreads, 0);
-  } else {
+  if (UseParNewGC) {
+    // CDS doesn't work with ParNew yet
     no_shared_spaces();
 
     // By default YoungPLABSize and OldPLABSize are set to 4096 and 1024 respectively,
@@ -980,7 +986,7 @@
       FLAG_SET_DEFAULT(OldPLABSize, (intx)1024);
     }
 
-    // AlwaysTenure flag should make ParNew to promote all at first collection.
+    // AlwaysTenure flag should make ParNew promote all at first collection.
     // See CR 6362902.
     if (AlwaysTenure) {
       FLAG_SET_CMDLINE(intx, MaxTenuringThreshold, 0);
@@ -1003,7 +1009,7 @@
 // further optimization and tuning efforts, and would almost
 // certainly gain from analysis of platform and environment.
 void Arguments::set_cms_and_parnew_gc_flags() {
-  assert(!UseSerialGC && !UseParallelGC, "Error");
+  assert(!UseSerialGC && !UseParallelOldGC && !UseParallelGC, "Error");
   assert(UseConcMarkSweepGC, "CMS is expected to be on here");
 
   // If we are using CMS, we prefer to UseParNewGC,
@@ -1068,7 +1074,7 @@
     } else {
       FLAG_SET_ERGO(uintx, MaxNewSize, preferred_max_new_size);
     }
-    if(PrintGCDetails && Verbose) {
+    if (PrintGCDetails && Verbose) {
       // Too early to use gclog_or_tty
       tty->print_cr("Ergo set MaxNewSize: " SIZE_FORMAT, MaxNewSize);
     }
@@ -1097,15 +1103,15 @@
     } else {
       min_new = NewSize;
     }
-    size_t prev_initial_size = initial_heap_size();
-    if (prev_initial_size != 0 && prev_initial_size < min_new+OldSize) {
-      set_initial_heap_size(min_new+OldSize);
+    size_t prev_initial_size = InitialHeapSize;
+    if (prev_initial_size != 0 && prev_initial_size < min_new + OldSize) {
+      FLAG_SET_ERGO(uintx, InitialHeapSize, min_new + OldSize);
       // Currently minimum size and the initial heap sizes are the same.
-      set_min_heap_size(initial_heap_size());
+      set_min_heap_size(InitialHeapSize);
       if (PrintGCDetails && Verbose) {
         warning("Initial heap size increased to " SIZE_FORMAT " M from "
                 SIZE_FORMAT " M; use -XX:NewSize=... for finer control.",
-                initial_heap_size()/M, prev_initial_size/M);
+                InitialHeapSize/M, prev_initial_size/M);
       }
     }
 
@@ -1114,12 +1120,12 @@
       align_size_down(MaxHeapSize,
                       CardTableRS::ct_max_alignment_constraint());
 
-    if(PrintGCDetails && Verbose) {
+    if (PrintGCDetails && Verbose) {
       // Too early to use gclog_or_tty
       tty->print_cr("CMS set min_heap_size: " SIZE_FORMAT
            " initial_heap_size:  " SIZE_FORMAT
            " max_heap: " SIZE_FORMAT,
-           min_heap_size(), initial_heap_size(), max_heap);
+           min_heap_size(), InitialHeapSize, max_heap);
     }
     if (max_heap > min_new) {
       // Unless explicitly requested otherwise, make young gen
@@ -1127,7 +1133,7 @@
       if (FLAG_IS_DEFAULT(NewSize)) {
         FLAG_SET_ERGO(uintx, NewSize, MAX2(NewSize, min_new));
         FLAG_SET_ERGO(uintx, NewSize, MIN2(preferred_max_new_size, NewSize));
-        if(PrintGCDetails && Verbose) {
+        if (PrintGCDetails && Verbose) {
           // Too early to use gclog_or_tty
           tty->print_cr("Ergo set NewSize: " SIZE_FORMAT, NewSize);
         }
@@ -1137,8 +1143,8 @@
       // later NewRatio will decide how it grows; see above.
       if (FLAG_IS_DEFAULT(OldSize)) {
         if (max_heap > NewSize) {
-          FLAG_SET_ERGO(uintx, OldSize, MIN2(3*NewSize,  max_heap - NewSize));
-          if(PrintGCDetails && Verbose) {
+          FLAG_SET_ERGO(uintx, OldSize, MIN2(3*NewSize, max_heap - NewSize));
+          if (PrintGCDetails && Verbose) {
             // Too early to use gclog_or_tty
             tty->print_cr("Ergo set OldSize: " SIZE_FORMAT, OldSize);
           }
@@ -1186,7 +1192,7 @@
 
 inline uintx max_heap_for_compressed_oops() {
   LP64_ONLY(return oopDesc::OopEncodingHeapMax - MaxPermSize - os::vm_page_size());
-  NOT_LP64(return DefaultMaxRAM);
+  NOT_LP64(ShouldNotReachHere(); return 0);
 }
 
 bool Arguments::should_auto_select_low_pause_collector() {
@@ -1205,7 +1211,7 @@
 
 void Arguments::set_ergonomics_flags() {
   // Parallel GC is not compatible with sharing. If one specifies
-  // that they want sharing explicitly, do not set ergonmics flags.
+  // that they want sharing explicitly, do not set ergonomics flags.
   if (DumpSharedSpaces || ForceSharedSpaces) {
     return;
   }
@@ -1234,9 +1240,11 @@
   // Check that UseCompressedOops can be set with the max heap size allocated
   // by ergonomics.
   if (MaxHeapSize <= max_heap_for_compressed_oops()) {
+#ifndef COMPILER1
     if (FLAG_IS_DEFAULT(UseCompressedOops) && !UseG1GC) {
       FLAG_SET_ERGO(bool, UseCompressedOops, true);
     }
+#endif
 #ifdef _WIN64
     if (UseLargePages && UseCompressedOops) {
       // Cannot allocate guard pages for implicit checks in indexed addressing
@@ -1271,8 +1279,6 @@
     FLAG_SET_ERGO(uintx, ParallelGCThreads,
                   Abstract_VM_Version::parallel_worker_threads());
 
-    // PS is a server collector, setup the heap sizes accordingly.
-    set_server_heap_size();
     // If InitialSurvivorRatio or MinSurvivorRatio were not specified, but the
     // SurvivorRatio has been set, reset their default values to SurvivorRatio +
     // 2.  By doing this we make SurvivorRatio also work for Parallel Scavenger.
@@ -1302,8 +1308,6 @@
 
 void Arguments::set_g1_gc_flags() {
   assert(UseG1GC, "Error");
-  // G1 is a server collector, setup the heap sizes accordingly.
-  set_server_heap_size();
 #ifdef COMPILER1
   FastTLABRefill = false;
 #endif
@@ -1321,50 +1325,79 @@
   }
 }
 
-void Arguments::set_server_heap_size() {
+void Arguments::set_heap_size() {
+  if (!FLAG_IS_DEFAULT(DefaultMaxRAMFraction)) {
+    // Deprecated flag
+    FLAG_SET_CMDLINE(uintx, MaxRAMFraction, DefaultMaxRAMFraction);
+  }
+
+  const julong phys_mem =
+    FLAG_IS_DEFAULT(MaxRAM) ? MIN2(os::physical_memory(), (julong)MaxRAM)
+                            : (julong)MaxRAM;
+
+  // If the maximum heap size has not been set with -Xmx,
+  // then set it as fraction of the size of physical memory,
+  // respecting the maximum and minimum sizes of the heap.
   if (FLAG_IS_DEFAULT(MaxHeapSize)) {
-    const uint64_t reasonable_fraction =
-      os::physical_memory() / DefaultMaxRAMFraction;
-    const uint64_t maximum_size = (uint64_t)
-                 (FLAG_IS_DEFAULT(DefaultMaxRAM) && UseCompressedOops ?
-                     MIN2(max_heap_for_compressed_oops(), DefaultMaxRAM) :
-                     DefaultMaxRAM);
-    size_t reasonable_max =
-      (size_t) os::allocatable_physical_memory(reasonable_fraction);
-    if (reasonable_max > maximum_size) {
-      reasonable_max = maximum_size;
+    julong reasonable_max = phys_mem / MaxRAMFraction;
+
+    if (phys_mem <= MaxHeapSize * MinRAMFraction) {
+      // Small physical memory, so use a minimum fraction of it for the heap
+      reasonable_max = phys_mem / MinRAMFraction;
+    } else {
+      // Not-small physical memory, so require a heap at least
+      // as large as MaxHeapSize
+      reasonable_max = MAX2(reasonable_max, (julong)MaxHeapSize);
+    }
+    if (!FLAG_IS_DEFAULT(ErgoHeapSizeLimit) && ErgoHeapSizeLimit != 0) {
+      // Limit the heap size to ErgoHeapSizeLimit
+      reasonable_max = MIN2(reasonable_max, (julong)ErgoHeapSizeLimit);
     }
+    if (UseCompressedOops) {
+      // Limit the heap size to the maximum possible when using compressed oops
+      reasonable_max = MIN2(reasonable_max, (julong)max_heap_for_compressed_oops());
+    }
+    reasonable_max = os::allocatable_physical_memory(reasonable_max);
+
+    if (!FLAG_IS_DEFAULT(InitialHeapSize)) {
+      // An initial heap size was specified on the command line,
+      // so be sure that the maximum size is consistent.  Done
+      // after call to allocatable_physical_memory because that
+      // method might reduce the allocation size.
+      reasonable_max = MAX2(reasonable_max, (julong)InitialHeapSize);
+    }
+
     if (PrintGCDetails && Verbose) {
       // Cannot use gclog_or_tty yet.
-      tty->print_cr("  Max heap size for server class platform "
-                    SIZE_FORMAT, reasonable_max);
+      tty->print_cr("  Maximum heap size " SIZE_FORMAT, reasonable_max);
     }
-    // If the initial_heap_size has not been set with -Xms,
-    // then set it as fraction of size of physical memory
-    // respecting the maximum and minimum sizes of the heap.
-    if (initial_heap_size() == 0) {
-      const uint64_t reasonable_initial_fraction =
-        os::physical_memory() / DefaultInitialRAMFraction;
-      const size_t reasonable_initial =
-        (size_t) os::allocatable_physical_memory(reasonable_initial_fraction);
-      const size_t minimum_size = NewSize + OldSize;
-      set_initial_heap_size(MAX2(MIN2(reasonable_initial, reasonable_max),
-                                minimum_size));
-      // Currently the minimum size and the initial heap sizes are the same.
-      set_min_heap_size(initial_heap_size());
-      if (PrintGCDetails && Verbose) {
-        // Cannot use gclog_or_tty yet.
-        tty->print_cr("  Initial heap size for server class platform "
-                      SIZE_FORMAT, initial_heap_size());
-      }
-    } else {
-      // A minimum size was specified on the command line.  Be sure
-      // that the maximum size is consistent.
-      if (initial_heap_size() > reasonable_max) {
-        reasonable_max = initial_heap_size();
-      }
+    FLAG_SET_ERGO(uintx, MaxHeapSize, (uintx)reasonable_max);
+  }
+
+  // If the initial_heap_size has not been set with InitialHeapSize
+  // or -Xms, then set it as fraction of the size of physical memory,
+  // respecting the maximum and minimum sizes of the heap.
+  if (FLAG_IS_DEFAULT(InitialHeapSize)) {
+    julong reasonable_minimum = (julong)(OldSize + NewSize);
+
+    reasonable_minimum = MIN2(reasonable_minimum, (julong)MaxHeapSize);
+
+    reasonable_minimum = os::allocatable_physical_memory(reasonable_minimum);
+
+    julong reasonable_initial = phys_mem / InitialRAMFraction;
+
+    reasonable_initial = MAX2(reasonable_initial, reasonable_minimum);
+    reasonable_initial = MIN2(reasonable_initial, (julong)MaxHeapSize);
+
+    reasonable_initial = os::allocatable_physical_memory(reasonable_initial);
+
+    if (PrintGCDetails && Verbose) {
+      // Cannot use gclog_or_tty yet.
+      tty->print_cr("  Initial heap size " SIZE_FORMAT, (uintx)reasonable_initial);
+      tty->print_cr("  Minimum heap size " SIZE_FORMAT, (uintx)reasonable_minimum);
     }
-    FLAG_SET_ERGO(uintx, MaxHeapSize, (uintx) reasonable_max);
+    FLAG_SET_ERGO(uintx, InitialHeapSize, (uintx)reasonable_initial);
+    set_min_heap_size((uintx)reasonable_minimum);
   }
 }
 
@@ -1448,7 +1481,7 @@
   return false;
 }
 
-static void set_serial_gc_flags() {
+static void force_serial_gc() {
   FLAG_SET_DEFAULT(UseSerialGC, true);
   FLAG_SET_DEFAULT(UseParNewGC, false);
   FLAG_SET_DEFAULT(UseConcMarkSweepGC, false);
@@ -1584,15 +1617,15 @@
     // force sharing off.
     if (DumpSharedSpaces || ForceSharedSpaces) {
       jio_fprintf(defaultStream::error_stream(),
-                  "Reverting to Serial GC because of %s \n",
+                  "Reverting to Serial GC because of %s\n",
                   ForceSharedSpaces ? " -Xshare:on" : "-Xshare:dump");
-      set_serial_gc_flags();
+      force_serial_gc();
       FLAG_SET_DEFAULT(SOLARIS_ONLY(UseISM) NOT_SOLARIS(UseLargePages), false);
     } else {
-      if (UseSharedSpaces) {
+      if (UseSharedSpaces && Verbose) {
         jio_fprintf(defaultStream::error_stream(),
                     "Turning off use of shared archive because of "
-                    "choice of garbage collector or large pages \n");
+                    "choice of garbage collector or large pages\n");
       }
       no_shared_spaces();
     }
@@ -1925,8 +1958,8 @@
         describe_range_error(errcode);
         return JNI_EINVAL;
       }
-      FLAG_SET_CMDLINE(uintx, MaxNewSize, (size_t) long_initial_eden_size);
-      FLAG_SET_CMDLINE(uintx, NewSize, (size_t) long_initial_eden_size);
+      FLAG_SET_CMDLINE(uintx, MaxNewSize, (uintx)long_initial_eden_size);
+      FLAG_SET_CMDLINE(uintx, NewSize, (uintx)long_initial_eden_size);
     // -Xms
     } else if (match_option(option, "-Xms", &tail)) {
       julong long_initial_heap_size = 0;
@@ -1937,9 +1970,9 @@
         describe_range_error(errcode);
         return JNI_EINVAL;
       }
-      set_initial_heap_size((size_t) long_initial_heap_size);
+      FLAG_SET_CMDLINE(uintx, InitialHeapSize, (uintx)long_initial_heap_size);
       // Currently the minimum size and the initial heap sizes are the same.
-      set_min_heap_size(initial_heap_size());
+      set_min_heap_size(InitialHeapSize);
     // -Xmx
     } else if (match_option(option, "-Xmx", &tail)) {
       julong long_max_heap_size = 0;
@@ -1950,7 +1983,7 @@
         describe_range_error(errcode);
         return JNI_EINVAL;
       }
-      FLAG_SET_CMDLINE(uintx, MaxHeapSize, (size_t) long_max_heap_size);
+      FLAG_SET_CMDLINE(uintx, MaxHeapSize, (uintx)long_max_heap_size);
     // Xmaxf
     } else if (match_option(option, "-Xmaxf", &tail)) {
       int maxf = (int)(atof(tail) * 100);
@@ -2196,9 +2229,9 @@
 
       if (FLAG_IS_DEFAULT(MaxHeapSize)) {
          FLAG_SET_CMDLINE(uintx, MaxHeapSize, initHeapSize);
-         set_initial_heap_size(MaxHeapSize);
+         FLAG_SET_CMDLINE(uintx, InitialHeapSize, initHeapSize);
          // Currently the minimum size and the initial heap sizes are the same.
-         set_min_heap_size(initial_heap_size());
+         set_min_heap_size(initHeapSize);
       }
       if (FLAG_IS_DEFAULT(NewSize)) {
          // Make the young generation 3/8ths of the total heap.
@@ -2675,8 +2708,12 @@
     }
   }
 
+#if defined(_LP64) && defined(COMPILER1)
+  UseCompressedOops = false;
+#endif
+
 #ifdef SERIALGC
-  set_serial_gc_flags();
+  force_serial_gc();
 #endif // SERIALGC
 #ifdef KERNEL
   no_shared_spaces();
@@ -2690,18 +2727,22 @@
     return JNI_EINVAL;
   }
 
-  if (UseParallelGC || UseParallelOldGC) {
-    // Set some flags for ParallelGC if needed.
-    set_parallel_gc_flags();
-  } else if (UseConcMarkSweepGC) {
-    // Set some flags for CMS
+  if (UseConcMarkSweepGC) {
+    // Set flags for CMS and ParNew.  Check UseConcMarkSweep first
+    // to ensure that when both UseConcMarkSweepGC and UseParNewGC
+    // are true, we don't call set_parnew_gc_flags() as well.
     set_cms_and_parnew_gc_flags();
-  } else if (UseParNewGC) {
-    // Set some flags for ParNew
-    set_parnew_gc_flags();
-  } else if (UseG1GC) {
-    // Set some flags for garbage-first, if needed.
-    set_g1_gc_flags();
+  } else {
+    // Set heap size based on available physical memory
+    set_heap_size();
+    // Set per-collector flags
+    if (UseParallelGC || UseParallelOldGC) {
+      set_parallel_gc_flags();
+    } else if (UseParNewGC) {
+      set_parnew_gc_flags();
+    } else if (UseG1GC) {
+      set_g1_gc_flags();
+    }
   }
 
 #ifdef SERIALGC
--- a/hotspot/src/share/vm/runtime/arguments.hpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/share/vm/runtime/arguments.hpp	Wed Jul 05 17:04:56 2017 +0200
@@ -254,7 +254,6 @@
   static bool   _has_profile;
   static bool   _has_alloc_profile;
   static const char*  _gc_log_filename;
-  static uintx  _initial_heap_size;
   static uintx  _min_heap_size;
 
   // -Xrun arguments
@@ -300,8 +299,8 @@
   static void set_g1_gc_flags();
   // GC ergonomics
   static void set_ergonomics_flags();
-  // Setup heap size for a server platform
-  static void set_server_heap_size();
+  // Setup heap size
+  static void set_heap_size();
   // Based on automatic selection criteria, should the
   // low pause collector be used.
   static bool should_auto_select_low_pause_collector();
@@ -434,9 +433,7 @@
   static bool has_profile()                 { return _has_profile; }
   static bool has_alloc_profile()           { return _has_alloc_profile; }
 
-  // -Xms , -Xmx
-  static uintx initial_heap_size()          { return _initial_heap_size; }
-  static void  set_initial_heap_size(uintx v) { _initial_heap_size = v;  }
+  // -Xms, -Xmx
   static uintx min_heap_size()              { return _min_heap_size; }
   static void  set_min_heap_size(uintx v)   { _min_heap_size = v;  }
 
--- a/hotspot/src/share/vm/runtime/frame.cpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/share/vm/runtime/frame.cpp	Wed Jul 05 17:04:56 2017 +0200
@@ -1190,9 +1190,19 @@
 
 
 void frame::oops_do_internal(OopClosure* f, CodeBlobClosure* cf, RegisterMap* map, bool use_interpreter_oop_map_cache) {
-         if (is_interpreted_frame())    { oops_interpreted_do(f, map, use_interpreter_oop_map_cache);
-  } else if (is_entry_frame())          { oops_entry_do      (f, map);
-  } else if (CodeCache::contains(pc())) { oops_code_blob_do  (f, cf, map);
+#ifndef PRODUCT
+  // simulate GC crash here to dump java thread in error report
+  if (CrashGCForDumpingJavaThread) {
+    char *t = NULL;
+    *t = 'c';
+  }
+#endif
+  if (is_interpreted_frame()) {
+    oops_interpreted_do(f, map, use_interpreter_oop_map_cache);
+  } else if (is_entry_frame()) {
+    oops_entry_do(f, map);
+  } else if (CodeCache::contains(pc())) {
+    oops_code_blob_do(f, cf, map);
   } else {
     ShouldNotReachHere();
   }
--- a/hotspot/src/share/vm/runtime/globals.cpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/share/vm/runtime/globals.cpp	Wed Jul 05 17:04:56 2017 +0200
@@ -46,7 +46,8 @@
 bool Flag::is_unlocked() const {
   if (strcmp(kind, "{diagnostic}") == 0) {
     return UnlockDiagnosticVMOptions;
-  } else if (strcmp(kind, "{experimental}") == 0) {
+  } else if (strcmp(kind, "{experimental}") == 0 ||
+             strcmp(kind, "{C2 experimental}") == 0) {
     return UnlockExperimentalVMOptions;
   } else {
     return true;
@@ -69,9 +70,10 @@
 
 void Flag::print_on(outputStream* st) {
   st->print("%5s %-35s %c= ", type, name, (origin != DEFAULT ? ':' : ' '));
-  if (is_bool())  st->print("%-16s", get_bool() ? "true" : "false");
-  if (is_intx())  st->print("%-16ld", get_intx());
-  if (is_uintx()) st->print("%-16lu", get_uintx());
+  if (is_bool())     st->print("%-16s", get_bool() ? "true" : "false");
+  if (is_intx())     st->print("%-16ld", get_intx());
+  if (is_uintx())    st->print("%-16lu", get_uintx());
+  if (is_uint64_t()) st->print("%-16lu", get_uint64_t());
   if (is_ccstr()) {
     const char* cp = get_ccstr();
     if (cp != NULL) {
@@ -100,6 +102,8 @@
     st->print("-XX:%s=" INTX_FORMAT, name, get_intx());
   } else if (is_uintx()) {
     st->print("-XX:%s=" UINTX_FORMAT, name, get_uintx());
+  } else if (is_uint64_t()) {
+    st->print("-XX:%s=" UINT64_FORMAT, name, get_uint64_t());
   } else if (is_ccstr()) {
     st->print("-XX:%s=", name);
     const char* cp = get_ccstr();
@@ -166,6 +170,7 @@
 #define C2_PRODUCT_FLAG_STRUCT(type, name, value, doc) { #type, XSTR(name), &name, "{C2 product}", DEFAULT },
 #define C2_PD_PRODUCT_FLAG_STRUCT(type, name, doc)     { #type, XSTR(name), &name, "{C2 pd product}", DEFAULT },
 #define C2_DIAGNOSTIC_FLAG_STRUCT(type, name, value, doc) { #type, XSTR(name), &name, "{C2 diagnostic}", DEFAULT },
+#define C2_EXPERIMENTAL_FLAG_STRUCT(type, name, value, doc) { #type, XSTR(name), &name, "{C2 experimental}", DEFAULT },
 #ifdef PRODUCT
   #define C2_DEVELOP_FLAG_STRUCT(type, name, value, doc) /* flag is constant */
   #define C2_PD_DEVELOP_FLAG_STRUCT(type, name, doc)     /* flag is constant */
@@ -187,7 +192,7 @@
  C1_FLAGS(C1_DEVELOP_FLAG_STRUCT, C1_PD_DEVELOP_FLAG_STRUCT, C1_PRODUCT_FLAG_STRUCT, C1_PD_PRODUCT_FLAG_STRUCT, C1_NOTPRODUCT_FLAG_STRUCT)
 #endif
 #ifdef COMPILER2
- C2_FLAGS(C2_DEVELOP_FLAG_STRUCT, C2_PD_DEVELOP_FLAG_STRUCT, C2_PRODUCT_FLAG_STRUCT, C2_PD_PRODUCT_FLAG_STRUCT, C2_DIAGNOSTIC_FLAG_STRUCT, C2_NOTPRODUCT_FLAG_STRUCT)
+ C2_FLAGS(C2_DEVELOP_FLAG_STRUCT, C2_PD_DEVELOP_FLAG_STRUCT, C2_PRODUCT_FLAG_STRUCT, C2_PD_PRODUCT_FLAG_STRUCT, C2_DIAGNOSTIC_FLAG_STRUCT, C2_EXPERIMENTAL_FLAG_STRUCT, C2_NOTPRODUCT_FLAG_STRUCT)
 #endif
  {0, NULL, NULL}
 };
@@ -324,6 +329,32 @@
   faddr->origin = origin;
 }
 
+bool CommandLineFlags::uint64_tAt(char* name, size_t len, uint64_t* value) {
+  Flag* result = Flag::find_flag(name, len);
+  if (result == NULL) return false;
+  if (!result->is_uint64_t()) return false;
+  *value = result->get_uint64_t();
+  return true;
+}
+
+bool CommandLineFlags::uint64_tAtPut(char* name, size_t len, uint64_t* value, FlagValueOrigin origin) {
+  Flag* result = Flag::find_flag(name, len);
+  if (result == NULL) return false;
+  if (!result->is_uint64_t()) return false;
+  uint64_t old_value = result->get_uint64_t();
+  result->set_uint64_t(*value);
+  *value = old_value;
+  result->origin = origin;
+  return true;
+}
+
+void CommandLineFlagsEx::uint64_tAtPut(CommandLineFlagWithType flag, uint64_t value, FlagValueOrigin origin) {
+  Flag* faddr = address_of_flag(flag);
+  guarantee(faddr != NULL && faddr->is_uint64_t(), "wrong flag type");
+  faddr->set_uint64_t(value);
+  faddr->origin = origin;
+}
+
 bool CommandLineFlags::doubleAt(char* name, size_t len, double* value) {
   Flag* result = Flag::find_flag(name, len);
   if (result == NULL) return false;
--- a/hotspot/src/share/vm/runtime/globals.hpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/share/vm/runtime/globals.hpp	Wed Jul 05 17:04:56 2017 +0200
@@ -47,8 +47,8 @@
 define_pd_global(intx, OnStackReplacePercentage,     0);
 define_pd_global(bool, ResizeTLAB,                   false);
 define_pd_global(intx, FreqInlineSize,               0);
+define_pd_global(intx, InlineSmallCode,              0);
 define_pd_global(intx, NewSizeThreadIncrease,        4*K);
-define_pd_global(intx, NewRatio,                     4);
 define_pd_global(intx, InlineClassNatives,           true);
 define_pd_global(intx, InlineUnsafeOps,              true);
 define_pd_global(intx, InitialCodeCacheSize,         160*K);
@@ -58,7 +58,7 @@
 define_pd_global(uintx,PermSize,    ScaleForWordSize(4*M));
 define_pd_global(uintx,MaxPermSize, ScaleForWordSize(64*M));
 define_pd_global(bool, NeverActAsServerClassMachine, true);
-define_pd_global(uintx, DefaultMaxRAM,               1*G);
+define_pd_global(uint64_t,MaxRAM,                    1ULL*G);
 #define CI_COMPILER_COUNT 0
 #else
 
@@ -113,6 +113,10 @@
   uintx get_uintx() const     { return *((uintx*) addr); }
   void set_uintx(uintx value) { *((uintx*) addr) = value; }
 
+  bool is_uint64_t() const          { return strcmp(type, "uint64_t") == 0; }
+  uint64_t get_uint64_t() const     { return *((uint64_t*) addr); }
+  void set_uint64_t(uint64_t value) { *((uint64_t*) addr) = value; }
+
   bool is_double() const        { return strcmp(type, "double") == 0; }
   double get_double() const     { return *((double*) addr); }
   void set_double(double value) { *((double*) addr) = value; }
@@ -188,6 +192,11 @@
   static bool uintxAtPut(char* name, size_t len, uintx* value, FlagValueOrigin origin);
   static bool uintxAtPut(char* name, uintx* value, FlagValueOrigin origin) { return uintxAtPut(name, strlen(name), value, origin); }
 
+  static bool uint64_tAt(char* name, size_t len, uint64_t* value);
+  static bool uint64_tAt(char* name, uint64_t* value) { return uint64_tAt(name, strlen(name), value); }
+  static bool uint64_tAtPut(char* name, size_t len, uint64_t* value, FlagValueOrigin origin);
+  static bool uint64_tAtPut(char* name, uint64_t* value, FlagValueOrigin origin) { return uint64_tAtPut(name, strlen(name), value, origin); }
+
   static bool doubleAt(char* name, size_t len, double* value);
   static bool doubleAt(char* name, double* value)    { return doubleAt(name, strlen(name), value); }
   static bool doubleAtPut(char* name, size_t len, double* value, FlagValueOrigin origin);
@@ -785,7 +794,7 @@
   product(bool, ProfilerRecordPC, false,                                    \
           "Collects tick for each 16 byte interval of compiled code")       \
                                                                             \
-  product(bool, ProfileVM,  false,                                          \
+  product(bool, ProfileVM, false,                                           \
           "Profiles ticks that fall within VM (either in the VM Thread "    \
           "or VM code called through stubs)")                               \
                                                                             \
@@ -815,7 +824,7 @@
                                                                             \
   product(bool, RegisterFinalizersAtInit, true,                             \
           "Register finalizable objects at end of Object.<init> or "        \
-          "after allocation.")                                              \
+          "after allocation")                                               \
                                                                             \
   develop(bool, RegisterReferences, true,                                   \
           "Tells whether the VM should register soft/weak/final/phantom "   \
@@ -862,14 +871,14 @@
   product(bool, AlwaysLockClassLoader, false,                               \
           "Require the VM to acquire the class loader lock before calling " \
           "loadClass() even for class loaders registering "                 \
-          "as parallel capable. Default false. ")                           \
+          "as parallel capable")                                            \
                                                                             \
   product(bool, AllowParallelDefineClass, false,                            \
           "Allow parallel defineClass requests for class loaders "          \
-          "registering as parallel capable. Default false")                 \
+          "registering as parallel capable")                                \
                                                                             \
   product(bool, MustCallLoadClassInternal, false,                           \
-          "Call loadClassInternal() rather than loadClass().Default false") \
+          "Call loadClassInternal() rather than loadClass()")               \
                                                                             \
   product_pd(bool, DontYieldALot,                                           \
           "Throw away obvious excess yield calls (for SOLARIS only)")       \
@@ -921,9 +930,9 @@
          "(Unstable, Linux-specific)"                                       \
          " avoid NPTL-FUTEX hang pthread_cond_timedwait" )                  \
                                                                             \
-  product(bool, FilterSpuriousWakeups , true,                               \
-          "Prevent spurious or premature wakeups from object.wait"              \
-          "(Solaris only)")                                                     \
+  product(bool, FilterSpuriousWakeups, true,                                \
+          "Prevent spurious or premature wakeups from object.wait "         \
+          "(Solaris only)")                                                 \
                                                                             \
   product(intx, NativeMonitorTimeout, -1, "(Unstable)" )                    \
   product(intx, NativeMonitorFlags, 0, "(Unstable)" )                       \
@@ -973,7 +982,7 @@
                                                                             \
   product(bool, UseAltSigs, false,                                          \
           "Use alternate signals instead of SIGUSR1 & SIGUSR2 for VM "      \
-          "internal signals. (Solaris only)")                               \
+          "internal signals (Solaris only)")                                \
                                                                             \
   product(bool, UseSpinning, false,                                         \
           "Use spinning in monitor inflation and before entry")             \
@@ -1265,12 +1274,12 @@
           "Always tenure objects in eden. (ParallelGC only)")               \
                                                                             \
   product(bool, NeverTenure, false,                                         \
-          "Never tenure objects in eden, May tenure on overflow"            \
-          " (ParallelGC only)")                                             \
+          "Never tenure objects in eden, May tenure on overflow "           \
+          "(ParallelGC only)")                                              \
                                                                             \
   product(bool, ScavengeBeforeFullGC, true,                                 \
-          "Scavenge youngest generation before each full GC,"               \
-          " used with UseParallelGC")                                       \
+          "Scavenge youngest generation before each full GC, "              \
+          "used with UseParallelGC")                                        \
                                                                             \
   develop(bool, ScavengeWithObjectsInToSpace, false,                        \
           "Allow scavenges to occur when to_space contains objects.")       \
@@ -1283,9 +1292,9 @@
           " (effective only when UseConcMarkSweepGC)")                      \
                                                                             \
   product(bool, ExplicitGCInvokesConcurrentAndUnloadsClasses, false,        \
-          "A System.gc() request invokes a concurrent collection and"       \
-          " also unloads classes during such a concurrent gc cycle  "       \
-          " (effective only when UseConcMarkSweepGC)")                      \
+          "A System.gc() request invokes a concurrent collection and "      \
+          "also unloads classes during such a concurrent gc cycle "         \
+          "(effective only when UseConcMarkSweepGC)")                       \
                                                                             \
   develop(bool, UseCMSAdaptiveFreeLists, true,                              \
           "Use Adaptive Free Lists in the CMS generation")                  \
@@ -1340,8 +1349,8 @@
           "Whether we should simulate work queue overflow in ParNew")       \
                                                                             \
   notproduct(uintx, ParGCWorkQueueOverflowInterval, 1000,                   \
-          "An `interval' counter that determines how frequently"            \
-          " we simulate overflow; a smaller number increases frequency")    \
+          "An `interval' counter that determines how frequently "           \
+          "we simulate overflow; a smaller number increases frequency")     \
                                                                             \
   product(uintx, ParGCDesiredObjsFromOverflowList, 20,                      \
           "The desired number of objects to claim from the overflow list")  \
@@ -1354,12 +1363,12 @@
           "It forces all freshly committed pages to be pre-touched.")       \
                                                                             \
   product(bool, CMSUseOldDefaults, false,                                   \
-          "A flag temporarily  introduced to allow reverting to some older" \
-          "default settings; older as of 6.0 ")                             \
+          "A flag temporarily introduced to allow reverting to some "       \
+          "older default settings; older as of 6.0")                        \
                                                                             \
   product(intx, CMSYoungGenPerWorker, 16*M,                                 \
           "The amount of young gen chosen by default per GC worker "        \
-          "thread available ")                                              \
+          "thread available")                                               \
                                                                             \
   product(bool, GCOverheadReporting, false,                                 \
          "Enables the GC overhead reporting facility")                      \
@@ -1380,43 +1389,44 @@
           "automatically adjusted")                                         \
                                                                             \
   product(uintx, CMSIncrementalDutyCycleMin, 0,                             \
-          "Lower bound on the duty cycle when CMSIncrementalPacing is"      \
-          "enabled (a percentage, 0-100).")                                 \
+          "Lower bound on the duty cycle when CMSIncrementalPacing is "     \
+          "enabled (a percentage, 0-100)")                                  \
                                                                             \
   product(uintx, CMSIncrementalSafetyFactor, 10,                            \
-          "Percentage (0-100) used to add conservatism when computing the"  \
-          "duty cycle.")                                                    \
+          "Percentage (0-100) used to add conservatism when computing the " \
+          "duty cycle")                                                     \
                                                                             \
   product(uintx, CMSIncrementalOffset, 0,                                   \
           "Percentage (0-100) by which the CMS incremental mode duty cycle" \
-          "is shifted to the right within the period between young GCs")    \
+          " is shifted to the right within the period between young GCs")   \
                                                                             \
   product(uintx, CMSExpAvgFactor, 25,                                       \
-          "Percentage (0-100) used to weight the current sample when"       \
-          "computing exponential averages for CMS statistics.")             \
+          "Percentage (0-100) used to weight the current sample when "      \
+          "computing exponential averages for CMS statistics")              \
                                                                             \
   product(uintx, CMS_FLSWeight, 50,                                         \
-          "Percentage (0-100) used to weight the current sample when"       \
-          "computing exponentially decating averages for CMS FLS statistics.") \
+          "Percentage (0-100) used to weight the current sample when "      \
+          "computing exponentially decating averages for CMS FLS statistics") \
                                                                             \
   product(uintx, CMS_FLSPadding, 2,                                         \
-          "The multiple of deviation from mean to use for buffering"        \
+          "The multiple of deviation from mean to use for buffering "       \
           "against volatility in free list demand.")                        \
                                                                             \
   product(uintx, FLSCoalescePolicy, 2,                                      \
           "CMS: Aggression level for coalescing, increasing from 0 to 4")   \
                                                                             \
   product(uintx, CMS_SweepWeight, 50,                                       \
-          "Percentage (0-100) used to weight the current sample when"       \
-          "computing exponentially decaying average for inter-sweep duration.") \
+          "Percentage (0-100) used to weight the current sample when "      \
+          "computing exponentially decaying average for inter-sweep "       \
+          "duration")                                                       \
                                                                             \
   product(uintx, CMS_SweepPadding, 2,                                       \
-          "The multiple of deviation from mean to use for buffering"        \
+          "The multiple of deviation from mean to use for buffering "       \
           "against volatility in inter-sweep duration.")                    \
                                                                             \
   product(uintx, CMS_SweepTimerThresholdMillis, 10,                         \
           "Skip block flux-rate sampling for an epoch unless inter-sweep "  \
-          " duration exceeds this threhold in milliseconds")                \
+          "duration exceeds this threhold in milliseconds")                 \
                                                                             \
   develop(bool, CMSTraceIncrementalMode, false,                             \
           "Trace CMS incremental mode")                                     \
@@ -1617,35 +1627,36 @@
                                                                             \
   product(intx, CMSTriggerRatio, 80,                                        \
           "Percentage of MinHeapFreeRatio in CMS generation that is "       \
-          "  allocated before a CMS collection cycle commences")            \
+          "allocated before a CMS collection cycle commences")              \
                                                                             \
   product(intx, CMSTriggerPermRatio, 80,                                    \
-          "Percentage of MinHeapFreeRatio in the CMS perm generation that"  \
-          "  is allocated before a CMS collection cycle commences, that  "  \
-          "  also collects the perm generation")                            \
+          "Percentage of MinHeapFreeRatio in the CMS perm generation that " \
+          "is allocated before a CMS collection cycle commences, that "     \
+          "also collects the perm generation")                              \
                                                                             \
   product(uintx, CMSBootstrapOccupancy, 50,                                 \
           "Percentage CMS generation occupancy at which to "                \
-          " initiate CMS collection for bootstrapping collection stats")    \
+          "initiate CMS collection for bootstrapping collection stats")     \
                                                                             \
   product(intx, CMSInitiatingOccupancyFraction, -1,                         \
           "Percentage CMS generation occupancy to start a CMS collection "  \
-          " cycle (A negative value means that CMSTriggerRatio is used)")   \
+          "cycle. A negative value means that CMSTriggerRatio is used")     \
                                                                             \
   product(intx, CMSInitiatingPermOccupancyFraction, -1,                     \
-          "Percentage CMS perm generation occupancy to start a CMScollection"\
-          " cycle (A negative value means that CMSTriggerPermRatio is used)")\
+          "Percentage CMS perm generation occupancy to start a "            \
+          "CMScollection cycle. A negative value means that "               \
+          "CMSTriggerPermRatio is used")                                    \
                                                                             \
   product(bool, UseCMSInitiatingOccupancyOnly, false,                       \
           "Only use occupancy as a crierion for starting a CMS collection") \
                                                                             \
   product(intx, CMSIsTooFullPercentage, 98,                                 \
-          "An absolute ceiling above which CMS will always consider the"    \
-          " perm gen ripe for collection")                                  \
+          "An absolute ceiling above which CMS will always consider the "   \
+          "perm gen ripe for collection")                                   \
                                                                             \
   develop(bool, CMSTestInFreeList, false,                                   \
           "Check if the coalesced range is already in the "                 \
-          "free lists as claimed.")                                         \
+          "free lists as claimed")                                          \
                                                                             \
   notproduct(bool, CMSVerifyReturnedBytes, false,                           \
           "Check that all the garbage collected was returned to the "       \
@@ -1663,8 +1674,8 @@
           "Enforce ScavengeALot/GCALot at all potential safepoints")        \
                                                                             \
   product(bool, HandlePromotionFailure, true,                               \
-          "The youngest generation collection does not require"             \
-          " a guarantee of full promotion of all live objects.")            \
+          "The youngest generation collection does not require "            \
+          "a guarantee of full promotion of all live objects.")             \
                                                                             \
   notproduct(bool, PromotionFailureALot, false,                             \
           "Use promotion failure handling on every youngest generation "    \
@@ -1692,7 +1703,7 @@
           "Ratio of hard spins to calls to yield")                          \
                                                                             \
   product(uintx, PreserveMarkStackSize, 1024,                               \
-           "Size for stack used in promotion failure handling")             \
+          "Size for stack used in promotion failure handling")              \
                                                                             \
   product_pd(bool, UseTLAB, "Use thread-local object allocation")           \
                                                                             \
@@ -1720,14 +1731,27 @@
   product(bool, AlwaysActAsServerClassMachine, false,                       \
           "Always act like a server-class machine")                         \
                                                                             \
-  product_pd(uintx, DefaultMaxRAM,                                          \
-          "Maximum real memory size for setting server class heap size")    \
+  product_pd(uint64_t, MaxRAM,                                              \
+          "Real memory size (in bytes) used to set maximum heap size")      \
+                                                                            \
+  product(uintx, ErgoHeapSizeLimit, 0,                                      \
+          "Maximum ergonomically set heap size (in bytes); zero means use " \
+          "MaxRAM / MaxRAMFraction")                                        \
+                                                                            \
+  product(uintx, MaxRAMFraction, 4,                                         \
+          "Maximum fraction (1/n) of real memory used for maximum heap "    \
+          "size")                                                           \
                                                                             \
   product(uintx, DefaultMaxRAMFraction, 4,                                  \
-          "Fraction (1/n) of real memory used for server class max heap")   \
-                                                                            \
-  product(uintx, DefaultInitialRAMFraction, 64,                             \
-          "Fraction (1/n) of real memory used for server class initial heap")  \
+          "Maximum fraction (1/n) of real memory used for maximum heap "    \
+          "size; deprecated: to be renamed to MaxRAMFraction")              \
+                                                                            \
+  product(uintx, MinRAMFraction, 2,                                         \
+          "Minimum fraction (1/n) of real memory used for maxmimum heap "   \
+          "size on systems with small physical memory size")                \
+                                                                            \
+  product(uintx, InitialRAMFraction, 64,                                    \
+          "Fraction (1/n) of real memory used for initial heap size")       \
                                                                             \
   product(bool, UseAutoGCSelectPolicy, false,                               \
           "Use automatic collection selection policy")                      \
@@ -1778,7 +1802,7 @@
           "Number of collections before the adaptive sizing is started")    \
                                                                             \
   product(uintx, AdaptiveSizePolicyOutputInterval, 0,                       \
-          "Collecton interval for printing information, zero => never")     \
+          "Collecton interval for printing information; zero => never")     \
                                                                             \
   product(bool, UseAdaptiveSizePolicyFootprintGoal, true,                   \
           "Use adaptive minimum footprint as a goal")                       \
@@ -1808,7 +1832,8 @@
           "Allowed collection cost difference between generations")         \
                                                                             \
   product(uintx, AdaptiveSizePolicyCollectionCostMargin, 50,                \
-          "If collection costs are within margin, reduce both by full delta") \
+          "If collection costs are within margin, reduce both by full "     \
+          "delta")                                                          \
                                                                             \
   product(uintx, YoungGenerationSizeIncrement, 20,                          \
           "Adaptive size percentage change in young generation")            \
@@ -2527,8 +2552,11 @@
                                                                             \
   develop(bool, VerifyCompiledCode, false,                                  \
           "Include miscellaneous runtime verifications in nmethod code; "   \
-          "off by default because it disturbs nmethod size heuristics.")    \
-                                                                            \
+          "default off because it disturbs nmethod size heuristics")        \
+                                                                            \
+  notproduct(bool, CrashGCForDumpingJavaThread, false,                      \
+          "Manually make GC thread crash then dump java stack trace;  "     \
+          "Test only")                                                      \
                                                                             \
   /* compilation */                                                         \
   product(bool, UseCompiler, true,                                          \
@@ -2789,20 +2817,28 @@
           "an OS lock")                                                     \
                                                                             \
   /* gc parameters */                                                       \
-  product(uintx, MaxHeapSize, ScaleForWordSize(64*M),                       \
-          "Default maximum size for object heap (in bytes)")                \
-                                                                            \
-  product_pd(uintx, NewSize,                                                \
-          "Default size of new generation (in bytes)")                      \
+  product(uintx, InitialHeapSize, 0,                                        \
+          "Initial heap size (in bytes); zero means OldSize + NewSize")     \
+                                                                            \
+  product(uintx, MaxHeapSize, ScaleForWordSize(96*M),                       \
+          "Maximum heap size (in bytes)")                                   \
+                                                                            \
+  product(uintx, OldSize, ScaleForWordSize(4*M),                            \
+          "Initial tenured generation size (in bytes)")                     \
+                                                                            \
+  product(uintx, NewSize, ScaleForWordSize(4*M),                            \
+          "Initial new generation size (in bytes)")                         \
                                                                             \
   product(uintx, MaxNewSize, max_uintx,                                     \
-          "Maximum size of new generation (in bytes)")                      \
+          "Maximum new generation size (in bytes), max_uintx means set "    \
+          "ergonomically")                                                  \
                                                                             \
   product(uintx, PretenureSizeThreshold, 0,                                 \
-          "Max size in bytes of objects allocated in DefNew generation")    \
-                                                                            \
-  product_pd(uintx, TLABSize,                                               \
-          "Default (or starting) size of TLAB (in bytes)")                  \
+          "Maximum size in bytes of objects allocated in DefNew "           \
+          "generation; zero means no maximum")                              \
+                                                                            \
+  product(uintx, TLABSize, 0,                                               \
+          "Starting TLAB size (in bytes); zero means set ergonomically")    \
                                                                             \
   product(uintx, MinTLABSize, 2*K,                                          \
           "Minimum allowed TLAB size (in bytes)")                           \
@@ -2819,10 +2855,10 @@
   product(uintx, TLABWasteIncrement,    4,                                  \
           "Increment allowed waste at slow allocation")                     \
                                                                             \
-  product_pd(intx, SurvivorRatio,                                           \
+  product(intx, SurvivorRatio, 8,                                           \
           "Ratio of eden/survivor space size")                              \
                                                                             \
-  product_pd(intx, NewRatio,                                                \
+  product(intx, NewRatio, 2,                                                \
           "Ratio of new/old generation sizes")                              \
                                                                             \
   product(uintx, MaxLiveObjectEvacuationRatio, 100,                         \
@@ -2832,11 +2868,8 @@
           "Additional size added to desired new generation size per "       \
           "non-daemon thread (in bytes)")                                   \
                                                                             \
-  product(uintx, OldSize, ScaleForWordSize(4096*K),                         \
-          "Default size of tenured generation (in bytes)")                  \
-                                                                            \
   product_pd(uintx, PermSize,                                               \
-          "Default size of permanent generation (in bytes)")                \
+          "Initial size of permanent generation (in bytes)")                \
                                                                             \
   product_pd(uintx, MaxPermSize,                                            \
           "Maximum size of permanent generation (in bytes)")                \
--- a/hotspot/src/share/vm/runtime/globals_extension.hpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/share/vm/runtime/globals_extension.hpp	Wed Jul 05 17:04:56 2017 +0200
@@ -64,6 +64,7 @@
 #define C2_PRODUCT_FLAG_MEMBER(type, name, value, doc)         FLAG_MEMBER(name),
 #define C2_PD_PRODUCT_FLAG_MEMBER(type, name, doc)             FLAG_MEMBER(name),
 #define C2_DIAGNOSTIC_FLAG_MEMBER(type, name, value, doc)      FLAG_MEMBER(name),
+#define C2_EXPERIMENTAL_FLAG_MEMBER(type, name, value, doc)    FLAG_MEMBER(name),
 #ifdef PRODUCT
   #define C2_DEVELOP_FLAG_MEMBER(type, name, value, doc)       /* flag is constant */
   #define C2_PD_DEVELOP_FLAG_MEMBER(type, name, doc)           /* flag is constant */
@@ -84,7 +85,7 @@
  C1_FLAGS(C1_DEVELOP_FLAG_MEMBER, C1_PD_DEVELOP_FLAG_MEMBER, C1_PRODUCT_FLAG_MEMBER, C1_PD_PRODUCT_FLAG_MEMBER, C1_NOTPRODUCT_FLAG_MEMBER)
 #endif
 #ifdef COMPILER2
- C2_FLAGS(C2_DEVELOP_FLAG_MEMBER, C2_PD_DEVELOP_FLAG_MEMBER, C2_PRODUCT_FLAG_MEMBER, C2_PD_PRODUCT_FLAG_MEMBER, C2_DIAGNOSTIC_FLAG_MEMBER, C2_NOTPRODUCT_FLAG_MEMBER)
+ C2_FLAGS(C2_DEVELOP_FLAG_MEMBER, C2_PD_DEVELOP_FLAG_MEMBER, C2_PRODUCT_FLAG_MEMBER, C2_PD_PRODUCT_FLAG_MEMBER, C2_DIAGNOSTIC_FLAG_MEMBER, C2_EXPERIMENTAL_FLAG_MEMBER, C2_NOTPRODUCT_FLAG_MEMBER)
 #endif
  NUM_CommandLineFlag
 } CommandLineFlag;
@@ -130,6 +131,7 @@
 #define C2_PRODUCT_FLAG_MEMBER_WITH_TYPE(type, name, value, doc)         FLAG_MEMBER_WITH_TYPE(name,type),
 #define C2_PD_PRODUCT_FLAG_MEMBER_WITH_TYPE(type, name, doc)             FLAG_MEMBER_WITH_TYPE(name,type),
 #define C2_DIAGNOSTIC_FLAG_MEMBER_WITH_TYPE(type, name, value, doc)      FLAG_MEMBER_WITH_TYPE(name,type),
+#define C2_EXPERIMENTAL_FLAG_MEMBER_WITH_TYPE(type, name, value, doc)      FLAG_MEMBER_WITH_TYPE(name,type),
 #ifdef PRODUCT
   #define C2_DEVELOP_FLAG_MEMBER_WITH_TYPE(type, name, value, doc)       /* flag is constant */
   #define C2_PD_DEVELOP_FLAG_MEMBER_WITH_TYPE(type, name, doc)           /* flag is constant */
@@ -181,6 +183,7 @@
           C2_PRODUCT_FLAG_MEMBER_WITH_TYPE,
           C2_PD_PRODUCT_FLAG_MEMBER_WITH_TYPE,
           C2_DIAGNOSTIC_FLAG_MEMBER_WITH_TYPE,
+          C2_EXPERIMENTAL_FLAG_MEMBER_WITH_TYPE,
           C2_NOTPRODUCT_FLAG_MEMBER_WITH_TYPE)
 #endif
  NUM_CommandLineFlagWithType
@@ -202,6 +205,7 @@
   static void boolAtPut(CommandLineFlagWithType flag, bool value, FlagValueOrigin origin);
   static void intxAtPut(CommandLineFlagWithType flag, intx value, FlagValueOrigin origin);
   static void uintxAtPut(CommandLineFlagWithType flag, uintx value, FlagValueOrigin origin);
+  static void uint64_tAtPut(CommandLineFlagWithType flag, uint64_t value, FlagValueOrigin origin);
   static void doubleAtPut(CommandLineFlagWithType flag, double value, FlagValueOrigin origin);
   static void ccstrAtPut(CommandLineFlagWithType flag, ccstr value, FlagValueOrigin origin);
 
--- a/hotspot/src/share/vm/runtime/os.hpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/share/vm/runtime/os.hpp	Wed Jul 05 17:04:56 2017 +0200
@@ -60,24 +60,26 @@
 typedef void (*java_call_t)(JavaValue* value, methodHandle* method, JavaCallArguments* args, Thread* thread);
 
 class os: AllStatic {
- private:
+ public:
   enum { page_sizes_max = 9 }; // Size of _page_sizes array (8 plus a sentinel)
 
+ private:
   static OSThread*          _starting_thread;
   static address            _polling_page;
   static volatile int32_t * _mem_serialize_page;
   static uintptr_t          _serialize_page_mask;
+ public:
   static size_t             _page_sizes[page_sizes_max];
 
+ private:
   static void init_page_sizes(size_t default_page_size) {
     _page_sizes[0] = default_page_size;
     _page_sizes[1] = 0; // sentinel
   }
 
  public:
-
-  static void init(void);                       // Called before command line parsing
-  static jint init_2(void);                    // Called after command line parsing
+  static void init(void);   // Called before command line parsing
+  static jint init_2(void); // Called after command line parsing
 
   // File names are case-insensitive on windows only
   // Override me as needed
@@ -141,6 +143,7 @@
   static int processor_count() {
     return _processor_count;
   }
+  static void set_processor_count(int count) { _processor_count = count; }
 
   // Returns the number of CPUs this process is currently allowed to run on.
   // Note that on some OSes this can change dynamically.
@@ -294,19 +297,16 @@
   }
 
   static bool    is_memory_serialize_page(JavaThread *thread, address addr) {
-    address thr_addr;
     if (UseMembar) return false;
-    // Calculate thread specific address
+    // Previously this function calculated the exact address of this
+    // thread's serialize page, and checked if the faulting address
+    // was equal.  However, some platforms mask off faulting addresses
+    // to the page size, so now we just check that the address is
+    // within the page.  This makes the thread argument unnecessary,
+    // but we retain the NULL check to preserve existing behaviour.
     if (thread == NULL) return false;
-    // TODO-FIXME: some platforms mask off faulting addresses to the base pagesize.
-    // Instead of using a test for equality we should probably use something
-    // of the form:
-    // return ((_mem_serialize_page ^ addr) & -pagesize) == 0
-    //
-    thr_addr  = (address)(((uintptr_t)thread >>
-                get_serialize_page_shift_count()) &
-                get_serialize_page_mask()) + (uintptr_t)_mem_serialize_page;
-    return  (thr_addr == addr);
+    address page = (address) _mem_serialize_page;
+    return addr >= page && addr < (page + os::vm_page_size());
   }
 
   static void block_on_serialize_page_trap();
--- a/hotspot/src/share/vm/runtime/thread.cpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/share/vm/runtime/thread.cpp	Wed Jul 05 17:04:56 2017 +0200
@@ -884,6 +884,22 @@
                                          vmSymbolHandles::void_method_signature(), CHECK);
 }
 
+#ifdef KERNEL
+static void set_jkernel_boot_classloader_hook(TRAPS) {
+  klassOop k = SystemDictionary::sun_jkernel_DownloadManager_klass();
+  instanceKlassHandle klass (THREAD, k);
+
+  if (k == NULL) {
+    // sun.jkernel.DownloadManager may not present in the JDK; just return
+    return;
+  }
+
+  JavaValue result(T_VOID);
+  JavaCalls::call_static(&result, klass, vmSymbolHandles::setBootClassLoaderHook_name(),
+                                         vmSymbolHandles::void_method_signature(), CHECK);
+}
+#endif // KERNEL
+
 static void reset_vm_info_property(TRAPS) {
   // the vm info string
   ResourceMark rm(THREAD);
@@ -975,6 +991,7 @@
 // uniquely named instances should derive from this.
 NamedThread::NamedThread() : Thread() {
   _name = NULL;
+  _processed_thread = NULL;
 }
 
 NamedThread::~NamedThread() {
@@ -2317,6 +2334,27 @@
   frames_do(frame_gc_prologue);
 }
 
+// If the caller is a NamedThread, then remember, in the current scope,
+// the given JavaThread in its _processed_thread field.
+class RememberProcessedThread: public StackObj {
+  NamedThread* _cur_thr;
+public:
+  RememberProcessedThread(JavaThread* jthr) {
+    Thread* thread = Thread::current();
+    if (thread->is_Named_thread()) {
+      _cur_thr = (NamedThread *)thread;
+      _cur_thr->set_processed_thread(jthr);
+    } else {
+      _cur_thr = NULL;
+    }
+  }
+
+  ~RememberProcessedThread() {
+    if (_cur_thr) {
+      _cur_thr->set_processed_thread(NULL);
+    }
+  }
+};
 
 void JavaThread::oops_do(OopClosure* f, CodeBlobClosure* cf) {
   // Flush deferred store-barriers, if any, associated with
@@ -2333,6 +2371,8 @@
           (has_last_Java_frame() && java_call_counter() > 0), "wrong java_sp info!");
 
   if (has_last_Java_frame()) {
+    // Record JavaThread to GC thread
+    RememberProcessedThread rpt(this);
 
     // Traverse the privileged stack
     if (_privileged_stack_top != NULL) {
@@ -3102,6 +3142,12 @@
     vm_exit_during_initialization(Handle(THREAD, PENDING_EXCEPTION));
   }
 
+#ifdef KERNEL
+  if (JDK_Version::is_gte_jdk17x_version()) {
+    set_jkernel_boot_classloader_hook(THREAD);
+  }
+#endif // KERNEL
+
 #ifndef SERIALGC
   // Support for ConcurrentMarkSweep. This should be cleaned up
   // and better encapsulated. The ugly nested if test would go away
--- a/hotspot/src/share/vm/runtime/thread.hpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/share/vm/runtime/thread.hpp	Wed Jul 05 17:04:56 2017 +0200
@@ -48,7 +48,12 @@
 
 // Class hierarchy
 // - Thread
-//   - VMThread
+//   - NamedThread
+//     - VMThread
+//     - ConcurrentGCThread
+//     - WorkerThread
+//       - GangWorker
+//       - GCTaskThread
 //   - JavaThread
 //   - WatcherThread
 
@@ -249,6 +254,7 @@
   virtual bool is_GC_task_thread() const             { return false; }
   virtual bool is_Watcher_thread() const             { return false; }
   virtual bool is_ConcurrentGC_thread() const        { return false; }
+  virtual bool is_Named_thread() const               { return false; }
 
   virtual char* name() const { return (char*)"Unknown thread"; }
 
@@ -568,12 +574,18 @@
   };
  private:
   char* _name;
+  // log JavaThread being processed by oops_do
+  JavaThread* _processed_thread;
+
  public:
   NamedThread();
   ~NamedThread();
   // May only be called once per thread.
   void set_name(const char* format, ...);
+  virtual bool is_Named_thread() const { return true; }
   virtual char* name() const { return _name == NULL ? (char*)"Unknown Thread" : _name; }
+  JavaThread *processed_thread() { return _processed_thread; }
+  void set_processed_thread(JavaThread *thread) { _processed_thread = thread; }
 };
 
 // Worker threads are named and have an id of an assigned work.
--- a/hotspot/src/share/vm/runtime/vmStructs.cpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/share/vm/runtime/vmStructs.cpp	Wed Jul 05 17:04:56 2017 +0200
@@ -666,6 +666,7 @@
   nonstatic_field(Thread,                      _current_pending_monitor_is_from_java,         bool)                                  \
   nonstatic_field(Thread,                      _current_waiting_monitor,                      ObjectMonitor*)                        \
   nonstatic_field(NamedThread,                 _name,                                         char*)                                 \
+  nonstatic_field(NamedThread,                 _processed_thread,                             JavaThread*)                           \
   nonstatic_field(JavaThread,                  _next,                                         JavaThread*)                           \
   nonstatic_field(JavaThread,                  _threadObj,                                    oop)                                   \
   nonstatic_field(JavaThread,                  _anchor,                                       JavaFrameAnchor)                       \
--- a/hotspot/src/share/vm/runtime/vmThread.cpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/share/vm/runtime/vmThread.cpp	Wed Jul 05 17:04:56 2017 +0200
@@ -204,8 +204,8 @@
 }
 
 
-VMThread::VMThread() : Thread() {
-  // nothing to do
+VMThread::VMThread() : NamedThread() {
+  set_name("VM Thread");
 }
 
 void VMThread::destroy() {
--- a/hotspot/src/share/vm/runtime/vmThread.hpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/share/vm/runtime/vmThread.hpp	Wed Jul 05 17:04:56 2017 +0200
@@ -83,7 +83,7 @@
 // like scavenge, garbage_collect etc.
 //
 
-class VMThread: public Thread {
+class VMThread: public NamedThread {
  private:
   static ThreadPriority _current_priority;
 
@@ -101,8 +101,6 @@
   bool is_VM_thread() const                      { return true; }
   bool is_GC_thread() const                      { return true; }
 
-  char* name() const { return (char*)"VM Thread"; }
-
   // The ever running loop for the VMThread
   void loop();
 
--- a/hotspot/src/share/vm/services/attachListener.cpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/share/vm/services/attachListener.cpp	Wed Jul 05 17:04:56 2017 +0200
@@ -207,7 +207,7 @@
     int tmp;
     int n = sscanf(arg1, "%d", &tmp);
     if (n != 1) {
-      out->print_cr("flag value has to be boolean (1 or 0)");
+      out->print_cr("flag value must be a boolean (1 or 0)");
       return JNI_ERR;
     }
     value = (tmp != 0);
@@ -226,11 +226,11 @@
   if ((arg1 = op->arg(1)) != NULL) {
     int n = sscanf(arg1, INTX_FORMAT, &value);
     if (n != 1) {
-      out->print_cr("flag value has to be integer");
+      out->print_cr("flag value must be an integer");
       return JNI_ERR;
     }
   }
-  bool res = CommandLineFlags::intxAtPut((char*)name,  &value, ATTACH_ON_DEMAND);
+  bool res = CommandLineFlags::intxAtPut((char*)name, &value, ATTACH_ON_DEMAND);
   if (! res) {
     out->print_cr("setting flag %s failed", name);
   }
@@ -245,11 +245,30 @@
   if ((arg1 = op->arg(1)) != NULL) {
     int n = sscanf(arg1, UINTX_FORMAT, &value);
     if (n != 1) {
-      out->print_cr("flag value has to be integer");
+      out->print_cr("flag value must be an unsigned integer");
       return JNI_ERR;
     }
   }
-  bool res = CommandLineFlags::uintxAtPut((char*)name,  &value, ATTACH_ON_DEMAND);
+  bool res = CommandLineFlags::uintxAtPut((char*)name, &value, ATTACH_ON_DEMAND);
+  if (! res) {
+    out->print_cr("setting flag %s failed", name);
+  }
+
+  return res? JNI_OK : JNI_ERR;
+}
+
+// set a uint64_t global flag using value from AttachOperation
+static jint set_uint64_t_flag(const char* name, AttachOperation* op, outputStream* out) {
+  uint64_t value;
+  const char* arg1;
+  if ((arg1 = op->arg(1)) != NULL) {
+    int n = sscanf(arg1, UINT64_FORMAT, &value);
+    if (n != 1) {
+      out->print_cr("flag value must be an unsigned 64-bit integer");
+      return JNI_ERR;
+    }
+  }
+  bool res = CommandLineFlags::uint64_tAtPut((char*)name, &value, ATTACH_ON_DEMAND);
   if (! res) {
     out->print_cr("setting flag %s failed", name);
   }
@@ -261,10 +280,10 @@
 static jint set_ccstr_flag(const char* name, AttachOperation* op, outputStream* out) {
   const char* value;
   if ((value = op->arg(1)) == NULL) {
-    out->print_cr("flag value has to be a string");
+    out->print_cr("flag value must be a string");
     return JNI_ERR;
   }
-  bool res = CommandLineFlags::ccstrAtPut((char*)name,  &value, ATTACH_ON_DEMAND);
+  bool res = CommandLineFlags::ccstrAtPut((char*)name, &value, ATTACH_ON_DEMAND);
   if (res) {
     FREE_C_HEAP_ARRAY(char, value);
   } else {
@@ -291,6 +310,8 @@
       return set_intx_flag(name, op, out);
     } else if (f->is_uintx()) {
       return set_uintx_flag(name, op, out);
+    } else if (f->is_uint64_t()) {
+      return set_uint64_t_flag(name, op, out);
     } else if (f->is_ccstr()) {
       return set_ccstr_flag(name, op, out);
     } else {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/services/g1MemoryPool.cpp	Wed Jul 05 17:04:56 2017 +0200
@@ -0,0 +1,162 @@
+/*
+ * Copyright (c) 2007 Sun Microsystems, Inc.  All Rights Reserved.
+ * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ *
+ */
+
+# include "incls/_precompiled.incl"
+# include "incls/_g1MemoryPool.cpp.incl"
+
+G1MemoryPoolSuper::G1MemoryPoolSuper(G1CollectedHeap* g1h,
+                                     const char* name,
+                                     size_t init_size,
+                                     size_t max_size,
+                                     bool support_usage_threshold) :
+  _g1h(g1h), CollectedMemoryPool(name,
+                                 MemoryPool::Heap,
+                                 init_size,
+                                 max_size,
+                                 support_usage_threshold) {
+  assert(UseG1GC, "sanity");
+}
+
+// See the comment at the top of g1MemoryPool.hpp
+size_t G1MemoryPoolSuper::eden_space_committed(G1CollectedHeap* g1h) {
+  return MAX2(eden_space_used(g1h), (size_t) HeapRegion::GrainBytes);
+}
+
+// See the comment at the top of g1MemoryPool.hpp
+size_t G1MemoryPoolSuper::eden_space_used(G1CollectedHeap* g1h) {
+  size_t young_list_length = g1h->young_list_length();
+  size_t eden_used = young_list_length * HeapRegion::GrainBytes;
+  size_t survivor_used = survivor_space_used(g1h);
+  eden_used = subtract_up_to_zero(eden_used, survivor_used);
+  return eden_used;
+}
+
+// See the comment at the top of g1MemoryPool.hpp
+size_t G1MemoryPoolSuper::eden_space_max(G1CollectedHeap* g1h) {
+  // This should ensure that it returns a value no smaller than the
+  // region size. Currently, eden_space_committed() guarantees that.
+  return eden_space_committed(g1h);
+}
+
+// See the comment at the top of g1MemoryPool.hpp
+size_t G1MemoryPoolSuper::survivor_space_committed(G1CollectedHeap* g1h) {
+  return MAX2(survivor_space_used(g1h), (size_t) HeapRegion::GrainBytes);
+}
+
+// See the comment at the top of g1MemoryPool.hpp
+size_t G1MemoryPoolSuper::survivor_space_used(G1CollectedHeap* g1h) {
+  size_t survivor_num = g1h->g1_policy()->recorded_survivor_regions();
+  size_t survivor_used = survivor_num * HeapRegion::GrainBytes;
+  return survivor_used;
+}
+
+// See the comment at the top of g1MemoryPool.hpp
+size_t G1MemoryPoolSuper::survivor_space_max(G1CollectedHeap* g1h) {
+  // This should ensure that it returns a value no smaller than the
+  // region size. Currently, survivor_space_committed() guarantees that.
+  return survivor_space_committed(g1h);
+}
+
+// See the comment at the top of g1MemoryPool.hpp
+size_t G1MemoryPoolSuper::old_space_committed(G1CollectedHeap* g1h) {
+  size_t committed = overall_committed(g1h);
+  size_t eden_committed = eden_space_committed(g1h);
+  size_t survivor_committed = survivor_space_committed(g1h);
+  committed = subtract_up_to_zero(committed, eden_committed);
+  committed = subtract_up_to_zero(committed, survivor_committed);
+  committed = MAX2(committed, (size_t) HeapRegion::GrainBytes);
+  return committed;
+}
+
+// See the comment at the top of g1MemoryPool.hpp
+size_t G1MemoryPoolSuper::old_space_used(G1CollectedHeap* g1h) {
+  size_t used = overall_used(g1h);
+  size_t eden_used = eden_space_used(g1h);
+  size_t survivor_used = survivor_space_used(g1h);
+  used = subtract_up_to_zero(used, eden_used);
+  used = subtract_up_to_zero(used, survivor_used);
+  return used;
+}
+
+// See the comment at the top of g1MemoryPool.hpp
+size_t G1MemoryPoolSuper::old_space_max(G1CollectedHeap* g1h) {
+  size_t max = overall_max(g1h);
+  size_t eden_max = eden_space_max(g1h);
+  size_t survivor_max = survivor_space_max(g1h);
+  max = subtract_up_to_zero(max, eden_max);
+  max = subtract_up_to_zero(max, survivor_max);
+  max = MAX2(max, (size_t) HeapRegion::GrainBytes);
+  return max;
+}
+
+G1EdenPool::G1EdenPool(G1CollectedHeap* g1h) :
+  G1MemoryPoolSuper(g1h,
+                    "G1 Eden",
+                    eden_space_committed(g1h), /* init_size */
+                    eden_space_max(g1h), /* max_size */
+                    false /* support_usage_threshold */) {
+}
+
+MemoryUsage G1EdenPool::get_memory_usage() {
+  size_t initial_sz = initial_size();
+  size_t max_sz     = max_size();
+  size_t used       = used_in_bytes();
+  size_t committed  = eden_space_committed(_g1h);
+
+  return MemoryUsage(initial_sz, used, committed, max_sz);
+}
+
+G1SurvivorPool::G1SurvivorPool(G1CollectedHeap* g1h) :
+  G1MemoryPoolSuper(g1h,
+                    "G1 Survivor",
+                    survivor_space_committed(g1h), /* init_size */
+                    survivor_space_max(g1h), /* max_size */
+                    false /* support_usage_threshold */) {
+}
+
+MemoryUsage G1SurvivorPool::get_memory_usage() {
+  size_t initial_sz = initial_size();
+  size_t max_sz     = max_size();
+  size_t used       = used_in_bytes();
+  size_t committed  = survivor_space_committed(_g1h);
+
+  return MemoryUsage(initial_sz, used, committed, max_sz);
+}
+
+G1OldGenPool::G1OldGenPool(G1CollectedHeap* g1h) :
+  G1MemoryPoolSuper(g1h,
+                    "G1 Old Gen",
+                    old_space_committed(g1h), /* init_size */
+                    old_space_max(g1h), /* max_size */
+                    true /* support_usage_threshold */) {
+}
+
+MemoryUsage G1OldGenPool::get_memory_usage() {
+  size_t initial_sz = initial_size();
+  size_t max_sz     = max_size();
+  size_t used       = used_in_bytes();
+  size_t committed  = old_space_committed(_g1h);
+
+  return MemoryUsage(initial_sz, used, committed, max_sz);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/services/g1MemoryPool.hpp	Wed Jul 05 17:04:56 2017 +0200
@@ -0,0 +1,197 @@
+/*
+ * Copyright (c) 2007 Sun Microsystems, Inc.  All Rights Reserved.
+ * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ *
+ */
+
+class G1CollectedHeap;
+
+// This file contains the three classes that represent the memory
+// pools of the G1 spaces: G1EdenPool, G1SurvivorPool, and
+// G1OldGenPool. In G1, unlike our other GCs, we do not have a
+// physical space for each of those spaces. Instead, we allocate
+// regions for all three spaces out of a single pool of regions (that
+// pool basically covers the entire heap). As a result, the eden,
+// survivor, and old gen are considered logical spaces in G1, as each
+// is a set of non-contiguous regions. This is also reflected in the
+// way we map them to memory pools here. The easiest way to have done
+// this would have been to map the entire G1 heap to a single memory
+// pool. However, it's helpful to show how large the eden and survivor
+// get, as this does affect the performance and behavior of G1. Which
+// is why we introduce the three memory pools implemented here.
+//
+// The above approach inroduces a couple of challenging issues in the
+// implementation of the three memory pools:
+//
+// 1) The used space calculation for a pool is not necessarily
+// independent of the others. We can easily get from G1 the overall
+// used space in the entire heap, the number of regions in the young
+// generation (includes both eden and survivors), and the number of
+// survivor regions. So, from that we calculate:
+//
+//  survivor_used = survivor_num * region_size
+//  eden_used     = young_region_num * region_size - survivor_used
+//  old_gen_used  = overall_used - eden_used - survivor_used
+//
+// Note that survivor_used and eden_used are upper bounds. To get the
+// actual value we would have to iterate over the regions and add up
+// ->used(). But that'd be expensive. So, we'll accept some lack of
+// accuracy for those two. But, we have to be careful when calculating
+// old_gen_used, in case we subtract from overall_used more then the
+// actual number and our result goes negative.
+//
+// 2) Calculating the used space is straightforward, as described
+// above. However, how do we calculate the committed space, given that
+// we allocate space for the eden, survivor, and old gen out of the
+// same pool of regions? One way to do this is to use the used value
+// as also the committed value for the eden and survivor spaces and
+// then calculate the old gen committed space as follows:
+//
+//  old_gen_committed = overall_committed - eden_committed - survivor_committed
+//
+// Maybe a better way to do that would be to calculate used for eden
+// and survivor as a sum of ->used() over their regions and then
+// calculate committed as region_num * region_size (i.e., what we use
+// to calculate the used space now). This is something to consider
+// in the future.
+//
+// 3) Another decision that is again not straightforward is what is
+// the max size that each memory pool can grow to. Right now, we set
+// that the committed size for the eden and the survivors and
+// calculate the old gen max as follows (basically, it's a similar
+// pattern to what we use for the committed space, as described
+// above):
+//
+//  old_gen_max = overall_max - eden_max - survivor_max
+//
+// 4) Now, there is a very subtle issue with all the above. The
+// framework will call get_memory_usage() on the three pools
+// asynchronously. As a result, each call might get a different value
+// for, say, survivor_num which will yield inconsistent values for
+// eden_used, survivor_used, and old_gen_used (as survivor_num is used
+// in the calculation of all three). This would normally be
+// ok. However, it's possible that this might cause the sum of
+// eden_used, survivor_used, and old_gen_used to go over the max heap
+// size and this seems to sometimes cause JConsole (and maybe other
+// clients) to get confused. There's not a really an easy / clean
+// solution to this problem, due to the asynchrounous nature of the
+// framework.
+
+
+// This class is shared by the three G1 memory pool classes
+// (G1EdenPool, G1SurvivorPool, G1OldGenPool). Given that the way we
+// calculate used / committed bytes for these three pools is related
+// (see comment above), we put the calculations in this class so that
+// we can easily share them among the subclasses.
+class G1MemoryPoolSuper : public CollectedMemoryPool {
+private:
+  // It returns x - y if x > y, 0 otherwise.
+  // As described in the comment above, some of the inputs to the
+  // calculations we have to do are obtained concurrently and hence
+  // may be inconsistent with each other. So, this provides a
+  // defensive way of performing the subtraction and avoids the value
+  // going negative (which would mean a very large result, given that
+  // the parameter are size_t).
+  static size_t subtract_up_to_zero(size_t x, size_t y) {
+    if (x > y) {
+      return x - y;
+    } else {
+      return 0;
+    }
+  }
+
+protected:
+  G1CollectedHeap* _g1h;
+
+  // Would only be called from subclasses.
+  G1MemoryPoolSuper(G1CollectedHeap* g1h,
+                    const char* name,
+                    size_t init_size,
+                    size_t max_size,
+                    bool support_usage_threshold);
+
+  // The reason why all the code is in static methods is so that it
+  // can be safely called from the constructors of the subclasses.
+
+  static size_t overall_committed(G1CollectedHeap* g1h) {
+    return g1h->capacity();
+  }
+  static size_t overall_used(G1CollectedHeap* g1h) {
+    return g1h->used_unlocked();
+  }
+  static size_t overall_max(G1CollectedHeap* g1h) {
+    return g1h->g1_reserved_obj_bytes();
+  }
+
+  static size_t eden_space_committed(G1CollectedHeap* g1h);
+  static size_t eden_space_used(G1CollectedHeap* g1h);
+  static size_t eden_space_max(G1CollectedHeap* g1h);
+
+  static size_t survivor_space_committed(G1CollectedHeap* g1h);
+  static size_t survivor_space_used(G1CollectedHeap* g1h);
+  static size_t survivor_space_max(G1CollectedHeap* g1h);
+
+  static size_t old_space_committed(G1CollectedHeap* g1h);
+  static size_t old_space_used(G1CollectedHeap* g1h);
+  static size_t old_space_max(G1CollectedHeap* g1h);
+};
+
+// Memory pool that represents the G1 eden.
+class G1EdenPool : public G1MemoryPoolSuper {
+public:
+  G1EdenPool(G1CollectedHeap* g1h);
+
+  size_t used_in_bytes() {
+    return eden_space_used(_g1h);
+  }
+  size_t max_size() const {
+    return eden_space_max(_g1h);
+  }
+  MemoryUsage get_memory_usage();
+};
+
+// Memory pool that represents the G1 survivor.
+class G1SurvivorPool : public G1MemoryPoolSuper {
+public:
+  G1SurvivorPool(G1CollectedHeap* g1h);
+
+  size_t used_in_bytes() {
+    return survivor_space_used(_g1h);
+  }
+  size_t max_size() const {
+    return survivor_space_max(_g1h);
+  }
+  MemoryUsage get_memory_usage();
+};
+
+// Memory pool that represents the G1 old gen.
+class G1OldGenPool : public G1MemoryPoolSuper {
+public:
+  G1OldGenPool(G1CollectedHeap* g1h);
+
+  size_t used_in_bytes() {
+    return old_space_used(_g1h);
+  }
+  size_t max_size() const {
+    return old_space_max(_g1h);
+  }
+  MemoryUsage get_memory_usage();
+};
--- a/hotspot/src/share/vm/services/management.cpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/share/vm/services/management.cpp	Wed Jul 05 17:04:56 2017 +0200
@@ -790,7 +790,7 @@
   assert(!has_undefined_init_size, "Undefined init size");
   assert(!has_undefined_max_size, "Undefined max size");
 
-  MemoryUsage usage((heap ? Arguments::initial_heap_size() : total_init),
+  MemoryUsage usage((heap ? InitialHeapSize : total_init),
                     total_used,
                     total_committed,
                     (heap ? Universe::heap()->max_capacity() : total_max));
@@ -1507,16 +1507,17 @@
   return (jobjectArray)JNIHandles::make_local(env, flags_ah());
 JVM_END
 
-// utility function used by jmm_GetVMGlobals
-void add_global_entry(JNIEnv* env, Handle name, jmmVMGlobal *global, Flag *flag, TRAPS) {
+// Utility function used by jmm_GetVMGlobals.  Returns false if flag type
+// can't be determined, true otherwise.  If false is returned, then *global
+// will be incomplete and invalid.
+bool add_global_entry(JNIEnv* env, Handle name, jmmVMGlobal *global, Flag *flag, TRAPS) {
   Handle flag_name;
   if (name() == NULL) {
-    flag_name = java_lang_String::create_from_str(flag->name, CHECK);
+    flag_name = java_lang_String::create_from_str(flag->name, CHECK_false);
   } else {
     flag_name = name;
   }
   global->name = (jstring)JNIHandles::make_local(env, flag_name());
-  global->type = JMM_VMGLOBAL_TYPE_UNKNOWN;
 
   if (flag->is_bool()) {
     global->value.z = flag->get_bool() ? JNI_TRUE : JNI_FALSE;
@@ -1527,10 +1528,17 @@
   } else if (flag->is_uintx()) {
     global->value.j = (jlong)flag->get_uintx();
     global->type = JMM_VMGLOBAL_TYPE_JLONG;
+  } else if (flag->is_uint64_t()) {
+    global->value.j = (jlong)flag->get_uint64_t();
+    global->type = JMM_VMGLOBAL_TYPE_JLONG;
   } else if (flag->is_ccstr()) {
-    Handle str = java_lang_String::create_from_str(flag->get_ccstr(), CHECK);
+    Handle str = java_lang_String::create_from_str(flag->get_ccstr(), CHECK_false);
     global->value.l = (jobject)JNIHandles::make_local(env, str());
     global->type = JMM_VMGLOBAL_TYPE_JSTRING;
+  } else {
+    global->type = JMM_VMGLOBAL_TYPE_UNKNOWN;
+    assert(false, "Unsupported VMGlobal Type");
+    return false;
   }
 
   global->writeable = flag->is_writeable();
@@ -1557,6 +1565,8 @@
     default:
       global->origin = JMM_VMGLOBAL_ORIGIN_OTHER;
   }
+
+  return true;
 }
 
 // Fill globals array of count length with jmmVMGlobal entries
@@ -1599,8 +1609,8 @@
       Handle sh(THREAD, s);
       char* str = java_lang_String::as_utf8_string(s);
       Flag* flag = Flag::find_flag(str, strlen(str));
-      if (flag != NULL) {
-        add_global_entry(env, sh, &globals[i], flag, THREAD);
+      if (flag != NULL &&
+          add_global_entry(env, sh, &globals[i], flag, THREAD)) {
         num_entries++;
       } else {
         globals[i].name = NULL;
@@ -1617,8 +1627,8 @@
     for (int i = 0; i < nFlags && num_entries < count;  i++) {
       Flag* flag = &Flag::flags[i];
       // Exclude the locked (diagnostic, experimental) flags
-      if (flag->is_unlocked() || flag->is_unlocker()) {
-        add_global_entry(env, null_h, &globals[num_entries], flag, THREAD);
+      if ((flag->is_unlocked() || flag->is_unlocker()) &&
+          add_global_entry(env, null_h, &globals[num_entries], flag, THREAD)) {
         num_entries++;
       }
     }
@@ -1650,11 +1660,14 @@
     bool bvalue = (new_value.z == JNI_TRUE ? true : false);
     succeed = CommandLineFlags::boolAtPut(name, &bvalue, MANAGEMENT);
   } else if (flag->is_intx()) {
-    intx ivalue = new_value.j;
+    intx ivalue = (intx)new_value.j;
     succeed = CommandLineFlags::intxAtPut(name, &ivalue, MANAGEMENT);
   } else if (flag->is_uintx()) {
-    uintx uvalue = new_value.j;
+    uintx uvalue = (uintx)new_value.j;
     succeed = CommandLineFlags::uintxAtPut(name, &uvalue, MANAGEMENT);
+  } else if (flag->is_uint64_t()) {
+    uint64_t uvalue = (uint64_t)new_value.j;
+    succeed = CommandLineFlags::uint64_tAtPut(name, &uvalue, MANAGEMENT);
   } else if (flag->is_ccstr()) {
     oop str = JNIHandles::resolve_external_guard(new_value.l);
     if (str == NULL) {
--- a/hotspot/src/share/vm/services/memoryManager.cpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/share/vm/services/memoryManager.cpp	Wed Jul 05 17:04:56 2017 +0200
@@ -72,6 +72,14 @@
   return (GCMemoryManager*) new PSMarkSweepMemoryManager();
 }
 
+GCMemoryManager* MemoryManager::get_g1YoungGen_memory_manager() {
+  return (GCMemoryManager*) new G1YoungGenMemoryManager();
+}
+
+GCMemoryManager* MemoryManager::get_g1OldGen_memory_manager() {
+  return (GCMemoryManager*) new G1OldGenMemoryManager();
+}
+
 instanceOop MemoryManager::get_memory_manager_instance(TRAPS) {
   // Must do an acquire so as to force ordering of subsequent
   // loads from anything _memory_mgr_obj points to or implies.
--- a/hotspot/src/share/vm/services/memoryManager.hpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/share/vm/services/memoryManager.hpp	Wed Jul 05 17:04:56 2017 +0200
@@ -54,7 +54,9 @@
     ParNew,
     ConcurrentMarkSweep,
     PSScavenge,
-    PSMarkSweep
+    PSMarkSweep,
+    G1YoungGen,
+    G1OldGen
   };
 
   MemoryManager();
@@ -85,6 +87,8 @@
   static GCMemoryManager* get_cms_memory_manager();
   static GCMemoryManager* get_psScavenge_memory_manager();
   static GCMemoryManager* get_psMarkSweep_memory_manager();
+  static GCMemoryManager* get_g1YoungGen_memory_manager();
+  static GCMemoryManager* get_g1OldGen_memory_manager();
 
 };
 
@@ -231,3 +235,21 @@
   MemoryManager::Name kind() { return MemoryManager::PSMarkSweep; }
   const char* name()         { return "PS MarkSweep"; }
 };
+
+class G1YoungGenMemoryManager : public GCMemoryManager {
+private:
+public:
+  G1YoungGenMemoryManager() : GCMemoryManager() {}
+
+  MemoryManager::Name kind() { return MemoryManager::G1YoungGen; }
+  const char* name()         { return "G1 Young Generation"; }
+};
+
+class G1OldGenMemoryManager : public GCMemoryManager {
+private:
+public:
+  G1OldGenMemoryManager() : GCMemoryManager() {}
+
+  MemoryManager::Name kind() { return MemoryManager::G1OldGen; }
+  const char* name()         { return "G1 Old Generation"; }
+};
--- a/hotspot/src/share/vm/services/memoryService.cpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/share/vm/services/memoryService.cpp	Wed Jul 05 17:04:56 2017 +0200
@@ -60,8 +60,8 @@
       break;
     }
     case CollectedHeap::G1CollectedHeap : {
-      G1CollectedHeap::g1_unimplemented();
-      return;
+      add_g1_heap_info(G1CollectedHeap::heap());
+      break;
     }
 #endif // SERIALGC
     default: {
@@ -164,6 +164,19 @@
   add_psOld_memory_pool(heap->old_gen(), _major_gc_manager);
   add_psPerm_memory_pool(heap->perm_gen(), _major_gc_manager);
 }
+
+void MemoryService::add_g1_heap_info(G1CollectedHeap* g1h) {
+  assert(UseG1GC, "sanity");
+
+  _minor_gc_manager = MemoryManager::get_g1YoungGen_memory_manager();
+  _major_gc_manager = MemoryManager::get_g1OldGen_memory_manager();
+  _managers_list->append(_minor_gc_manager);
+  _managers_list->append(_major_gc_manager);
+
+  add_g1YoungGen_memory_pool(g1h, _major_gc_manager, _minor_gc_manager);
+  add_g1OldGen_memory_pool(g1h, _major_gc_manager);
+  add_g1PermGen_memory_pool(g1h, _major_gc_manager);
+}
 #endif // SERIALGC
 
 MemoryPool* MemoryService::add_gen(Generation* gen,
@@ -384,6 +397,64 @@
   mgr->add_pool(perm_gen);
   _pools_list->append(perm_gen);
 }
+
+void MemoryService::add_g1YoungGen_memory_pool(G1CollectedHeap* g1h,
+                                               MemoryManager* major_mgr,
+                                               MemoryManager* minor_mgr) {
+  assert(major_mgr != NULL && minor_mgr != NULL, "should have two managers");
+
+  G1EdenPool* eden = new G1EdenPool(g1h);
+  G1SurvivorPool* survivor = new G1SurvivorPool(g1h);
+
+  major_mgr->add_pool(eden);
+  major_mgr->add_pool(survivor);
+  minor_mgr->add_pool(eden);
+  minor_mgr->add_pool(survivor);
+  _pools_list->append(eden);
+  _pools_list->append(survivor);
+}
+
+void MemoryService::add_g1OldGen_memory_pool(G1CollectedHeap* g1h,
+                                             MemoryManager* mgr) {
+  assert(mgr != NULL, "should have one manager");
+
+  G1OldGenPool* old_gen = new G1OldGenPool(g1h);
+  mgr->add_pool(old_gen);
+  _pools_list->append(old_gen);
+}
+
+void MemoryService::add_g1PermGen_memory_pool(G1CollectedHeap* g1h,
+                                              MemoryManager* mgr) {
+  assert(mgr != NULL, "should have one manager");
+
+  CompactingPermGenGen* perm_gen = (CompactingPermGenGen*) g1h->perm_gen();
+  PermanentGenerationSpec* spec = perm_gen->spec();
+  size_t max_size = spec->max_size() - spec->read_only_size()
+                                     - spec->read_write_size();
+  MemoryPool* pool = add_space(perm_gen->unshared_space(),
+                               "G1 Perm Gen",
+                               false, /* is_heap */
+                               max_size,
+                               true   /* support_usage_threshold */);
+  mgr->add_pool(pool);
+
+  // in case we support CDS in G1
+  if (UseSharedSpaces) {
+    pool = add_space(perm_gen->ro_space(),
+                     "G1 Perm Gen [shared-ro]",
+                     false, /* is_heap */
+                     spec->read_only_size(),
+                     true   /* support_usage_threshold */);
+    mgr->add_pool(pool);
+
+    pool = add_space(perm_gen->rw_space(),
+                     "G1 Perm Gen [shared-rw]",
+                     false, /* is_heap */
+                     spec->read_write_size(),
+                     true   /* support_usage_threshold */);
+    mgr->add_pool(pool);
+  }
+}
 #endif // SERIALGC
 
 void MemoryService::add_code_heap_memory_pool(CodeHeap* heap) {
--- a/hotspot/src/share/vm/services/memoryService.hpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/share/vm/services/memoryService.hpp	Wed Jul 05 17:04:56 2017 +0200
@@ -40,6 +40,7 @@
 class ParallelScavengeHeap;
 class CompactingPermGenGen;
 class CMSPermGenGen;
+class G1CollectedHeap;
 
 // VM Monitoring and Management Support
 
@@ -88,6 +89,13 @@
   static void add_psPerm_memory_pool(PSPermGen* perm,
                                      MemoryManager* mgr);
 
+  static void add_g1YoungGen_memory_pool(G1CollectedHeap* g1h,
+                                         MemoryManager* major_mgr,
+                                         MemoryManager* minor_mgr);
+  static void add_g1OldGen_memory_pool(G1CollectedHeap* g1h,
+                                       MemoryManager* mgr);
+  static void add_g1PermGen_memory_pool(G1CollectedHeap* g1h,
+                                        MemoryManager* mgr);
 
   static MemoryPool* add_space(ContiguousSpace* space,
                                const char* name,
@@ -111,6 +119,7 @@
 
   static void add_gen_collected_heap_info(GenCollectedHeap* heap);
   static void add_parallel_scavenge_heap_info(ParallelScavengeHeap* heap);
+  static void add_g1_heap_info(G1CollectedHeap* g1h);
 
 public:
   static void set_universe_heap(CollectedHeap* heap);
--- a/hotspot/src/share/vm/utilities/growableArray.hpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/share/vm/utilities/growableArray.hpp	Wed Jul 05 17:04:56 2017 +0200
@@ -278,6 +278,17 @@
     _len--;
   }
 
+  // inserts the given element before the element at index i
+  void insert_before(const int idx, const E& elem) {
+    check_nesting();
+    if (_len == _max) grow(_len);
+    for (int j = _len - 1; j >= idx; j--) {
+      _data[j + 1] = _data[j];
+    }
+    _len++;
+    _data[idx] = elem;
+  }
+
   void appendAll(const GrowableArray<E>* l) {
     for (int i = 0; i < l->_len; i++) {
       raw_at_put_grow(_len, l->_data[i], 0);
--- a/hotspot/src/share/vm/utilities/numberSeq.cpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/share/vm/utilities/numberSeq.cpp	Wed Jul 05 17:04:56 2017 +0200
@@ -241,3 +241,33 @@
 
   return b0 + b1 * num;
 }
+
+
+// Printing/Debugging Support
+
+void AbsSeq::dump() { dump_on(gclog_or_tty); }
+
+void AbsSeq::dump_on(outputStream* s) {
+  s->print_cr("\t _num = %d, _sum = %7.3f, _sum_of_squares = %7.3f",
+                  _num,      _sum,         _sum_of_squares);
+  s->print_cr("\t _davg = %7.3f, _dvariance = %7.3f, _alpha = %7.3f",
+                  _davg,         _dvariance,         _alpha);
+}
+
+void NumberSeq::dump_on(outputStream* s) {
+  AbsSeq::dump_on(s);
+  s->print_cr("\t\t _last = %7.3f, _maximum = %7.3f");
+}
+
+void TruncatedSeq::dump_on(outputStream* s) {
+  AbsSeq::dump_on(s);
+  s->print_cr("\t\t _length = %d, _next = %d", _length, _next);
+  for (int i = 0; i < _length; i++) {
+    if (i%5 == 0) {
+      s->cr();
+      s->print("\t");
+    }
+    s->print("\t[%d]=%7.3f", i, _sequence[i]);
+  }
+  s->print_cr("");
+}
--- a/hotspot/src/share/vm/utilities/numberSeq.hpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/share/vm/utilities/numberSeq.hpp	Wed Jul 05 17:04:56 2017 +0200
@@ -74,6 +74,10 @@
   double davg() const; // decaying average
   double dvariance() const; // decaying variance
   double dsd() const; // decaying "standard deviation"
+
+  // Debugging/Printing
+  virtual void dump();
+  virtual void dump_on(outputStream* s);
 };
 
 class NumberSeq: public AbsSeq {
@@ -91,6 +95,9 @@
   virtual void add(double val);
   virtual double maximum() const { return _maximum; }
   virtual double last() const { return _last; }
+
+  // Debugging/Printing
+  virtual void dump_on(outputStream* s);
 };
 
 class TruncatedSeq: public AbsSeq {
@@ -114,4 +121,7 @@
 
   double oldest() const; // the oldest valid value in the sequence
   double predict_next() const; // prediction based on linear regression
+
+  // Debugging/Printing
+  virtual void dump_on(outputStream* s);
 };
--- a/hotspot/src/share/vm/utilities/vmError.cpp	Thu Dec 17 14:10:20 2009 -0800
+++ b/hotspot/src/share/vm/utilities/vmError.cpp	Wed Jul 05 17:04:56 2017 +0200
@@ -502,6 +502,23 @@
 #endif // ZERO
      }
 
+  STEP(135, "(printing target Java thread stack)" )
+
+     // printing Java thread stack trace if it is involved in GC crash
+     if (_verbose && (_thread->is_Named_thread())) {
+       JavaThread*  jt = ((NamedThread *)_thread)->processed_thread();
+       if (jt != NULL) {
+         st->print_cr("JavaThread " PTR_FORMAT " (nid = " UINTX_FORMAT ") was being processed", jt, jt->osthread()->thread_id());
+         if (jt->has_last_Java_frame()) {
+           st->print_cr("Java frames: (J=compiled Java code, j=interpreted, Vv=VM code)");
+           for(StackFrameStream sfs(jt); !sfs.is_done(); sfs.next()) {
+             sfs.current()->print_on_error(st, buf, sizeof(buf), true);
+             st->cr();
+           }
+         }
+       }
+     }
+
   STEP(140, "(printing VM operation)" )
 
      if (_verbose && _thread && _thread->is_VM_thread()) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/6769124/TestArrayCopy6769124.java	Wed Jul 05 17:04:56 2017 +0200
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ *
+ */
+
+/**
+ * @test
+ * @bug 6769124
+ * @summary arraycopy may crash the VM with c1 on 64 bit
+ */
+
+public class TestArrayCopy6769124 {
+
+    public static void main(String[] args) {
+
+        int k = 1 << 31;
+
+
+        for(int j = 0; j <1000000; j++) {
+            int i = -1;
+            while(i < 10) {
+                i++;
+            }
+
+            int m = k * i;
+
+            int[] O1 = new int[20];
+            int[] O2 = new int[20];
+
+            System.arraycopy(O1, i, O2, i, 1); //will crash on amd64
+            System.arraycopy(O1, m, O2, m, 1); //will crash on sparcv9
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/6769124/TestDeoptInt6769124.java	Wed Jul 05 17:04:56 2017 +0200
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ *
+ */
+
+/**
+ * @test
+ * @bug 6769124
+ * @summary int value might not be correctly decoded on deopt with c1 on 64 bit
+ *
+ * @run main/othervm -Xcomp -XX:CompileOnly=TestDeoptInt6769124.m TestDeoptInt6769124
+ */
+
+public class TestDeoptInt6769124 {
+
+    static class A {
+        volatile int vl;
+        A(int v) {
+            vl = v;
+        }
+    }
+
+    static void m(int b) {
+        A a = new A(10);
+        int c;
+        c = b + a.vl; //accessing volatile field of class not loaded at compile time forces a deopt
+        if(c != 20) {
+            System.out.println("a (= " + a.vl + ") + b (= " + b + ") = c (= " + c + ") != 20");
+            throw new InternalError();
+        }
+    }
+
+    public static void main(String[] args) {
+        m(10);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/6769124/TestUnalignedLoad6769124.java	Wed Jul 05 17:04:56 2017 +0200
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ *
+ */
+
+/**
+ * @test
+ * @bug 6769124
+ * @summary unaligned load may fail with c1 on 64 bit
+ */
+
+public class TestUnalignedLoad6769124 {
+
+    static long l1v = 0x200000003L;
+    static long l2v = 0x400000005L;
+    static double d1v = Double.MAX_VALUE;
+    static double d2v = Double.MIN_VALUE;
+
+    public static void main(String[] args) {
+        long l1 = l1v;
+        double d1 = d1v;
+        long l2 = l2v;
+        double d2 = d2v;
+
+        // Run long enough to induce an OSR
+        for (int i = 0; i < 10000000; i++) {
+        }
+        boolean error = false;
+
+        if (l1 != l1v) {
+            System.out.println(l1 + " != " + l1v);
+            error = true;
+        }
+        if (l2 != l2v) {
+            System.out.println(l2 + " != " + l2v);
+            error = true;
+        }
+        if (d1 != d1v) {
+            System.out.println(d1 + " != " + d1v);
+            error = true;
+        }
+        if (d2 != d2v) {
+            System.out.println(d2 + " != " + d2v);
+            error = true;
+        }
+        if (error) {
+            throw new InternalError();
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/6852078/Test6852078.java	Wed Jul 05 17:04:56 2017 +0200
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ *
+ */
+
+/**
+ * @test
+ * @bug 6852078
+ * @summary Disable SuperWord optimization for unsafe read/write
+ *
+ * @run main/othervm Test6852078
+ */
+
+import java.util.*;
+import java.nio.ByteBuffer;
+import com.sun.corba.se.impl.encoding.ByteBufferWithInfo;
+import com.sun.jndi.toolkit.corba.CorbaUtils;
+
+public class Test6852078 {
+
+    public Test6852078(String [] args) {
+
+        int capacity = 128;
+        ByteBuffer bb = ByteBuffer.allocateDirect(capacity);
+        ByteBufferWithInfo bbwi = new ByteBufferWithInfo( CorbaUtils.getOrb(null, -1, new Hashtable()), bb);
+        byte[] tmpBuf;
+        tmpBuf = new byte[bbwi.buflen];
+
+        for (int i = 0; i < capacity; i++)
+            tmpBuf[i] = bbwi.byteBuffer.get(i);
+    }
+
+    public static void main(String [] args) {
+        for (int i=0; i<2000; i++) {
+            Test6852078 t = new Test6852078(args);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/6895383/Test.java	Wed Jul 05 17:04:56 2017 +0200
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ *
+ */
+
+/**
+ * @test
+ * @bug 6895383
+ * @summary JCK test throws NPE for method compiled with Escape Analysis
+ *
+ * @run main/othervm -Xcomp Test
+ */
+
+public class Test {
+    public static void main(String argv[]) {
+        Test test = new Test();
+        test.testRemove1_IndexOutOfBounds();
+        test.testAddAll1_IndexOutOfBoundsException();
+    }
+
+    public void testRemove1_IndexOutOfBounds() {
+        CopyOnWriteArrayList c = new CopyOnWriteArrayList();
+    }
+
+    public void testAddAll1_IndexOutOfBoundsException() {
+        try {
+            CopyOnWriteArrayList c = new CopyOnWriteArrayList();
+            c.addAll(-1, new LinkedList()); // should throw IndexOutOfBoundsException
+        } catch (IndexOutOfBoundsException e) {
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/6896727/Test.java	Wed Jul 05 17:04:56 2017 +0200
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ *
+ */
+
+/*
+ * @test
+ * @bug 6896727
+ * @summary nsk/logging/LoggingPermission/LoggingPermission/logperm002 fails with G1, EscapeAnalisys w/o COOPs
+ * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -Xcomp -XX:+DoEscapeAnalysis -XX:+UnlockExperimentalVMOptions -XX:+UseG1GC Test
+ */
+
+public class Test {
+
+    final static String testString = "abracadabra";
+    public static void main(String args[]) {
+        String params[][] = {
+            {"control", testString}
+        };
+        for (int i=0; i<params.length; i++) {
+            try {
+                System.out.println("Params :" + testString + " and " + params[i][0] + ", " + params[i][1]);
+                if (params[i][1] == null) {
+                    System.exit(97);
+                }
+            } catch (Exception e) {}
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/6901572/Test.java	Wed Jul 05 17:04:56 2017 +0200
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/**
+ * @test
+ * @bug 6901572
+ * @summary JVM 1.6.16 crash on loops: assert(has_node(i),"")
+ *
+ * @run main/othervm Test
+ */
+
+
+public class Test {
+
+    public static void main(String[] args) {
+        for (int i = 0; i < 2; i++)
+            NestedLoop();
+    }
+
+    public static long NestedLoop() {
+        final int n = 50;
+        long startTime = System.currentTimeMillis();
+        int x = 0;
+        for(int a = 0; a < n; a++)
+            for(int b = 0; b < n; b++)
+                for(int c = 0; c < n; c++)
+                    for(int d = 0; d < n; d++)
+                        for(int e = 0; e < n; e++)
+                            for(int f = 0; f < n; f++)
+                                x++;
+        long stopTime = System.currentTimeMillis();
+
+        return stopTime - startTime;
+    }
+}
--- a/jdk/.hgtags	Thu Dec 17 14:10:20 2009 -0800
+++ b/jdk/.hgtags	Wed Jul 05 17:04:56 2017 +0200
@@ -52,3 +52,4 @@
 8885b22565077236a927e824ef450742e434a230 jdk7-b75
 8fb602395be0f7d5af4e7e93b7df2d960faf9d17 jdk7-b76
 e6a5d095c356a547cf5b3c8885885aca5e91e09b jdk7-b77
+1143e498f813b8223b5e3a696d79da7ff7c25354 jdk7-b78
--- a/jdk/make/Makefile	Thu Dec 17 14:10:20 2009 -0800
+++ b/jdk/make/Makefile	Wed Jul 05 17:04:56 2017 +0200
@@ -74,6 +74,7 @@
 import_product    -- copy in the product components \n\
 import_fastdebug  -- copy in the fastdebug components \n\
 import_debug      -- copy in the debug components \n\
+modules           -- build the jdk and jre module images (experimental) \n\
 sccs_get          -- make sure all SCCS files are up-to-date (need SCCS) \n\
 create_links      -- create softlinks in Solaris 32bit build to 64bit dirs \n\
 "
@@ -257,6 +258,7 @@
 # Release engineering targets.
 #
 include $(BUILDDIR)/common/Release.gmk
+include $(BUILDDIR)/common/Modules.gmk
 
 #
 # Cscope targets.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/make/common/Modules.gmk	Wed Jul 05 17:04:56 2017 +0200
@@ -0,0 +1,442 @@
+#
+# Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
+# 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.  Sun designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+# CA 95054 USA or visit www.sun.com if you need additional information or
+# have any questions.
+#
+
+JDK_MODULE_IMAGE_DIR = $(ABS_OUTPUTDIR)/jdk-module-image
+JRE_MODULE_IMAGE_DIR = $(ABS_OUTPUTDIR)/jre-module-image
+
+#
+# modules   Target to build jdk and jre module image
+#
+#           There is one jar file per module containing classes only.
+#           All module jars are currently placed under jre/lib directory.
+#
+# Open issues that need further investigation:
+# 1. Classes in jre/lib/ext/dnsns.jar are currently put in jre/lib/jndi-dns
+#    module.
+# 2. Signed jars
+#    For JDK build, signed jars are copied to the build.
+#    All jars in the module image are unsigned.
+# 3. jre/lib/security/US_export_policy.jar and local_policy.jar
+#    are not included in the module image yet.
+
+MODULE_IMAGEBINDIR = bin
+
+#
+# Targets.
+#
+INITIAL_MODULE_IMAGE_JRE=initial-module-image-jre
+INITIAL_MODULE_IMAGE_JDK=initial-module-image-jdk
+ifeq ($(PLATFORM), solaris)
+  ifeq ($(ARCH_DATA_MODEL), 64)
+    INITIAL_MODULE_IMAGE_JRE=initial-module-image-jre-sol64
+    INITIAL_MODULE_IMAGE_JDK=initial-module-image-jdk-sol64
+  endif
+endif
+
+modules modules-clobber \
+initial-module-image-jre initial-module-image-jdk \
+initial-module-image-jre-sol64 initial-module-image-jdk-sol64 \
+trim-module-image-jre trim-module-image-jdk \
+process-module-image-jre process-module-image-jdk ::
+	@$(ECHO) ">>>Making "$@" @ `$(DATE)` ..."
+
+# Order is important here, trim jre after jdk image is created
+modules:: sanity-module-images post-sanity-module-images  \
+	 $(INITIAL_MODULE_IMAGE_JRE) $(INITIAL_MODULE_IMAGE_JDK) \
+	 trim-module-image-jre trim-module-image-jdk \
+	 process-module-image-jre process-module-image-jdk
+
+# Don't use these
+module-image-jre:: initial-module-image-jre trim-module-image-jre process-module-image-jre
+module-image-jdk:: initial-module-image-jdk trim-module-image-jdk process-module-image-jdk
+
+#
+# Paths to these files we need
+JDK_MODULE_LICENSES   = $(LICENSE_DOCLIST_JDK:%=$(JDK_MODULE_IMAGE_DIR)/%)
+JDK_MODULE_64_LICENSES = $(LICENSE_DOCLIST_JDK:%=$(JDK_MODULE_IMAGE_DIR)/%64)
+JDK_MODULE_DOCFILES   = $(OTHER_DOCLIST_JDK:%=$(JDK_MODULE_IMAGE_DIR)/%)
+
+JRE_MODULE_LICENSES   = $(LICENSE_DOCLIST_JRE:%=$(JRE_MODULE_IMAGE_DIR)/%)
+JRE_MODULE_64_LICENSES = $(LICENSE_DOCLIST_JRE:%=$(JRE_MODULE_IMAGE_DIR)/%64)
+JRE_MODULE_DOCFILES   = $(OTHER_DOCLIST_JRE:%=$(JRE_MODULE_IMAGE_DIR)/%)
+JRE_MODULE_DOCFILES  += $(JRE_NAMECHANGE_DOCLIST:%=$(JRE_MODULE_IMAGE_DIR)/%$(TEXT_SUFFIX))
+
+###### RULES
+
+# JDK files
+$(JDK_MODULE_IMAGE_DIR)/%: $(SHARE_JDK_DOC_SRC)/%
+	$(process-doc-file)
+# Removes LICENSE_VERSION or not
+ifdef LICENSE_VERSION
+$(JDK_MODULE_IMAGE_DIR)/%: $(SHARE_JDK_DOC_SRC)/%$(LICENSE_VERSION)
+	$(process-doc-file)
+$(JDK_MODULE_IMAGE_DIR)/%64: $(SHARE_JDK_DOC_SRC)/%$(LICENSE_VERSION)
+	$(process-doc-file)
+else
+$(JDK_MODULE_IMAGE_DIR)/%64: $(SHARE_JDK_DOC_SRC)/%
+	$(process-doc-file)
+endif
+
+# JRE files 
+$(JRE_MODULE_IMAGE_DIR)/%: $(SHARE_JRE_DOC_SRC)/%
+	$(process-doc-file)
+# Add $(TEXT_SUFFIX) suffix
+ifdef TEXT_SUFFIX
+$(JRE_MODULE_IMAGE_DIR)/%$(TEXT_SUFFIX): $(SHARE_JRE_DOC_SRC)/%
+	$(process-doc-file)
+endif
+# Removes LICENSE_VERSION or not
+ifdef LICENSE_VERSION
+$(JRE_MODULE_IMAGE_DIR)/%: $(SHARE_JRE_DOC_SRC)/%$(LICENSE_VERSION)
+	$(process-doc-file)
+$(JRE_MODULE_IMAGE_DIR)/%64: $(SHARE_JRE_DOC_SRC)/%$(LICENSE_VERSION)
+	$(process-doc-file)
+else
+$(JRE_MODULE_IMAGE_DIR)/%64: $(SHARE_JRE_DOC_SRC)/%
+	$(process-doc-file)
+endif
+
+######################################################
+# JRE Image
+######################################################
+
+MODULES_TEMPDIR=$(ABS_TEMPDIR)/modules
+MODULES_LIB = $(ABS_OUTPUTDIR)/modules
+
+gen-modules:
+	$(CD) modules; $(MAKE) all
+
+initial-module-image-jre-setup:
+	$(RM) -r $(JRE_MODULE_IMAGE_DIR)
+	$(MKDIR) -p $(JRE_MODULE_IMAGE_DIR)
+
+# 64-bit solaris jre image contains only the 64-bit add-on files.
+initial-module-image-jre-sol64:: initial-module-image-jre-setup \
+			  $(JRE_MODULE_LICENSES) $(JRE_MODULE_64_LICENSES)
+	@# Use tar instead of cp to preserve the symbolic links
+	for dir in bin lib ; do \
+	  ( $(CD) $(OUTPUTDIR) && \
+		$(TAR) cf - `$(FIND) $$dir -name '$(ARCH)' -print` | \
+		($(CD) $(JRE_MODULE_IMAGE_DIR) && $(TAR) xf -) ) ; \
+	done
+	@# Remove some files from the jre area
+	for t in $(NOTJRETOOLS) ; do \
+	    $(RM) $(JRE_MODULE_IMAGE_DIR)/bin$(ISA_DIR)/$$t ; \
+	done
+	$(RM) `$(FIND) $(JRE_MODULE_IMAGE_DIR)/lib -name 'orb.idl'`
+	$(RM) `$(FIND) $(JRE_MODULE_IMAGE_DIR)/lib -name 'ir.idl'`
+
+# Construct an initial jre image (initial jdk jre) no trimming or stripping
+initial-module-image-jre:: initial-module-image-jre-setup \
+		    $(JRE_LICENSES) $(JRE_MODULE_DOCFILES) \
+		    gen-modules \
+		    $(BUILDMETAINDEX_JARFILE)
+	@# Copy in bin directory
+	$(CD) $(OUTPUTDIR) && $(FIND) bin -depth | $(CPIO) -pdum $(JRE_MODULE_IMAGE_DIR)
+	@# CTE plugin security change require new empty directory lib/applet
+	$(MKDIR) -p $(JRE_MODULE_IMAGE_DIR)/lib/applet
+	@# Copy files but not .jar in lib directory 
+	$(CD) $(OUTPUTDIR) && $(FIND) lib -depth | $(EGREP) -v ".jar$$" | $(CPIO) -pdum $(JRE_MODULE_IMAGE_DIR)
+	@#
+	@# copy modules to jre/lib
+	@#
+	$(CP) -rf $(MODULES_LIB)/jre/lib/* $(JRE_MODULE_IMAGE_DIR)/lib 
+	@# Make sure all directories are read/execute for everyone
+	$(CHMOD) a+rx `$(FIND) $(JRE_MODULE_IMAGE_DIR) -type d`
+	@# Remove some files from the jre area
+	for t in $(NOTJRETOOLS) ; do \
+	    $(RM) $(JRE_MODULE_IMAGE_DIR)/bin$(ISA_DIR)/$$t ; \
+	done
+	@# Remove orb.idl and ir.idl from jre
+	$(FIND) $(JRE_MODULE_IMAGE_DIR)/lib -name 'orb.idl' -exec $(RM) \{} \;
+	$(FIND) $(JRE_MODULE_IMAGE_DIR)/lib -name 'ir.idl' -exec $(RM) \{} \;
+	@# Generate meta-index to make boot and extension class loaders lazier
+	$(CD) $(JRE_MODULE_IMAGE_DIR)/lib && \
+	    $(BOOT_JAVA_CMD) -jar $(BUILDMETAINDEX_JARFILE) \
+		-o meta-index *.jar
+	@$(CD) $(JRE_MODULE_IMAGE_DIR)/lib && $(java-vm-cleanup)
+	$(CD) $(JRE_MODULE_IMAGE_DIR)/lib/ext && \
+	    $(BOOT_JAVA_CMD) -jar $(BUILDMETAINDEX_JARFILE) \
+		-o meta-index *.jar
+	@$(CD) $(JRE_MODULE_IMAGE_DIR)/lib/ext && $(java-vm-cleanup)
+ifeq ($(PLATFORM), windows)
+	@# Remove certain *.lib files
+	$(CD) $(JRE_MODULE_IMAGE_DIR)/lib && \
+            $(RM) java.$(LIB_SUFFIX) jvm.$(LIB_SUFFIX) \
+                  hpi.$(LIB_SUFFIX) awt.$(LIB_SUFFIX) jawt.$(LIB_SUFFIX)
+  ifeq ($(ARCH_DATA_MODEL), 32)
+	@# The Java Kernel JRE image ships with a special VM.  It is not included
+	@# in the full JRE image, so remove it.  Also, is it only for 32-bit windows.
+	$(CD) $(JRE_MODULE_IMAGE_DIR)/bin && $(RM) -r kernel
+  endif
+endif # Windows
+ifneq ($(PLATFORM), windows)
+	$(call copy-man-pages,$(JRE_MODULE_IMAGE_DIR),$(JRE_MAN_PAGES))
+endif # !windows
+
+# Trim out any extra files not for the jre shipment but wanted in the jdk jre.
+#   (Note the jdk WILL want the jre image before this trimming)
+#   Removes server VM on Windows 32bit.
+#   Remove certain shared libraries that should not be in the jre image
+#      but should be in the jdk jre image.
+trim-module-image-jre::
+ifeq ($(PLATFORM), windows)
+  ifeq ($(ARCH_DATA_MODEL), 32)
+	$(RM) -r $(JRE_MODULE_IMAGE_DIR)/bin/server
+  endif
+  ifdef NOTJRE_SHARED_LIBS
+	for l in $(NOTJRE_SHARED_LIBS) ; do \
+	    $(RM) $(JRE_MODULE_IMAGE_DIR)/bin/$$l ; \
+	done ;
+  endif
+else # PLATFORM
+  ifdef NOTJRE_SHARED_LIBS
+	for l in $(NOTJRE_SHARED_LIBS) ; do \
+	    $(RM) $(JRE_MODULE_IMAGE_DIR)/lib/$(LIBARCH)/$$l ; \
+	done ;
+  endif
+endif # PLATFORM
+
+# Get list of all Elf files in the jre
+JRE_MODULE_ELF_LIST=$(MODULES_TEMPDIR)/jre-elf-files.list
+$(JRE_MODULE_ELF_LIST):
+	@$(prep-target)
+ifneq ($(PLATFORM), windows)
+	$(RM) $@
+	$(FIND) $(JRE_MODULE_IMAGE_DIR)/lib -type f -name \*.$(LIB_SUFFIX) >> $@
+	$(FILE) `$(FIND) $(JRE_MODULE_IMAGE_DIR)/bin -type f -name \*$(EXE_SUFFIX)` \
+	    | $(EGREP) 'ELF' | $(CUT) -d':' -f1 >> $@
+endif
+
+# Post process the image (strips and mcs on Elf files we are shipping)
+#   (Note the jdk WILL want the jre image before this processing)
+process-module-image-jre:: $(JRE_MODULE_ELF_LIST)
+ifneq ($(POST_STRIP_PROCESS), )
+	for f in `$(CAT) $(JRE_MODULE_ELF_LIST)`; do \
+	  $(CHMOD) u+w $${f}; \
+	  $(ECHO) $(POST_STRIP_PROCESS) $${f}; \
+	  $(POST_STRIP_PROCESS) $${f}; \
+	  $(CHMOD) go-w $${f}; \
+	done
+endif
+ifneq ($(POST_MCS_PROCESS), )
+	for f in `$(CAT) $(JRE_MODULE_ELF_LIST)`; do \
+	  $(CHMOD) u+w $${f}; \
+	  $(ECHO) $(POST_MCS_PROCESS) $${f}; \
+	  $(POST_MCS_PROCESS) $${f}; \
+	  $(CHMOD) go-w $${f}; \
+	done
+endif
+	$(RM) $(JRE_MODULE_ELF_LIST)
+
+######################################################
+# JDK Image
+######################################################
+# Note: cpio ($(CPIO)) sometimes leaves directories without rx access.
+
+initial-module-image-jdk-setup:
+	$(RM) -r $(JDK_MODULE_IMAGE_DIR)
+	$(MKDIR) -p $(JDK_MODULE_IMAGE_DIR)/jre
+	($(CD) $(JRE_MODULE_IMAGE_DIR) && $(FIND) . -depth -print \
+	      | $(CPIO) -pdum $(JDK_MODULE_IMAGE_DIR)/jre )
+	$(RM) -rf $(JDK_MODULE_IMAGE_DIR)/jre/man
+	$(CHMOD) a+rx `$(FIND) $(JDK_MODULE_IMAGE_DIR) -type d`
+
+initial-module-image-jdk64-bindemos:
+	for dir in bin demo ; do \
+	  ( $(CD) $(OUTPUTDIR) && \
+		$(TAR) cf - `$(FIND) $$dir -name '$(LIBARCH)' -print` | \
+		($(CD) $(JDK_MODULE_IMAGE_DIR) && $(TAR) xf -) ) ; \
+        done
+
+# Solaris 64 bit image is special
+initial-module-image-jdk-sol64:: initial-module-image-jdk-setup \
+			  initial-module-image-jdk64-bindemos \
+			  $(JDK_MODULE_LICENSES) $(JDK_MODULARLIZED_64_LICENSES)
+
+# DB files to add
+ifeq ($(OPENJDK),true)
+
+initial-module-image-jdk-db:
+
+else
+
+# Create the list of db *.zip files to bundle with jdk
+ABS_DB_PATH  :=$(call FullPath,$(CLOSED_SHARE_SRC)/db)
+DB_ZIP_LIST = $(shell $(LS) $(ABS_DB_PATH)/*.zip 2>/dev/null)
+
+initial-module-image-jdk-db: $(DB_ZIP_LIST)
+	$(MKDIR) -p $(JDK_MODULE_IMAGE_DIR)/db
+	for d in $(DB_ZIP_LIST); do \
+          ($(CD) $(JDK_MODULE_IMAGE_DIR)/db && $(UNZIP) -o $$d); \
+	done
+
+endif
+
+# Standard jdk image
+initial-module-image-jdk:: initial-module-image-jdk-setup \
+		    initial-module-image-jdk-db \
+		    $(JDK_MODULE_LICENSES) $(JDK_MODULE_DOCFILES)
+	$(MKDIR) $(JDK_MODULE_IMAGE_DIR)/lib
+	@#
+	@# copy jdk modules to jdk/lib
+	@#
+	$(MKDIR) -p $(JDK_MODULE_IMAGE_DIR)/lib
+	$(CP) -rf $(MODULES_LIB)/lib/* $(JDK_MODULE_IMAGE_DIR)/lib 
+  ifeq ($(PLATFORM), windows)
+	@#
+	@# lib/
+	@#
+	$(CP) $(LIBDIR)/$(LIB_PREFIX)jvm.$(LIB_SUFFIX) $(JDK_MODULE_IMAGE_DIR)/lib
+	$(CP) $(LIBDIR)/$(LIB_PREFIX)jawt.$(LIB_SUFFIX) $(JDK_MODULE_IMAGE_DIR)/lib
+	@#
+	@# bin/
+	@#
+	@# copy all EXE files and only certain DLL files from BINDIR
+	$(MKDIR) -p $(JDK_MODULE_IMAGE_DIR)/bin
+	$(CP) $(BINDIR)/*$(EXE_SUFFIX) $(JDK_MODULE_IMAGE_DIR)/bin
+	$(CP) $(BINDIR)/jli.$(LIBRARY_SUFFIX) $(JDK_MODULE_IMAGE_DIR)/bin
+    ifeq ($(ARCH_DATA_MODEL), 32)
+      ifeq ($(COMPILER_VERSION), VS2003)
+	$(CP) $(BINDIR)/msvc*71.$(LIBRARY_SUFFIX) $(JDK_MODULE_IMAGE_DIR)/bin
+      endif
+    endif
+  else # PLATFORM
+	@#
+	@# bin/
+	@#
+	($(CD) $(BINDIR)/.. && $(TAR) cf - \
+	    `$(FIND) bin \( -type f -o -type l \) -print `) | \
+	    ($(CD) $(JDK_MODULE_IMAGE_DIR) && $(TAR) xf -)
+  endif # PLATFORM
+	@#
+	@# lib/ct.sym
+	@#
+	$(MKDIR) -p $(OUTPUTDIR)/symbols/META-INF/sym
+	$(JAVAC_CMD) -XDprocess.packages -proc:only \
+	    -processor com.sun.tools.javac.sym.CreateSymbols \
+	    -Acom.sun.tools.javac.sym.Jar=$(RT_JAR) \
+	    -Acom.sun.tools.javac.sym.Dest=$(OUTPUTDIR)/symbols/META-INF/sym/rt.jar \
+	    $(CORE_PKGS) $(NON_CORE_PKGS) $(EXCLUDE_PROPWARN_PKGS)
+	$(BOOT_JAR_CMD) c0f $(LIBDIR)/ct.sym \
+	    -C $(OUTPUTDIR)/symbols META-INF $(BOOT_JAR_JFLAGS)
+	@$(java-vm-cleanup)
+	$(CP) $(LIBDIR)/ct.sym $(JDK_MODULE_IMAGE_DIR)/lib/ct.sym
+	@#
+	@# CORBA supported orb.idl and ir.idl should be copied to lib
+	@#
+	$(CP) $(LIBDIR)/orb.idl $(JDK_MODULE_IMAGE_DIR)/lib/orb.idl
+	$(CP) $(LIBDIR)/ir.idl $(JDK_MODULE_IMAGE_DIR)/lib/ir.idl
+  ifeq ($(PLATFORM), linux)
+	@#
+	@# on Linux copy jexec from jre/lib to /lib
+	@#
+	$(CP) $(LIBDIR)/jexec $(JDK_MODULE_IMAGE_DIR)/lib/jexec
+  endif # PLATFORM
+	@#
+	@# demo, include
+	@#
+	$(CP) -r -f $(DEMODIR) $(JDK_MODULE_IMAGE_DIR)
+	$(CP) -r -f $(SAMPLEDIR) $(JDK_MODULE_IMAGE_DIR)
+	$(CP) -r $(INCLUDEDIR) $(JDK_MODULE_IMAGE_DIR)
+	@#
+	@# Swing BeanInfo generation
+	@#
+	$(CD) javax/swing/beaninfo && $(MAKE) JDK_IMAGE_DIR=$(JDK_MODULE_IMAGE_DIR) swing-1.2-beans
+ifneq ($(PLATFORM), windows)
+	$(call copy-man-pages,$(JDK_MODULE_IMAGE_DIR),$(JDK_MAN_PAGES))
+endif # !windows
+
+# Trim out files we don't want to ship
+trim-module-image-jdk::
+	@# Remove tools that should not be part of SDK.
+	for t in $(NOTJDKTOOLS); do \
+	    $(RM) $(JDK_MODULE_IMAGE_DIR)/bin/$${t}$(EXE_SUFFIX) \
+		  $(JDK_MODULE_IMAGE_DIR)/bin/*/native_threads/$${t}$(EXE_SUFFIX); \
+	done
+
+# Get list of Elf files in the jdk
+JDK_MODULE_ELF_LIST=$(MODULES_TEMPDIR)/jdk-elf-files.list
+$(JDK_MODULE_ELF_LIST):
+	@$(prep-target)
+ifneq ($(PLATFORM), windows)
+	$(RM) $@
+	$(FIND) $(JDK_MODULE_IMAGE_DIR)/jre/lib -type f -name \*.$(LIB_SUFFIX) >> $@
+	$(FILE) `$(FIND) $(JDK_MODULE_IMAGE_DIR)/jre/bin -type f -name \*$(EXE_SUFFIX)` \
+	    | $(EGREP) 'ELF' | $(CUT) -d':' -f1 >> $@
+	file `$(FIND) $(JDK_MODULE_IMAGE_DIR)/bin -type f -name \*$(EXE_SUFFIX)` \
+	    | $(EGREP) 'ELF' | $(CUT) -d':' -f1 >> $@
+endif
+
+# Post process the image (strips and mcs on files we are shipping)
+process-module-image-jdk:: $(JDK_MODULE_ELF_LIST)
+ifneq ($(POST_STRIP_PROCESS), )
+	for f in `$(CAT) $(JDK_MODULE_ELF_LIST)`; do \
+	  $(CHMOD) u+w $${f}; \
+	  $(ECHO) $(POST_STRIP_PROCESS) $${f}; \
+	  $(POST_STRIP_PROCESS) $${f}; \
+	  $(CHMOD) go-w $${f}; \
+	done
+endif
+ifneq ($(POST_MCS_PROCESS), )
+	for f in `$(CAT) $(JDK_MODULE_ELF_LIST)`; do \
+	  $(CHMOD) u+w $${f}; \
+	  $(ECHO) $(POST_MCS_PROCESS) $${f}; \
+	  $(POST_MCS_PROCESS) $${f}; \
+	  $(CHMOD) go-w $${f}; \
+	done
+endif
+	$(RM) $(JDK_MODULE_ELF_LIST)
+
+######################################################
+# clobber
+######################################################
+modules-clobber::
+	$(RM) -r $(JDK_MODULE_IMAGE_DIR)
+	$(RM) -r $(JRE_MODULE_IMAGE_DIR)
+
+#
+# TODO - nop for now
+sanity-module-images post-sanity-module-images:
+
+modules modules-clobber::
+	@$(ECHO) ">>>Finished making "$@" @ `$(DATE)` ..."
+	@$(java-vm-cleanup)
+
+.PHONY: modules module-image-jre module-image-jdk \
+	initial-module-image-jre initial-module-image-jdk \
+	initial-module-image-jre-sol64 initial-module-image-jdk-sol64 \
+        initial-module-image-jdk-setup \
+	initial-module-image-jdk-db \
+        initial-module-image-jdk64-bindemos \
+        initial-module-image-jre-setup \
+	trim-module-image-jre trim-module-image-jdk \
+	process-module-image-jre process-module-image-jdk \
+	install-previous-jre install-previous-jdk \
+	modules-clobber
+
+# Force rule
+FRC:
+
--- a/jdk/make/java/java/mapfile-vers	Thu Dec 17 14:10:20 2009 -0800
+++ b/jdk/make/java/java/mapfile-vers	Wed Jul 05 17:04:56 2017 +0200
@@ -150,10 +150,8 @@
 		Java_java_lang_StrictMath_asin;
 		Java_java_lang_StrictMath_atan;
 		Java_java_lang_StrictMath_atan2;
-		Java_java_lang_StrictMath_ceil;
 		Java_java_lang_StrictMath_cos;
 		Java_java_lang_StrictMath_exp;
-		Java_java_lang_StrictMath_floor;
 		Java_java_lang_StrictMath_log;
 		Java_java_lang_StrictMath_log10;
 		Java_java_lang_StrictMath_pow;
--- a/jdk/make/java/java/reorder-i586	Thu Dec 17 14:10:20 2009 -0800
+++ b/jdk/make/java/java/reorder-i586	Wed Jul 05 17:04:56 2017 +0200
@@ -107,4 +107,3 @@
 text: .text%Java_java_util_TimeZone_getSystemTimeZoneID;
 text: .text%findJavaTZ_md;
 text: .text%Java_java_lang_StrictMath_log;
-text: .text%Java_java_lang_StrictMath_floor;
--- a/jdk/make/java/java/reorder-sparc	Thu Dec 17 14:10:20 2009 -0800
+++ b/jdk/make/java/java/reorder-sparc	Wed Jul 05 17:04:56 2017 +0200
@@ -105,4 +105,3 @@
 text: .text%findJavaTZ_md;
 text: .text%Java_java_lang_StrictMath_log;
 text: .text%Java_java_lang_StrictMath_sqrt;
-text: .text%Java_java_lang_StrictMath_floor;
--- a/jdk/make/java/java/reorder-sparcv9	Thu Dec 17 14:10:20 2009 -0800
+++ b/jdk/make/java/java/reorder-sparcv9	Wed Jul 05 17:04:56 2017 +0200
@@ -101,4 +101,3 @@
 text: .text%findJavaTZ_md;
 text: .text%Java_java_lang_StrictMath_log;
 text: .text%Java_java_lang_StrictMath_sqrt;
-text: .text%Java_java_lang_StrictMath_floor;
--- a/jdk/make/java/jli/Makefile	Thu Dec 17 14:10:20 2009 -0800
+++ b/jdk/make/java/jli/Makefile	Wed Jul 05 17:04:56 2017 +0200
@@ -152,7 +152,6 @@
 STATIC_LIBRARY = $(STATIC_LIBRARY_DIR)/$(STATIC_LIBRARY_NAME)
 
 $(STATIC_LIBRARY_DIR): $(OBJDIR)
-	@$(prep-target)
 	@$(MKDIR) $(STATIC_LIBRARY_DIR)
 
 $(STATIC_LIBRARY): $(STATIC_LIBRARY_DIR)
--- a/jdk/make/java/nio/FILES_java.gmk	Thu Dec 17 14:10:20 2009 -0800
+++ b/jdk/make/java/nio/FILES_java.gmk	Wed Jul 05 17:04:56 2017 +0200
@@ -234,6 +234,7 @@
 	sun/nio/cs/UTF_16BE.java \
 	sun/nio/cs/UTF_16LE.java \
 	sun/nio/cs/UTF_8.java \
+	sun/nio/cs/Unicode.java \
 	sun/nio/cs/UnicodeDecoder.java \
 	sun/nio/cs/UnicodeEncoder.java \
 	sun/nio/cs/UTF_32.java \
--- a/jdk/make/java/nio/genBuffer.sh	Thu Dec 17 14:10:20 2009 -0800
+++ b/jdk/make/java/nio/genBuffer.sh	Wed Jul 05 17:04:56 2017 +0200
@@ -44,6 +44,7 @@
 
 case $type in
   char)  fulltype=character;;
+  int)   fulltype=integer;;
   *)     fulltype=$type;;
 esac
 
@@ -54,6 +55,11 @@
   long | double)  LBPV=3;;
 esac
 
+case $type in 
+  float|double) floatingPointOrIntegralType=floatingPointType;;
+  *)            floatingPointOrIntegralType=integralType;;
+esac
+
 typesAndBits() {
 
   type="$1"; BO="$2"
@@ -101,6 +107,7 @@
 
 $SPP <$SRC >$DST \
   -K$type \
+  -K$floatingPointOrIntegralType \
   -Dtype=$type \
   -DType=$Type \
   -Dfulltype=$fulltype \
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/make/modules/Makefile	Wed Jul 05 17:04:56 2017 +0200
@@ -0,0 +1,145 @@
+#
+# Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
+# 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.  Sun designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+# CA 95054 USA or visit www.sun.com if you need additional information or
+# have any questions.
+#
+
+#
+# Modularizing the JDK
+#
+
+BUILDDIR = ..
+include $(BUILDDIR)/common/Defs.gmk
+
+CLASSANALYZER_JAR=$(BUILDTOOLJARDIR)/classanalyzer.jar
+JAVA_FLAGS=$(JAVA_TOOLS_FLAGS) -Xbootclasspath:$(CLASSBINDIR)
+
+MODULE_LIB = $(ABS_OUTPUTDIR)/modules
+MAINMANIFEST=$(JDK_TOPDIR)/make/tools/manifest.mf
+MODULE_JAR_MANIFEST_FILE=$(ABS_TEMPDIR)/manifest.tmp
+
+TMP=$(ABS_TEMPDIR)/modules
+MODULE_CLASSLIST = $(TMP)/classlist
+MODULE_CLASSES = $(TMP)/classes
+MODULE_LIST = $(MODULE_CLASSLIST)/modules.list
+
+# Modules in the modules/ext directory
+EXT_MODULES = localedata security-sunec security-sunjce
+
+# Build PKCS#11 on all platforms except 64-bit Windows.
+# We exclude windows-amd64 because we don't have any
+# 64-bit PKCS#11 implementations to test with on that platform.
+PKCS11 = security-sunpkcs11
+ifeq ($(ARCH_DATA_MODEL), 64)
+  ifeq ($(PLATFORM), windows)
+    PKCS11 =
+  endif
+endif
+
+EXT_MODULES += $(PKCS11)
+
+# Build Microsoft CryptoAPI provider only on (non-64-bit) Windows platform.
+ifeq ($(PLATFORM), windows)
+  ifneq ($(ARCH_DATA_MODEL), 64)
+    EXT_MODULES += security-sunmscapi
+  endif
+endif
+
+
+JDK_MODULES = tools
+
+SUBDIRS = tools
+all build clean clobber::
+	$(SUBDIRS-loop)
+
+all:: unpack-jars gen-classlist modularize
+
+$(CLASSANALYZER_JAR):
+	$(CD) tools && $(MAKE) all
+
+JAR_LIST := $(shell $(FIND) $(ABS_OUTPUTDIR)/lib -name \*.jar -depth) 
+unpack-jars:
+	$(RM) -rf $(MODULE_CLASSES)
+	$(MKDIR) -p $(MODULE_CLASSES)
+	$(CP) -rf $(CLASSBINDIR)/* $(MODULE_CLASSES)
+	for jf in  $(JAR_LIST) ; do \
+	   $(CD) $(MODULE_CLASSES) && $(BOOT_JAR_CMD) xf $$jf $(BOOT_JAR_JFLAGS);\
+	done
+
+gen-classlist: $(CLASSANALYZER_JAR)
+	@$(ECHO) ">>>Making "$@" @ `$(DATE)` ..."
+	@$(RM) -rf $(MODULE_CLASSLIST)
+	@$(MKDIR) -p $(MODULE_CLASSLIST)
+
+	@# Use java in the default tool directory.
+	@# OUTPUTDIR for solaris 64-bit doesn't have the tools.
+	$(JAVA_TOOLS_DIR)/java $(JAVA_FLAGS) \
+		-Dclassanalyzer.debug \
+		-jar $(CLASSANALYZER_JAR) \
+		-jdkhome $(OUTPUTDIR) \
+	        -config modules.config \
+	        -config modules.group \
+		-depconfig jdk7.depconfig \
+		-depconfig optional.depconfig \
+		-showdynamic \
+		-output $(MODULE_CLASSLIST)
+	@$(ECHO) ">>>Finished making "$@" @ `$(DATE)` ..."
+
+modularize: $(MODULE_JAR_MANIFEST_FILE)
+	@$(ECHO) ">>>Making "$@" @ `$(DATE)` ..."
+	@$(RM) -rf $(MODULE_LIB)
+	@$(MKDIR) -p $(MODULE_LIB)/lib
+	@$(MKDIR) -p $(MODULE_LIB)/jre/lib/ext
+
+	@# create modules
+	for m in `$(NAWK) '{print $$1}' $(MODULE_LIST)` ; do \
+   	   $(ECHO) "Creating module $$m" ; \
+   	   $(SED) -e 's%\\%\/%g' < $(MODULE_CLASSLIST)/$$m.classlist > $(TMP)/tmp.cf ; \
+	   if [ -f $(MODULE_CLASSLIST)/$$m.resources ] ; then \
+   	       $(SED) -e 's%\\%\/%g' < $(MODULE_CLASSLIST)/$$m.resources >> $(TMP)/tmp.cf ; \
+           fi ; \
+	   $(CD) $(MODULE_CLASSES) && \
+               $(BOOT_JAR_CMD) c0mf $(MODULE_JAR_MANIFEST_FILE) \
+		   $(MODULE_LIB)/$$m.jar \
+		   @$(TMP)/tmp.cf \
+                   $(BOOT_JAR_JFLAGS) ; \
+	done
+	@$(CD) $(MODULE_CLASSES) && $(java-vm-cleanup)
+	@# move modules to lib, jre/lib, or jre/lib/ext
+	for m in $(EXT_MODULES) ; do \
+	   $(MV) $(MODULE_LIB)/$$m.jar $(MODULE_LIB)/jre/lib/ext ; \
+	done
+	for m in $(JDK_MODULES) ; do \
+	   $(MV) $(MODULE_LIB)/$$m.jar $(MODULE_LIB)/lib ; \
+	done
+	$(MV) $(MODULE_LIB)/*.jar $(MODULE_LIB)/jre/lib
+	@$(ECHO) ">>>Finished making "$@" @ `$(DATE)` ..."
+
+$(MODULE_JAR_MANIFEST_FILE):
+	$(SED) -e "s/@@RELEASE@@/$(RELEASE)/" $(MAINMANIFEST) > $@
+
+clean clobber::
+	$(RM) -rf $(MODULE_CLASSLIST)
+	$(RM) -rf $(MODULE_LIB)
+	$(RM) -f $(MODULE_JAR_MANIFEST_FILE)
+	$(RM) -f $(CLASSANALYZER_JAR)
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/make/modules/bootmodule.roots	Wed Jul 05 17:04:56 2017 +0200
@@ -0,0 +1,199 @@
+#
+# Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
+# 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+# CA 95054 USA or visit www.sun.com if you need additional information or
+# have any questions.
+#
+
+#
+# List of root classes/methods, each line of the following syntax:
+# <class name> 
+# <method name> <signature>|*
+# exclude <class>|<method> 
+
+# The boot module generated based on this rootset does not support
+# - security permission check
+# - non-standard charset
+# - logging output
+# - resource bundles
+#   including error output from the launcher 
+
+# VM preloaded classes
+java.lang.Object
+java.lang.String
+java.lang.Class
+java.lang.Cloneable
+java.lang.ClassLoader
+java.lang.System
+java.lang.Throwable
+java.lang.Error
+java.lang.ThreadDeath
+java.lang.Exception
+java.lang.RuntimeException
+java.security.ProtectionDomain
+java.security.AccessControlContext
+java.lang.ClassNotFoundException
+java.lang.NoClassDefFoundError
+java.lang.ClassCastException
+java.lang.ArrayStoreException
+java.lang.VirtualMachineError
+java.lang.OutOfMemoryError
+java.lang.StackOverflowError
+java.lang.IllegalMonitorStateException
+java.lang.ref.Reference
+java.lang.ref.SoftReference
+java.lang.ref.WeakReference
+java.lang.ref.FinalReference
+java.lang.ref.PhantomReference
+java.lang.ref.Finalizer
+java.lang.Runnable
+java.lang.Thread
+java.lang.ThreadGroup
+java.util.Properties
+java.lang.reflect.AccessibleObject
+java.lang.reflect.Member
+java.lang.reflect.Field
+java.lang.reflect.Method
+java.lang.reflect.Constructor
+java.lang.reflect.Type
+sun.reflect.MagicAccessorImpl
+sun.reflect.MethodAccessorImpl
+sun.reflect.ConstructorAccessorImpl
+sun.reflect.DelegatingClassLoader
+sun.reflect.ConstantPool
+sun.reflect.UnsafeStaticFieldAccessorImpl
+java.util.Vector
+java.lang.StringBuffer
+java.lang.StackTraceElement
+java.nio.Buffer
+java.lang.Boolean
+java.lang.Character
+java.lang.Float
+java.lang.Double
+java.lang.Byte
+java.lang.Short
+java.lang.Integer
+java.lang.Long
+java.lang.NullPointerException
+java.lang.ArithmeticException
+java.lang.Compiler
+
+
+# Root methods
+java.lang.ClassLoader.getSystemClassLoader ()Ljava/lang/ClassLoader;
+java.lang.System.initializeSystemClass ()V
+sun.launcher.LauncherHelper.checkAndLoadMain (ZZLjava/lang/String;)Ljava/lang/Object;
+
+# The tool doesn't automatically find superclasses and parse the method
+# if overridden as it tries to reduce unnecessary classes being pulled in.
+# The following forces the dependency to be included the result.
+sun.net.www.protocol.file.Handler.<init> ()V
+sun.net.www.protocol.jar.Handler.<init> ()V
+sun.net.www.protocol.file.Handler.openConnection *
+sun.net.www.protocol.jar.Handler.openConnection *
+sun.misc.URLClassPath$JarLoader.<init>  (Ljava/net/URL;Ljava/net/URLStreamHandler;Ljava/util/HashMap;)V
+sun.misc.URLClassPath$FileLoader.<init> (Ljava/net/URL;)V
+sun.misc.URLClassPath$FileLoader.getClassPath *
+sun.misc.URLClassPath$FileLoader.getResource *
+sun.misc.URLClassPath$JarLoader.getResource *
+sun.misc.URLClassPath$JarLoader.getClassPath *
+
+# permission collections
+java.io.FilePermission.newPermissionCollection ()Ljava/security/PermissionCollection;
+java.security.BasicPermission.newPermissionCollection ()Ljava/security/PermissionCollection;
+
+# native
+java.io.UnixFileSystem
+java.io.UnixFileSystem.<init> ()V
+java.io.UnixFileSystem.canonicalize *
+java.io.Win32FileSystem
+java.io.Win32FileSystem.<init> ()V
+java.io.Win32FileSystem.canonicalize *
+java.io.WinNTFileSystem
+java.io.WinNTFileSystem.<init> ()V
+java.io.WinNTFileSystem.canonicalize *
+
+# missing
+java.util.HashMap.<init> ()V
+java.util.HashMap$EntrySet.iterator *
+
+# Called from native GetStringPlatformChars (jni_util.c)
+java.lang.String.getBytes *
+
+# charset
+sun.nio.cs.US_ASCII.newEncoder ()Ljava/nio/charset/CharsetEncoder;
+sun.nio.cs.UTF_8.newEncoder ()Ljava/nio/charset/CharsetEncoder;
+sun.nio.cs.UTF_8.newDecoder  *
+sun.nio.cs.UTF_16.newEncoder ()Ljava/nio/charset/CharsetEncoder;
+sun.nio.cs.UTF_16.newDecoder  *
+sun.nio.cs.UTF_32.newEncoder ()Ljava/nio/charset/CharsetEncoder;
+sun.nio.cs.UTF_32.newDecoder  *
+
+# hashcode
+java.util.jar.Attributes$Name.hashCode *
+
+# nio
+sun.nio.ByteBuffered
+sun.nio.ch.DirectBuffer
+java.nio.DirectByteBuffer
+java.nio.MappedByteBuffer
+java.nio.DirectLongBufferU
+
+# resource files
+sun.launcher.resources.launcher
+
+sun.misc.Launcher$AppClassLoader.getPermissions *
+sun.misc.Launcher$AppClassLoader.loadClass  (Ljava/lang/String;)Ljava/lang/Class;
+sun.misc.Launcher$AppClassLoader.findClass  (Ljava/lang/String;)Ljava/lang/Class;
+sun.misc.Launcher$ExtClassLoader.getPermissions *
+sun.misc.Launcher$ExtClassLoader.loadClass  (Ljava/lang/String;)Ljava/lang/Class;
+sun.misc.Launcher$ExtClassLoader.findClass  (Ljava/lang/String;)Ljava/lang/Class;
+java.lang.ClassLoader.checkPackageAccess *
+java.lang.ClassLoader.findClass *
+java.lang.ClassLoader.defineClass *
+java.net.URLClassLoader.getPermissions *
+java.net.URLClassLoader.findClass *
+java.net.URLClassLoader.defineClass *
+java.security.SecureClassLoader.defineClass *
+# need to parse superclasses <init>
+java.security.SecureClassLoader.<init> ()V
+
+exclude sun.security.provider.PolicyFile.<init>
+exclude java.lang.ClassLoader.compareCerts
+exclude java.security.cert.Certificate.equals
+# unsigned jars - no verifier
+exclude java.util.jar.JarFile.initializeVerifier
+exclude java.util.jar.JarVerifier 
+exclude sun.security.util.SignatureFileVerifier.<init>
+
+
+# what about other charset
+exclude sun.misc.Service
+exclude java.util.ServiceLoader
+
+# exclude support for localized messages
+exclude java.util.ResourceBundle.getBundle
+exclude java.text.MessageFormat
+exclude sun.util.logging.PlatformLogger$LoggerProxy.format *
+
+# exclude nio and miscellaneous classes
+exclude java.nio.channels.**
+exclude sun.misc.FloatingDecimal
+exclude sun.misc.FormattedFloatingDecimal
+exclude sun.misc.FDBigInt 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/make/modules/jdk7.depconfig	Wed Jul 05 17:04:56 2017 +0200
@@ -0,0 +1,473 @@
+#
+# Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
+# 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+# CA 95054 USA or visit www.sun.com if you need additional information or
+# have any questions.
+#
+
+# private java.lang.Object createInetSocketAddress(java.lang.String, int)
+@ClassForName
+  com.sun.jndi.ldap.Connection -> java.net.InetSocketAddress
+  com.sun.jndi.ldap.Connection -> java.net.SocketAddress
+
+# com.sun.jndi.ldap.VersionHelper
+@ClassForName(optional)
+  com.sun.jndi.ldap.VersionHelper -> com.sun.jndi.ldap.VersionHelper*
+
+# private static void initMethodHandles()
+@ClassForName
+  com.sun.jndi.toolkit.corba.CorbaUtils -> javax.rmi.CORBA.Stub
+  com.sun.jndi.toolkit.corba.CorbaUtils -> javax.rmi.PortableRemoteObject
+
+# com.sun.naming.internal.ResourceManager$AppletParameter
+@ClassForName(optional)
+  com.sun.naming.internal.ResourceManager$AppletParameter -> java.applet.Applet
+
+# private static boolean loadProviderAsService()
+@Provider
+  com.sun.net.httpserver.spi.HttpServerProvider -> META-INF/services/com.sun.net.httpserver.spi.HttpServerProvider
+
+# com.sun.org.apache.xml.internal.security.transforms.implementations.TransformXSLT
+@ClassForName
+  com.sun.org.apache.xml.internal.security.transforms.implementations.TransformXSLT -> javax.xml.XMLConstants
+
+# public static java.beans.PersistenceDelegate getPersistenceDelegate(java.lang.Class)
+@ClassForName
+  java.beans.MetaData -> java.beans.*_PersistenceDelegate
+
+# private static java.lang.reflect.Method getNanosMethod()
+@ClassForName(optional)
+  java.beans.java_sql_Timestamp_PersistenceDelegate -> java.sql.Timestamp
+
+# java.beans.java_util_Collections$CheckedCollection_PersistenceDelegate
+@ClassForName
+  java.beans.java_util_Collections$CheckedCollection_PersistenceDelegate -> java.util.Collections$CheckedCollection
+
+# java.beans.java_util_Collections$CheckedMap_PersistenceDelegate
+@ClassForName
+  java.beans.java_util_Collections$CheckedMap_PersistenceDelegate -> java.util.Collections$CheckedMap
+
+# private static java.lang.Object getType(java.lang.Object)
+@ClassForName
+  java.beans.java_util_EnumMap_PersistenceDelegate -> java.util.EnumMap
+
+# private java.lang.Integer getAxis(java.lang.Object)
+@ClassForName
+  java.beans.javax_swing_Box_PersistenceDelegate -> javax.swing.BoxLayout
+
+# java.lang.Double
+@Inline
+  java.lang.Double -> sun.misc.FloatConsts
+  java.lang.Double -> sun.misc.DoubleConsts
+
+# java.lang.Float
+@Inline
+  java.lang.Float -> sun.misc.FloatConsts
+  java.lang.Float -> sun.misc.DoubleConsts
+
+# java.net.DefaultDatagramSocketImplFactory
+@ClassForName(optional)
+  java.net.DefaultDatagramSocketImplFactory -> java.net.*DatagramSocketImpl
+
+# private static sun.net.spi.nameservice.NameService createNSProvider(java.lang.String)
+@Provider
+  java.net.InetAddress -> META-INF/services/sun.net.spi.nameservice.NameServiceDescriptor
+
+# static java.net.InetAddressImpl create()
+@ClassForName
+  java.net.InetAddressImplFactory -> java.net.*Inet[46]AddressImpl
+
+# private static void init()
+@NativeFindClass
+  java.net.PlainDatagramSocketImpl -> java.io.FileDescriptor
+
+# java.net.ProxySelector
+@ClassForName
+  java.net.ProxySelector -> sun.net.spi.DefaultProxySelector
+
+# static java.net.URLStreamHandler getURLStreamHandler(java.lang.String)
+@ClassForName(optional)
+  java.net.URL -> sun.net.www.protocol.*.Handler
+
+# private java.net.ContentHandler lookupContentHandlerClassFor(java.lang.String)
+@ClassForName
+  java.net.URLConnection -> sun.net.www.content.*
+
+# private static java.nio.channels.spi.AsynchronousChannelProvider loadProviderAsService()
+@Provider
+  java.nio.channels.spi.AsynchronousChannelProvider$ProviderHolder -> META-INF/services/java.nio.channels.spi.AsynchronousChannelProvider
+
+# private static boolean loadProviderFromProperty()
+@ClassForName
+  java.nio.channels.spi.SelectorProvider -> sun.nio.ch.DefaultSelectorProvider
+
+# private static boolean loadProviderAsService()
+@Provider
+  java.nio.channels.spi.SelectorProvider -> META-INF/services/java.nio.channels.spi.SelectorProvider
+
+# private static java.util.Iterator providers()
+@Provider
+  java.nio.charset.Charset -> META-INF/services/java.nio.charset.spi.CharsetProvider
+
+# private static void probeExtendedProvider()
+@ClassForName(optional)
+  java.nio.charset.Charset -> sun.nio.cs.ext.ExtendedCharsets
+
+# public static java.nio.file.FileSystem newFileSystem(java.net.URI, java.util.Map<java.lang.String, ?>, java.lang.ClassLoader)
+@Provider
+  java.nio.file.FileSystems -> META-INF/services/java.nio.file.FileSystemProvider
+
+# private static java.util.List<java.nio.file.spi.FileTypeDetector> loadInstalledDetectors()
+@Provider
+  java.nio.file.Files$DefaultFileTypeDetectorHolder -> META-INF/services/java.nio.file.spi.FileTypeDetector
+
+# public static java.util.List<java.nio.file.spi.FileSystemProvider> installedProviders()
+@Provider
+  java.nio.file.spi.FileSystemProvider -> META-INF/services/java.nio.file.FileSystemProvider
+
+# private static java.rmi.server.RMIClassLoaderSpi initializeProvider()
+@Provider
+  java.rmi.server.RMIClassLoader -> META-INF/services/java.rmi.server.RMIClassLoaderSpi
+
+# private static void initializeSystemScope()
+@ClassForName(optional)
+  java.security.IdentityScope -> sun.security.provider.IdentityDatabase
+
+# static java.security.Policy getPolicyNoCheck()
+@ClassForName
+  java.security.Policy -> sun.security.provider.PolicyFile
+
+# private static java.lang.Class getSpiClass(java.lang.String)
+@ClassForName
+  java.security.Security -> java.security.*Spi
+
+# private static void invalidateSMCache(java.lang.String)
+@ClassForName
+  java.security.Security -> java.lang.SecurityManager
+
+# private static void loadInitialDrivers()
+@Provider
+  java.sql.DriverManager -> META-INF/services/java.sql.Driver
+
+# private static java.text.BreakIterator createBreakInstance(java.util.Locale, int, java.lang.String, java.lang.String)
+@Provider
+  java.text.BreakIterator -> META-INF/services/java.util.spi.BreakIteratorProvider
+
+# public static java.text.Collator getInstance(java.util.Locale)
+@Provider
+  java.text.Collator -> META-INF/services/java.util.spi.CollatorProvider
+
+# private static java.text.DateFormat get(int, int, int, java.util.Locale)
+@Provider
+  java.text.DateFormat -> META-INF/services/java.util.spi.DateNameProvider
+
+# public static java.util.Locale[] getAvailableLocales()
+@Provider
+  java.text.DateFormatSymbols -> META-INF/services/java.util.spi.DateFormatSymbolsProvider
+
+# public static java.util.Locale[] getAvailableLocales()
+@Provider
+  java.text.DecimalFormatSymbols -> META-INF/services/java.util.spi.DecimalFormatSymbolsProvider
+
+# public static java.util.Locale[] getAvailableLocales()
+@Provider
+  java.text.NumberFormat -> META-INF/services/java.util.spi.NumberFormatProvider
+
+# public java.lang.String getDisplayName(java.util.Locale)
+@Provider
+  java.util.Currency -> META-INF/services/java.util.spi.CurrencyNameProvider
+
+# java.util.Formatter
+@Inline
+  java.util.Formatter -> sun.misc.DoubleConsts
+
+# java.util.Locale
+@Inline
+  java.util.Locale -> java.util.LocaleISOData
+
+# private java.lang.String getDisplayString(java.lang.String, java.util.Locale, int)
+@Provider
+  java.util.Locale -> META-INF/services/java.util.spi.LocaleNameProvider
+
+# private static java.util.prefs.PreferencesFactory factory1()
+@ClassForName
+  java.util.prefs.Preferences -> java.util.prefs.WindowsPreferencesFactory
+  java.util.prefs.Preferences -> java.util.prefs.FileSystemPreferencesFactory
+
+# private static java.util.prefs.PreferencesFactory factory1()
+@Provider
+  java.util.prefs.Preferences -> META-INF/services/java.util.prefs.PreferencesFactory
+
+# public void registerApplicationClasspathSpis()
+@Provider
+  javax.imageio.spi.IIORegistry -> META-INF/services/javax.imageio.spi.IIOServiceProvider
+
+# private void registerInstalledProviders()
+@Provider
+  javax.imageio.spi.IIORegistry -> META-INF/services/javax.imageio.spi.ImageReaderSpi
+  javax.imageio.spi.IIORegistry -> META-INF/services/javax.imageio.spi.ImageWriterSpi
+  javax.imageio.spi.IIORegistry -> META-INF/services/javax.imageio.spi.ImageReaderWriterSpi
+  javax.imageio.spi.IIORegistry -> META-INF/services/javax.imageio.spi.ImageTranscoderSpi
+  javax.imageio.spi.IIORegistry -> META-INF/services/javax.imageio.spi.ImageInputStreamSpi
+  javax.imageio.spi.IIORegistry -> META-INF/services/javax.imageio.spi.ImageOutputStreamSpi
+
+# public javax.naming.ldap.ExtendedResponse createExtendedResponse(java.lang.String, byte[], int, int)
+@Provider
+  javax.naming.ldap.StartTlsRequest -> META-INF/services/javax.naming.ldap.StartTlsResponse
+
+# private static java.util.ArrayList getAllLookupServices()
+@Provider
+  javax.print.PrintServiceLookup -> META-INF/services/javax.print.PrintServiceLookup
+
+# private static java.util.ArrayList getAllFactories()
+@Provider
+  javax.print.StreamPrintServiceFactory -> META-INF/services/javax.print.StreamPrintServiceFactory
+
+# private void initEngines(java.lang.ClassLoader)
+@Provider
+  javax.script.ScriptEngineManager -> META-INF/services/javax.script.ScriptEngineFactory
+
+# private void initializeInputMethodLocatorList()
+@Provider
+  sun.awt.im.ExecutableInputMethodManager -> META-INF/services/java.awt.im.spi.InputMethodDescriptor
+
+# private static java.lang.Class getConverterClass(int, java.lang.String)
+@ClassForName(optional)
+  sun.io.Converters -> sun.io.*
+
+# public static sun.java2d.cmm.PCMM getModule()
+@Provider
+  sun.java2d.cmm.CMSManager -> META-INF/services/sun.java2d.cmm.PCMM
+
+# public static sun.java2d.pipe.RenderingEngine getInstance()
+@Provider
+  sun.java2d.pipe.RenderingEngine -> META-INF/services/sun.java2d.pipe.RenderingEngine
+
+# public static sun.java2d.pipe.RenderingEngine getInstance()
+@ClassForName(optional)
+  sun.java2d.pipe.RenderingEngine -> sun.dc.DuctusRenderingEngine
+
+# sun.misc.FloatingDecimal
+@Inline
+  sun.misc.FloatingDecimal -> sun.misc.FloatConsts
+  sun.misc.FloatingDecimal -> sun.misc.DoubleConsts
+
+# sun.misc.FormattedFloatingDecimal
+@Inline
+  sun.misc.FormattedFloatingDecimal -> sun.misc.FloatConsts
+  sun.misc.FormattedFloatingDecimal -> sun.misc.DoubleConsts
+
+# sun.misc.FpUtils
+@Inline
+  sun.misc.FpUtils -> sun.misc.FloatConsts
+  sun.misc.FpUtils -> sun.misc.DoubleConsts
+
+# public java.net.URLStreamHandler createURLStreamHandler(java.lang.String)
+@ClassForName(optional)
+  sun.misc.Launcher$Factory -> sun.net.www.protocol.*.Handler
+
+# private static sun.net.NetHooks$Provider loadProvider(java.lang.String)
+@ClassForName(optional)
+  sun.net.NetHooks -> sun.net.spi.SdpProvider
+
+# sun.net.idn.StringPrep
+@Inline
+  sun.net.idn.StringPrep -> sun.net.idn.UCharacterDirection
+
+# private static boolean init()
+@NativeFindClass
+  sun.net.spi.DefaultProxySelector -> java.net.Proxy
+  sun.net.spi.DefaultProxySelector -> java.net.Proxy$Type
+  sun.net.spi.DefaultProxySelector -> java.net.InetSocketAddress
+
+# private static java.nio.channels.Channel createChannel()
+@ClassForName
+  sun.nio.ch.InheritedChannel -> java.io.FileDescriptor
+
+# private static void initDBBConstructor()
+@ClassForName
+  sun.nio.ch.Util -> java.nio.DirectByteBuffer
+
+# private static void initDBBRConstructor()
+@ClassForName
+  sun.nio.ch.Util -> java.nio.DirectByteBufferR
+
+# private java.nio.charset.Charset lookup(java.lang.String)
+@ClassForName(optional)
+  sun.nio.cs.FastCharsetProvider -> sun.nio.cs.*
+
+# sun.nio.cs.ext.ExtendedCharsets
+@ClassForName(optional)
+  sun.nio.cs.ext.ExtendedCharsets -> sun.nio.cs.ext.*
+
+# sun.nio.cs.ext.ExtendedCharsets
+@ClassForName(optional)
+  sun.nio.cs.ext.ExtendedCharsets -> sun.nio.cs.ext.*
+
+# public static java.nio.file.spi.FileSystemProvider create()
+@ClassForName
+  sun.nio.fs.DefaultFileSystemProvider -> sun.nio.fs.SolarisFileSystemProvider
+  sun.nio.fs.DefaultFileSystemProvider -> sun.nio.fs.LinuxFileSystemProvider
+
+# sun.rmi.server.MarshalInputStream
+@ClassForName
+  sun.rmi.server.MarshalInputStream -> sun.rmi.server.Activation$ActivationSystemImpl_Stub
+  sun.rmi.server.MarshalInputStream -> sun.rmi.registry.RegistryImpl_Stub
+
+# private java.security.Provider doLoadProvider()
+@ClassForName(optional)
+  sun.security.jca.ProviderConfig -> sun.security.pkcs11.SunPKCS11
+  sun.security.jca.ProviderConfig -> sun.security.provider.Sun
+  sun.security.jca.ProviderConfig -> sun.security.rsa.SunRsaSign
+  sun.security.jca.ProviderConfig -> sun.security.ec.SunEC
+  sun.security.jca.ProviderConfig -> com.sun.net.ssl.internal.ssl.Provider
+  sun.security.jca.ProviderConfig -> com.sun.crypto.provider.SunJCE
+  sun.security.jca.ProviderConfig -> sun.security.jgss.SunProvider
+  sun.security.jca.ProviderConfig -> com.sun.security.sasl.Provider
+  sun.security.jca.ProviderConfig -> org.jcp.xml.dsig.internal.dom.XMLDSigRI
+  sun.security.jca.ProviderConfig -> sun.security.smartcardio.SunPCSC
+  sun.security.jca.ProviderConfig -> sun.security.mscapi.SunMSCAPI
+
+# public static java.security.Provider getSunProvider()
+@ClassForName
+  sun.security.jca.Providers -> sun.security.provider.Sun
+  sun.security.jca.Providers -> sun.security.provider.VerificationProvider
+
+# private static sun.security.jgss.spi.MechanismFactory getMechFactoryImpl(java.security.Provider, java.lang.String, org.ietf.jgss.Oid, sun.security.jgss.GSSCaller)
+@ClassForName
+  sun.security.jgss.ProviderList -> sun.security.jgss.spi.MechanismFactory
+
+# sun.security.jgss.wrapper.SunNativeProvider
+@NativeFindClass
+  sun.security.jgss.wrapper.SunNativeProvider -> org.ietf.jgss.Oid
+  sun.security.jgss.wrapper.SunNativeProvider -> org.ietf.jgss.GSSException
+  sun.security.jgss.wrapper.SunNativeProvider -> sun.security.jgss.wrapper.GSSNameElement
+  sun.security.jgss.wrapper.SunNativeProvider -> sun.security.jgss.wrapper.GSSCredElement
+  sun.security.jgss.wrapper.SunNativeProvider -> sun.security.jgss.wrapper.NativeGSSContext
+  sun.security.jgss.wrapper.SunNativeProvider -> sun.security.jgss.wrapper.SunNativeProvider
+  sun.security.jgss.wrapper.SunNativeProvider -> org.ietf.jgss.MessageProp
+  sun.security.jgss.wrapper.SunNativeProvider -> org.ietf.jgss.ChannelBinding
+  sun.security.jgss.wrapper.SunNativeProvider -> java.net.InetAddress
+  sun.security.jgss.wrapper.SunNativeProvider -> sun.security.jgss.wrapper.GSSLibStub
+
+# static void ensureLoaded()
+@NativeFindClass
+  sun.security.krb5.Credentials -> sun.security.krb5.internal.Krb5
+  sun.security.krb5.Credentials -> sun.security.krb5.internal.Ticket
+  sun.security.krb5.Credentials -> sun.security.krb5.PrincipalName
+  sun.security.krb5.Credentials -> sun.security.util.DerValue
+  sun.security.krb5.Credentials -> sun.security.krb5.EncryptionKey
+  sun.security.krb5.Credentials -> sun.security.krb5.internal.TicketFlags
+  sun.security.krb5.Credentials -> sun.security.krb5.internal.KerberosTime
+
+# public static java.lang.String getDefaultCacheName()
+@ClassForName(optional)
+  sun.security.krb5.internal.ccache.FileCredentialsCache -> com.sun.security.auth.module.UnixSystem
+
+# sun.security.pkcs.PKCS9Attribute
+@ClassForName
+  sun.security.pkcs.PKCS9Attribute -> sun.security.util.ObjectIdentifier
+  sun.security.pkcs.PKCS9Attribute -> java.util.Date
+  sun.security.pkcs.PKCS9Attribute -> sun.security.pkcs.SignerInfo
+  sun.security.pkcs.PKCS9Attribute -> sun.security.x509.CertificateExtensions
+
+# protected T engineGetKeySpec(java.security.Key, java.lang.Class<T>)
+@ClassForName
+  sun.security.provider.DSAKeyFactory -> java.security.spec.DSAPublicKeySpec
+  sun.security.provider.DSAKeyFactory -> java.security.spec.X509EncodedKeySpec
+  sun.security.provider.DSAKeyFactory -> java.security.spec.DSAPrivateKeySpec
+  sun.security.provider.DSAKeyFactory -> java.security.spec.PKCS8EncodedKeySpec
+
+# protected T engineGetParameterSpec(java.lang.Class<T>)
+@ClassForName
+  sun.security.provider.DSAParameters -> java.security.spec.DSAParameterSpec
+
+# sun.security.provider.VerificationProvider
+@ClassForName(optional)
+  sun.security.provider.VerificationProvider -> sun.security.provider.Sun
+  sun.security.provider.VerificationProvider -> sun.security.rsa.SunRsaSign
+
+# sun.security.provider.certpath.URICertStore$LDAP
+@ClassForName(optional)
+  sun.security.provider.certpath.URICertStore$LDAP -> sun.security.provider.certpath.ldap.LDAPCertStoreHelper
+
+# sun.security.smartcardio.PCSC
+@NativeFindClass
+  sun.security.smartcardio.PCSC -> sun.security.smartcardio.PCSCException
+
+# sun.security.ssl.HandshakeMessage
+@ClassForName
+  sun.security.ssl.HandshakeMessage -> java.security.MessageDigest$Delegate
+
+# sun.security.ssl.JsseJce
+@ClassForName(optional)
+  sun.security.ssl.JsseJce -> sun.security.krb5.PrincipalName
+
+# sun.security.x509.OIDMap$OIDInfo
+@ClassForName
+  sun.security.x509.OIDMap$OIDInfo -> sun.security.x509.SubjectKeyIdentifierExtension
+  sun.security.x509.OIDMap$OIDInfo -> sun.security.x509.KeyUsageExtension
+  sun.security.x509.OIDMap$OIDInfo -> sun.security.x509.PrivateKeyUsageExtension
+  sun.security.x509.OIDMap$OIDInfo -> sun.security.x509.SubjectAlternativeNameExtension
+  sun.security.x509.OIDMap$OIDInfo -> sun.security.x509.IssuerAlternativeNameExtension
+  sun.security.x509.OIDMap$OIDInfo -> sun.security.x509.BasicConstraintsExtension
+  sun.security.x509.OIDMap$OIDInfo -> sun.security.x509.CRLNumberExtension
+  sun.security.x509.OIDMap$OIDInfo -> sun.security.x509.CRLReasonCodeExtension
+  sun.security.x509.OIDMap$OIDInfo -> sun.security.x509.NameConstraintsExtension
+  sun.security.x509.OIDMap$OIDInfo -> sun.security.x509.PolicyMappingsExtension
+  sun.security.x509.OIDMap$OIDInfo -> sun.security.x509.AuthorityKeyIdentifierExtension
+  sun.security.x509.OIDMap$OIDInfo -> sun.security.x509.PolicyConstraintsExtension
+  sun.security.x509.OIDMap$OIDInfo -> sun.security.x509.NetscapeCertTypeExtension
+  sun.security.x509.OIDMap$OIDInfo -> sun.security.x509.CertificatePoliciesExtension
+  sun.security.x509.OIDMap$OIDInfo -> sun.security.x509.ExtendedKeyUsageExtension
+  sun.security.x509.OIDMap$OIDInfo -> sun.security.x509.InhibitAnyPolicyExtension
+  sun.security.x509.OIDMap$OIDInfo -> sun.security.x509.CRLDistributionPointsExtension
+  sun.security.x509.OIDMap$OIDInfo -> sun.security.x509.CertificateIssuerExtension
+  sun.security.x509.OIDMap$OIDInfo -> sun.security.x509.SubjectInfoAccessExtension
+  sun.security.x509.OIDMap$OIDInfo -> sun.security.x509.AuthorityInfoAccessExtension
+  sun.security.x509.OIDMap$OIDInfo -> sun.security.x509.IssuingDistributionPointExtension
+  sun.security.x509.OIDMap$OIDInfo -> sun.security.x509.DeltaCRLIndicatorExtension
+  sun.security.x509.OIDMap$OIDInfo -> sun.security.x509.FreshestCRLExtension
+  sun.security.x509.OIDMap$OIDInfo -> sun.security.x509.OCSPNoCheckExtension
+
+# sun.util.LocaleServiceProviderPool$AllAvailableLocales
+@Provider
+  sun.util.LocaleServiceProviderPool$AllAvailableLocales -> META-INF/services/java.text.spi.BreakIteratorProvider
+  sun.util.LocaleServiceProviderPool$AllAvailableLocales -> META-INF/services/java.text.spi.CollatorProvider
+  sun.util.LocaleServiceProviderPool$AllAvailableLocales -> META-INF/services/java.text.spi.DateFormatProvider
+  sun.util.LocaleServiceProviderPool$AllAvailableLocales -> META-INF/services/java.text.spi.DateFormatSymbolsProvider
+  sun.util.LocaleServiceProviderPool$AllAvailableLocales -> META-INF/services/java.text.spi.DecimalFormatSymbolsProvider
+  sun.util.LocaleServiceProviderPool$AllAvailableLocales -> META-INF/services/java.text.spi.NumberFormatProvider
+  sun.util.LocaleServiceProviderPool$AllAvailableLocales -> META-INF/services/java.util.spi.CurrencyNameProvider
+  sun.util.LocaleServiceProviderPool$AllAvailableLocales -> META-INF/services/java.util.spi.LocaleNameProvider
+  sun.util.LocaleServiceProviderPool$AllAvailableLocales -> META-INF/services/java.util.spi.TimeZoneNameProvider
+
+# private static final java.lang.String[] retrieveDisplayNames(sun.util.resources.OpenListResourceBundle, java.lang.String, java.util.Locale)
+@Provider
+  sun.util.TimeZoneNameUtility -> META-INF/services/java.util.spi.TimeZoneNamePProvider
+
+# public static sun.util.calendar.CalendarSystem forName(java.lang.String)
+@ClassForName
+  sun.util.calendar.CalendarSystem -> sun.util.calendar.Gregorian
+  sun.util.calendar.CalendarSystem -> sun.util.calendar.LocalGregorianCalendar
+  sun.util.calendar.CalendarSystem -> sun.util.calendar.JulianCalendar
+
+# sun.util.logging.LoggingSupport
+@ClassForName(optional)
+  sun.util.logging.LoggingSupport -> java.util.logging.LoggingProxyImpl
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/make/modules/modules.config	Wed Jul 05 17:04:56 2017 +0200
@@ -0,0 +1,858 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+// These classes are not referenced in the JDK but we can't
+// remove them for compatibility reason.  Define this module
+// first so that other modules don't need to exclude these clases
+module private-legacy {
+    include sun.misc.Cache*,
+            sun.misc.ClassLoaderUtil,
+            sun.misc.Compare,
+            sun.misc.ConditionLock,
+            sun.misc.CRC16,
+            sun.misc.Lock,
+            sun.misc.Regexp,
+            sun.misc.RequestProcessor,
+            sun.misc.Sort,
+            sun.misc.Request,
+            sun.misc.Timeable,
+            sun.misc.Timer,
+            sun.misc.TimerThread,
+            sun.misc.TimerTickThread,
+            sun.misc.UCDecoder,
+            sun.misc.UCEncoder,
+            sun.misc.UUDecoder,
+            sun.misc.UUEncoder,
+            com.sun.net.ssl.SSLContext,
+            sun.net.NetworkServer,
+            sun.net.URLCanonicalizer,
+            sun.reflect.misc.ConstructorUtil,
+            sun.reflect.FieldInfo,
+            sun.reflect.SignatureIterator,
+            sun.reflect.generics.reflectiveObjects.NotImplementedException,
+            sunw.io.Serializable,
+            sunw.util.EventListener,
+            sunw.util.EventObject;
+}
+
+// Deprecated classes that aren't referenced/used go here.
+module deprecated {
+    // add deprecated security classes once b78 is promoted
+}
+
+/**************************************************************************/
+
+module base {
+    // core classes
+    include java.lang.*,
+            java.lang.annotation.*,
+            java.lang.ref.*,
+            java.lang.reflect.*,
+            java.math.*,
+            java.net.*,
+            java.util.*,
+            java.util.concurrent.**,
+            java.util.jar.*,
+            java.util.regex.*,
+            java.util.spi.*,
+            java.util.zip.*,
+            java.text.**;
+
+    exclude java.util.jar.Pack200*,
+            java.util.XMLUtils,
+            java.text.Bidi;
+
+    include java.io.*, java.nio.*, java.nio.charset.**;
+    exclude java.io.TempFileHelper, java.nio.BufferPoolMXBean;
+
+    // security APIs
+    // javax.crypto and javax.security.auth are included to avoid inconsistent
+    // spliting of JCA and JAAS. This adds about 85k. Also note that some deprecated
+    // classes must be included for now (see 6876158, 6876170)
+    include java.security.*,
+            java.security.cert.*,
+            java.security.interfaces.*,
+            java.security.spec.*,
+            javax.security.auth.**,
+            javax.crypto.**;
+
+    // Sun and RSA security providers (except LDAP CertStore)
+    // roots sun.security.provider.* sun.security.provider.certpath.* sun.security.rsa.*
+    include com.sun.security.auth.PrincipalComparator,
+            com.sun.security.auth.SubjectCodeSource,
+            com.sun.security.auth.login.**,
+            com.sun.security.auth.Policy*,
+            sun.security.action.*,
+            sun.security.ec.*,
+            sun.security.jca.*,
+            sun.security.pkcs.*,
+            sun.security.provider.*,
+            sun.security.provider.certpath.*,
+            sun.security.rsa.*,
+            sun.security.util.*,
+            sun.security.validator.*,
+            sun.security.x509.*,
+            sun.security.timestamp.*;
+
+    // this list is based on the classlist generated from the rootset
+    // need investigation
+    exclude sun.security.ec.ECD*,
+            sun.security.ec.ECKeyPairGenerator,
+            sun.security.ec.SunEC*,
+            sun.security.pkcs.PKCS10*,
+            sun.security.pkcs.EncodingException,
+            sun.security.util.AuthResources_*,
+            sun.security.util.Resources_*,
+            sun.security.util.BigInt,
+            sun.security.util.HostnameChecker,
+            sun.security.x509.CertAndKeyGen,
+            sun.security.util.PathList;
+
+    // Kerberos not needed
+    exclude javax.security.auth.kerberos.**,
+            sun.security.jgss.**,
+            sun.security.krb5.**,
+            sun.security.ssl.Kerberos*,
+            org.ietf.jgss.**;
+
+   // property events and annotations
+   include java.beans.ChangeListenerMap,
+           java.beans.IndexedPropertyChangeEvent,
+           java.beans.PropertyChange*,
+           java.beans.PropertyVetoException,
+           java.beans.VetoableChange*,
+           java.beans.ConstructorProperties;
+
+    // mandatory charsets
+    include sun.nio.cs.*;
+
+    exclude sun.nio.cs.AbstractCharsetProvider,
+            sun.nio.cs.CharsetMapping,
+            sun.nio.cs.IBM*,
+            sun.nio.cs.ISO*,
+            sun.nio.cs.KOI8_*,
+            sun.nio.cs.MS125*,
+            sun.nio.cs.UTF_32*,
+            sun.nio.cs.SingleByteDecoder,
+            sun.nio.cs.SingleByteEncoder;
+
+    allow   sun.nio.cs.ISO_8859_1,
+            sun.nio.cs.ISO_8859_15,
+            sun.nio.cs.MS1252;
+
+    include sun.text.*,
+            sun.text.normalizer.*;
+
+    // resource files
+    include sun/text/resources/*.icu;
+
+    exclude sun.text.bidi.*,
+            sun.text.CharArrayCodePointIterator,
+            sun.text.CharSequenceCodePointIterator,
+            sun.text.CharacterIteratorCodePointIterator,
+            sun.text.CodePointIterator;
+
+    include sun.util.*,
+            sun.util.calendar.*,
+            sun.util.logging.*,
+            sun.util.resources.LocaleData,
+            sun.util.resources.LocaleNamesBundle,
+            sun.util.resources.OpenListResourceBundle;
+
+    // US_en locale
+    include sun.text.resources.BreakIteratorInfo,
+            sun.text.resources.FormatData,
+            sun.text.resources.FormatData_en_US,
+            sun.util.resources.CalendarData,
+            sun.util.resources.CalendarData_en,
+            sun.util.resources.TimeZoneNames,
+            sun.util.resources.TimeZoneNames_en,
+            sun.util.resources.TimeZoneNamesBundle,
+            sun.util.resources.LocaleNames,
+            sun.util.resources.LocaleNames_en,
+            sun.util.resources.LocalenamesBundles,
+            sun.util.resources.CurrencyNames,
+            sun.util.resources.CurrencyNames_en_US,
+            sun.util.EmptyListResourceBundle;
+
+    // resources file needed by
+    // - sun.misc.ExtensionInfo
+    // - sun.security.provider.PolicyFile
+    // - com.sun.security.auth.PolicyFile
+    include sun.misc.resources.Messages,
+            sun.security.util.Resources,
+            sun.security.util.AuthResources;
+
+    // java.nio.channels and java.nio.file not in base
+    include sun.nio.ch.Interruptible,
+            sun.nio.ch.DirectBuffer,
+            sun.nio.ByteBuffered;
+
+    include sun.reflect.**;
+
+    // protocol handlers
+    include sun.net.www.protocol.file.*,
+            sun.net.www.protocol.jar.*,
+            sun.net.www.protocol.http.*;
+
+    include sun.net.*,
+            sun.net.spi.*,
+            sun.net.idn.*,
+            sun.net.util.*,
+            sun.net.www.*,
+            sun.net.www.http.*,
+            sun.net.spi.nameservice.*;
+
+    // resource file for sun.net.idn
+    include sun/net/idn/*;
+
+    // classes in net-compat
+    exclude sun.net.Telnet*, sun.net.TransferProtocolClient;
+
+    // classes in deploy
+    exclude sun.net.www.protocol.http.AuthCacheBridge;
+
+    // classes in security-jsse
+    exclude java.net.SecureCacheResponse;
+
+    // launcher
+    include sun.launcher.LauncherHelper, sun.launcher.resources.launcher;
+
+    include sun.misc.*;
+    exclude sun.misc.FIFOQueueEnumerator,
+            sun.misc.LIFOQueueEnumerator,
+            sun.misc.GC,
+            sun.misc.PerformanceLogger,
+            sun.misc.Queue,
+            sun.misc.QueueElement,
+            sun.misc.Ref,
+            sun.misc.VMSupport;
+
+    // On Windows, OSEnvironment dependency
+    include sun.io.Win32ErrorMode;
+}
+
+/**************************************************************************/
+
+module charsets {
+    include sun.nio.cs.ext.**;
+
+    include sun.nio.cs.AbstractCharsetProvider,
+            sun.nio.cs.CharsetMapping,
+            sun.nio.cs.IBM*,
+            sun.nio.cs.ISO*,
+            sun.nio.cs.KOI8_*,
+            sun.nio.cs.MS125*,
+            sun.nio.cs.SingleByte*,
+            sun.nio.cs.UTF_32*;
+
+    exclude sun.nio.cs.ISO_8859_1,
+            sun.nio.cs.MS1252;
+
+    // legacy sun.io converters
+    include sun.io.*;
+}
+
+/**************************************************************************/
+
+// For now, retains the current JRE extensions where localedata.jar in jre/lib/ext 
+module localedata {
+    include sun.util.resources.*_ar,
+            sun.util.resources.*_ar_*,
+            sun.util.resources.*_hi,
+            sun.util.resources.*_hi_*,
+            sun.util.resources.*_iw,
+            sun.util.resources.*_iw_*,
+            sun.util.resources.*_ja,
+            sun.util.resources.*_ja_*,
+            sun.util.resources.*_ko,
+            sun.util.resources.*_ko_*,
+            sun.util.resources.*_th,
+            sun.util.resources.*_th_*,
+            sun.util.resources.*_vi,
+            sun.util.resources.*_vi_*,
+            sun.util.resources.*_zh,
+            sun.util.resources.*_zh_*;
+    include sun.text.resources.*_ar,
+            sun.text.resources.*_ar_*,
+            sun.text.resources.*_hi,
+            sun.text.resources.*_hi_*,
+            sun.text.resources.*_iw,
+            sun.text.resources.*_iw_*,
+            sun.text.resources.*_ja,
+            sun.text.resources.*_ja_*,
+            sun.text.resources.*_ko,
+            sun.text.resources.*_ko_*,
+            sun.text.resources.*_th,
+            sun.text.resources.*_th_*,
+            sun.text.resources.*_vi,
+            sun.text.resources.*_vi_*,
+            sun.text.resources.*_zh,
+            sun.text.resources.*_zh_*;
+}
+
+module resources {
+    include sun.text.resources.*, sun.util.resources.*, sun.misc.resources.*;
+}
+
+/**************************************************************************/
+
+module nio {
+    include java.nio.channels.**, java.nio.file.**, com.sun.nio.file.**;
+
+    // this is excluded from base
+    include java.io.TempFileHelper;
+
+    // provider implementations and their dependencies
+    include sun.nio.ch.*, sun.nio.fs.**;
+    exclude sun.nio.ch.Sctp*;
+}
+
+/**************************************************************************/
+
+module pack200 {
+    include java.util.jar.Pack200*, com.sun.java.util.jar.pack.**;
+}
+
+/**************************************************************************/
+
+module logging {
+    include java.util.logging.*, sun.util.logging.**;
+    exclude java.util.logging.PlatformLoggingMXBean;
+
+    // Formatter for HTTP messages
+    include sun.net.www.protocol.http.logging.*;
+}
+
+/**************************************************************************/
+
+module management-snmp {
+    include com.sun.jmx.snmp.**, sun.management.snmp.**;
+}
+
+module management-iiop {
+    include com.sun.jmx.remote.protocol.iiop.*;
+
+    // stubs and ties
+    include javax.management.remote.rmi._*,
+            org.omg.stub.javax.management.remote.rmi.**;
+}
+
+module management {
+    include java.lang.management.*, com.sun.management.**, sun.management.**;
+    include javax.management.**, com.sun.jmx.**;
+
+    // other management interfaces
+    include java.nio.BufferPoolMXBean;
+    include java.util.logging.PlatformLoggingMXBean;
+
+    // supporting classes in sun.misc
+    include sun.misc.VMSupport;
+}
+
+/**************************************************************************/
+
+module instrument {
+    // java.lang.instrument
+    include java.lang.instrument.*, sun.instrument.*;
+
+    // tracing
+    include com.sun.tracing.**, sun.tracing.**;
+
+    // HPROF support
+    include com.sun.demo.jvmti.hprof.*;
+}
+
+/**************************************************************************/
+
+module rmi-activation {
+    include java.rmi.activation.**,
+            sun.rmi.server.Act*,
+            sun.rmi.server.InactiveGroupException;
+}
+
+module rmi {
+    include java.rmi.**, sun.rmi.**, com.sun.rmi.**;
+
+    // SSL factories are in rmi
+    include javax.rmi.ssl.**;
+
+    // rmic is in tools
+    exclude sun.rmi.rmic.**;
+
+    // supporting classes in sun.misc and dependencies
+    include sun.misc.GC;
+}
+
+/**************************************************************************/
+
+module prefs {
+    include java.util.prefs.*;
+}
+
+/**************************************************************************/
+
+module security-jsse {
+    include javax.net.**,
+            javax.security.cert.*,
+            java.net.SecureCacheResponse,
+            com.sun.net.ssl.**,
+            com.sun.security.cert.internal.x509.*,
+            sun.security.ssl.*,
+            sun.net.www.protocol.https.**,
+            sun.security.internal.interfaces.Tls*,
+            sun.security.internal.spec.Tls*,
+            sun.security.util.HostnameChecker;
+}
+
+module security-sunpkcs11 {
+    include sun.security.pkcs11.**;
+}
+
+module security-sunjce {
+    include com.sun.crypto.provider.*;
+}
+
+module security-sunec {
+    include sun.security.ec.*;
+}
+
+module security-sunmscapi {
+    include sun.security.mscapi.*;
+}
+
+module security-kerberos {
+    include javax.security.auth.kerberos.*,
+            com.sun.security.jgss.**,
+            com.sun.security.auth.module.Krb5LoginModule,
+            com.sun.security.sasl.gsskerb.**,             // GSSAPI SASL mechanism
+            sun.security.jgss.**,
+            sun.security.ssl.krb5.**,
+            sun.security.krb5.**,
+            org.ietf.jgss.**,
+            sun.net.www.protocol.http.spnego.*;
+}
+
+module security-sasl {
+    include javax.security.sasl.**,
+            com.sun.security.sasl.**;
+}
+
+module security-xmldsig {
+    include javax.xml.crypto.**,
+            org.jcp.xml.dsig.**,
+            com.sun.org.apache.xml.internal.security.**;
+}
+
+module security-smartcardio {
+    include javax.smartcardio.**, sun.security.smartcardio.**;
+}
+
+module security-misc {
+    include com.sun.security.auth.**, sun.security.util.AuthResources_*,
+            sun.security.pkcs.*,
+            sun.security.pkcs12.*;
+
+    // this class is a candidate to be removed.
+    include sun.security.util.BigInt;
+}
+
+module security-resources {
+    include sun.security.util.Resources_*;
+}
+
+module security-compat {
+    include java.security.acl.*, sun.security.acl.*;
+}
+
+/**************************************************************************/
+
+module jndi-ldap {
+    include javax.naming.ldap.**,
+            com.sun.jndi.ldap.**,
+            com.sun.jndi.url.ldap.*,
+            com.sun.jndi.url.ldaps.*,
+            sun.security.provider.certpath.ldap.**;
+}
+
+module jndi-rmiregistry {
+    include com.sun.jndi.rmi.**, com.sun.jndi.url.rmi.**;
+}
+
+module jndi-dns {
+    include com.sun.jndi.dns.**, com.sun.jndi.url.dns.**;
+    include sun.net.dns.**;                 // to access DNS config.
+    include sun.net.spi.nameservice.dns.**; // for DNS-only name service.
+}
+
+module jndi-cosnaming {
+    include com.sun.jndi.cosnaming.**,
+            com.sun.jndi.toolkit.corba.**,
+            com.sun.jndi.url.corbaname.**,
+            com.sun.jndi.url.iiop.**,
+            com.sun.jndi.url.iiopname.**;
+}
+
+// framework/API and classes used by providers
+module jndi {
+    include javax.naming.**,
+            com.sun.naming.**,
+            com.sun.jndi.toolkit.ctx.**,
+            com.sun.jndi.toolkit.dir.**,
+            com.sun.jndi.toolkit.url.**;
+}
+
+/**************************************************************************/
+
+module jdbc-base {
+    include java.sql.**, javax.sql.*;
+    exclude javax.sql.XA*;
+}
+
+module jdbc-enterprise {
+    include javax.sql.**, com.sun.rowset.**;
+}
+
+module jdbc-odbc {
+    include sun.jdbc.odbc.**;
+}
+
+/**************************************************************************/
+
+module scripting {
+    include javax.script.**;
+
+    // supporting classes for scripting engines
+    include com.sun.script.util.**;
+}
+
+module scripting-rhino {
+    include com.sun.script.javascript.**, sun.org.mozilla.javascript.**;
+}
+
+/**************************************************************************/
+
+module httpserver {
+    include com.sun.net.httpserver.**, sun.net.httpserver.**;
+}
+
+/**************************************************************************/
+
+module sctp {
+    // API and dependencies
+    include com.sun.nio.sctp.**, sun.nio.ch.Sctp*;
+}
+
+/**************************************************************************/
+
+module langtools {
+    include javax.tools.**, javax.lang.model.**, javax.annotation.processing.**;
+
+    // include mirror API for now
+    include com.sun.mirror.**;
+
+    // include the JSR292 APIs for now
+    include java.dyn.**, sun.dyn.**;
+}
+
+/**************************************************************************/
+
+module beans {
+    include java.beans.**, com.sun.beans.**, sun.beans.**;
+}
+
+/**************************************************************************/
+
+module jaxp-parsers-api {
+    include javax.xml.*, javax.xml.parsers.**,
+            org.w3c.dom.**, org.w3c.sax.**, org.xml.sax.**;
+}
+
+module jaxp-api {
+    include javax.xml.**;
+    exclude javax.xml.crypto.**,   // XML-DSIG
+            javax.xml.bind.**,     // JAX-WS
+            javax.xml.soap.**,
+            javax.xml.ws.**;
+}
+
+module jaxp-xerces-impl {
+    include com.sun.org.apache.xerces.internal.**;
+
+    // include in xerces-impl due to circular dependencies
+    include com.sun.org.apache.xml.internal.serialize.**,
+            com.sun.xml.internal.stream.**;
+    exclude com.sun.xml.internal.stream.buffer.**;  // JAX-WS
+}
+
+// required by Xerces and JAX-WS
+module jaxp-xerces-resolver {
+    include com.sun.org.apache.xml.internal.resolver.**;
+}
+
+module jaxp-xalan {
+    include com.sun.org.apache.xalan.internal.**,
+            com.sun.org.apache.xpath.internal.**,
+            com.sun.org.apache.xml.internal.dtm.**,
+            com.sun.org.apache.xml.internal.res.**,
+            com.sun.org.apache.xml.internal.serializer.**,
+            com.sun.org.apache.xml.internal.utils.**,
+            com.sun.org.apache.bcel.internal.**,
+            com.sun.org.apache.regexp.internal.**,
+            com.sun.java_cup.internal.**;
+}
+
+/**************************************************************************/
+
+module jaxws-tools {
+    include com.sun.codemodel.**,
+            com.sun.xml.internal.dtdparser.**,
+            com.sun.xml.internal.rngom.**,
+            com.sun.xml.internal.xsom.**,
+            com.sun.istack.internal.tools.**,
+            com.sun.istack.internal.ws.**,
+            com.sun.tools.internal.xjc.**,
+            com.sun.tools.internal.ws.**,
+            com.sun.tools.internal.jxc.**,
+            org.relaxng.datatype.**;
+}
+
+module jaxws {
+    include javax.jws.**,
+            javax.xml.bind.**,
+            javax.xml.soap.**,
+            javax.xml.ws.**,
+            org.relaxng.**,
+            com.sun.istack.internal.*,
+            com.sun.istack.internal.localization.*,
+            com.sun.xml.internal.**;
+
+    // include JAF in this module
+    include javax.activation.**, com.sun.activation.**;
+
+    include META-INF/mailcap.default,
+            META-INF/mimetypes.default;
+}
+
+/**************************************************************************/
+module enterprise-base {
+    include javax.transaction.**,  // JTA
+            javax.annotation.*;    // Common annotations (JSR-250)
+}
+
+/**************************************************************************/
+module corba {
+    include javax.activity.**,
+            javax.rmi.*,
+            javax.rmi.CORBA.*,
+            javax.transaction.**,
+            com.sun.corba.**,
+            com.sun.org.omg.**,
+            org.omg.**,
+            sun.corba.**;
+
+    // JMX remote API
+    exclude org.omg.stub.javax.management.**;
+}
+
+/**************************************************************************/
+
+module client {
+    include java.applet.**,
+            java.awt.**,
+            javax.accessibility.*,
+            javax.imageio.**,
+            javax.print.**,
+            javax.sound.**,
+            javax.swing.**,
+            sun.applet.**,
+            sun.audio.**,
+            sun.awt.**,
+            sun.dc.**,
+            sun.font.**,
+            sun.java2d.**,
+            sun.print.**,
+            sun.swing.**,
+            com.sun.accessibility.**,
+            com.sun.awt.**,
+            com.sun.image.**,
+            com.sun.imageio.**,
+            com.sun.java.swing.*,       // sajdi also contains classes in a subpackage;
+                                        // so use '*' instead of '**' 
+            com.sun.java.swing.plaf.**,
+            com.sun.media.**,
+            com.sun.swing.**;
+
+    // Bidi class in client module for now
+    include java.text.Bidi, sun.text.bidi.*;
+
+    // PerformanceLogger and dependencies
+    include sun.misc.Ref, sun.misc.PerformanceLogger;
+
+    // misc. dependencies that we need to examine
+    include sun.text.CodePointIterator,
+            sun.text.Char*,
+            sun.misc.Queue*,
+            sun.misc.FIFOQueueEnumerator,
+            sun.misc.LIFOQueueEnumerator;
+
+    // content handlers
+    include sun.net.www.content.audio.**,
+            sun.net.www.content.image.**;
+}
+
+/**************************************************************************/
+
+module deploy {
+    // For now, all plugin and JNLP
+    include com.sun.java.browser.**,
+            netscape.**,
+            sun.plugin.**,
+            sun.plugin2.**,,
+            com.sun.deploy.**,
+            com.sun.javaws.**,
+            javax.jnlp.*,
+            com.sun.jnlp.*,
+            sun.jkernel.*;
+
+    // Hook for http authentication
+    include sun.net.www.protocol.http.AuthCacheBridge;
+}
+
+/**************************************************************************/
+
+module net-compat {
+    // NTLM authentication support
+    include sun.net.www.protocol.http.ntlm.*;
+
+    // ftp and mail clients
+    include sun.net.ftp.**, sun.net.smtp.**;
+
+    // Legacy protocol handlers
+    include sun.net.www.protocol.**;
+
+    // Legacy content handlers
+    include sun.net.www.content.**;
+
+    include sun.net.Telnet*,
+            sun.net.TransferProtocolClient;
+}
+
+/**************************************************************************/
+
+// jar-tool and security-tools are JRE tools
+module jar-tool {
+    include sun.tools.jar.**;
+}
+
+module security-tools {
+    include sun.security.tools.**;
+
+    // Used by security tools
+    include sun.security.util.PathList, sun.security.x509.CertAndKeyGen;
+
+    exclude sun.security.tools.JarBASE64Encoder,
+            sun.security.tools.JarSigner,
+            sun.security.tools.JarSignerParameters,
+            sun.security.tools.JarSignerResources*,
+            sun.security.tools.SignatureFile,
+            sun.security.tools.TimestampedSigner;
+}
+
+module jconsole {
+    include sun.tools.jconsole.**,
+            com.sun.tools.jconsole.*;
+}
+
+module serialver {
+    include sun.tools.serialver.**;
+}
+
+module gui-tools {
+    include jconsole,
+            serialver;
+
+    include com.sun.tools.example.debug.bdi.**,
+            com.sun.tools.example.debug.gui.**,
+            com.sun.tools.internal.xjc.**;
+}
+
+module attach {
+    include com.sun.tools.attach.**,
+            sun.tools.attach.**;
+}
+
+module debugging {
+    include com.sun.jdi.**, com.sun.tools.jdi.**;
+}
+
+module jdb {
+    include com.sun.tools.example.debug.**;
+}
+
+module sajdi {
+    include sun.jvm.hotspot.**,
+            com.sun.java.swing.ui.**,
+            com.sun.java.swing.action.**;
+
+    include toolbarButtonGraphics/**;
+    include sa.properties;
+}
+
+module tools {
+    include attach,
+            debugging,
+            jaxws-tools,
+            jdb,
+            sajdi;
+
+    // include gui-tools in tools module unless the tool binaries
+    // are modified to load the new gui-tools.jar
+    include gui-tools;
+
+    include com.sun.tools.**, sun.tools.**, sun.security.tools.**,
+            com.sun.jarsigner.**,
+            com.sun.javac.**,
+            com.sun.javadoc.**, com.sun.source.**,
+            sun.jvmstat.**,
+            sun.rmi.rmic.**;
+}
+
+/**************************************************************************/
+
+module servicetag {
+    include com.sun.servicetag.**;
+}
+
+/**************************************************************************/
+
+// these classes will be removed from JRE - see 6909002
+module inputmethods-ext {
+    include com.sun.inputmethods.internal.**;
+}
+
+/**************************************************************************/
+
+module other {
+    include **;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/make/modules/modules.group	Wed Jul 05 17:04:56 2017 +0200
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * Example:
+ *    module jdbc {
+ *        include jdbc-base, jdbc-enterprise, jdbc-odbc;
+ *    }
+ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/make/modules/optional.depconfig	Wed Jul 05 17:04:56 2017 +0200
@@ -0,0 +1,124 @@
+# public final java.nio.channels.SocketChannel getChannel()
+@Optional
+  sun.security.ssl.BaseSSLSocketImpl -> java.nio.channels.SocketChannel
+
+# public XMLDecoder(java.io.InputStream)
+# public XMLDecoder(java.io.InputStream, java.lang.Object)
+# public XMLDecoder(java.io.InputStream, java.lang.Object, java.beans.ExceptionListener)
+# public XMLDecoder(java.io.InputStream, java.lang.Object, java.beans.ExceptionListener, java.lang.ClassLoader)
+# public XMLDecoder(org.xml.sax.InputSource)
+@Optional
+  java.beans.XMLDecoder -> com.sun.beans.decoder.DocumentHandler
+  java.beans.XMLDecoder -> org.xml.sax.InputSource
+
+# public static org.xml.sax.helpers.DefaultHandler createHandler(java.lang.Object, java.beans.ExceptionListener, java.lang.ClassLoader)
+@Optional
+  java.beans.XMLDecoder -> com.sun.beans.decoder.DocumentHandler
+  java.beans.XMLDecoder -> org.xml.sax.helpers.DefaultHandler
+
+# public final java.nio.channels.FileChannel getChannel()
+@Optional
+  java.net.SocketInputStream -> java.nio.channels.FileChannel
+
+# public final java.nio.channels.FileChannel getChannel()
+@Optional
+  java.net.SocketOutputStream -> java.nio.channels.FileChannel
+
+# public Scanner(java.io.File)
+# public Scanner(java.io.File, java.lang.String)
+@Optional
+  java.util.Scanner -> java.nio.channels.ReadableByteChannel
+  java.util.Scanner -> java.nio.channels.Channels
+
+# public Scanner(java.nio.file.FileRef)
+# public Scanner(java.nio.file.FileRef, java.lang.String)
+@Optional
+  java.util.Scanner -> java.nio.file.FileRef
+  java.util.Scanner -> java.nio.file.OpenOption
+
+# public Scanner(java.nio.channels.ReadableByteChannel)
+# public Scanner(java.nio.channels.ReadableByteChannel, java.lang.String)
+@Optional
+  java.util.Scanner -> java.nio.channels.ReadableByteChannel
+  java.util.Scanner -> java.nio.channels.Channels
+
+# private static void loadSnmpAgent(java.lang.String, java.util.Properties)
+@Optional
+  sun.management.Agent -> sun.management.snmp.AdaptorBootstrap
+
+# public void connect()
+@Optional
+  sun.net.www.protocol.http.HttpURLConnection -> java.net.SecureCacheResponse
+
+# private static sun.security.util.PermissionFactory<?> permissionFactory()
+@Optional
+  sun.security.util.SecurityConstants$AWT -> sun.awt.AWTPermissionFactory
+
+# sun.util.logging.LoggingSupport
+@Optional
+  sun.util.logging.LoggingSupport -> java.util.logging.LoggingProxyImpl
+
+# public java.nio.channels.DatagramChannel getChannel()
+@Optional
+  java.net.DatagramSocket -> java.nio.channels.DatagramChannel
+
+# public java.nio.channels.SocketChannel getChannel()
+@Optional
+  java.net.Socket -> java.nio.channels.SocketChannel
+
+# public java.nio.channels.ServerSocketChannel getChannel()
+@Optional
+  java.net.ServerSocket -> java.nio.channels.ServerSocketChannel
+
+# public final java.nio.channels.FileChannel getChannel()
+@Optional
+  java.io.RandomAccessFile -> java.nio.channels.FileChannel
+  java.io.RandomAccessFile -> sun.nio.ch.FileChannelImpl
+
+# public static sun.nio.cs.StreamDecoder forDecoder(java.nio.channels.ReadableByteChannel, java.nio.charset.CharsetDecoder, int)
+@Optional
+  sun.nio.cs.StreamDecoder -> java.nio.channels.ReadableByteChannel
+
+# private static java.nio.channels.FileChannel getChannel(java.io.FileInputStream)
+# StreamDecoder(java.io.InputStream, java.lang.Object, java.nio.charset.CharsetDecoder)
+@Optional
+  sun.nio.cs.StreamDecoder -> java.nio.channels.FileChannel
+
+# StreamDecoder(java.nio.channels.ReadableByteChannel, java.nio.charset.CharsetDecoder, int)
+@Optional
+  sun.nio.cs.StreamDecoder -> java.nio.channels.ReadableByteChannel
+
+# public static java.io.File createTemporaryFile(java.lang.String, java.lang.String, java.nio.file.attribute.FileAttribute<?>[])
+@Optional
+  java.io.File -> java.io.TempFileHelper
+  java.io.File -> java.nio.file.attribute.FileAttribute
+
+# public java.nio.file.Path toPath()
+@Optional
+  java.io.File -> java.nio.file.Paths
+  java.io.File -> java.nio.file.Path
+
+# public static sun.nio.cs.StreamEncoder forEncoder(java.nio.channels.WritableByteChannel, java.nio.charset.CharsetEncoder, int)
+# private StreamEncoder(java.nio.channels.WritableByteChannel, java.nio.charset.CharsetEncoder, int)
+@Optional
+  sun.nio.cs.StreamEncoder -> java.nio.channels.WritableByteChannel
+
+# public java.nio.channels.FileChannel getChannel()
+@Optional
+  java.io.FileOutputStream -> java.nio.channels.FileChannel
+  java.io.FileOutputStream -> sun.nio.ch.FileChannelImpl
+
+# public java.nio.channels.FileChannel getChannel()
+@Optional
+  java.io.FileInputStream -> java.nio.channels.FileChannel
+  java.io.FileInputStream -> sun.nio.ch.FileChannelImpl
+
+# public void loadFromXML(java.io.InputStream)
+# public void storeToXML(java.io.OutputStream, java.lang.String, java.lang.String)
+@Optional
+  java.util.Properties -> java.util.XMLUtils
+
+# public static java.nio.channels.Channel inheritedChannel()
+@Optional
+  java.lang.System -> java.nio.channels.Channel
+  java.lang.System -> java.nio.channels.spi.SelectorProvider
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/make/modules/tools/Makefile	Wed Jul 05 17:04:56 2017 +0200
@@ -0,0 +1,85 @@
+#
+# Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
+# 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.  Sun designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+# CA 95054 USA or visit www.sun.com if you need additional information or
+# have any questions.
+#
+
+#
+# Makefile for building the classanalyzer tool
+#
+
+BUILDDIR = ../..
+PACKAGE = com.sun.classanalyzer
+PRODUCT = tools
+PROGRAM = classanalyzer
+include $(BUILDDIR)/common/Defs.gmk
+
+BUILDTOOL_SOURCE_ROOT = src
+BUILDTOOL_MAIN        = $(PKGDIR)/ClassAnalyzer.java
+BUILTTOOL_MAINCLASS   = $(subst /,.,$(BUILDTOOL_MAIN:%.java=%))
+
+BUILDTOOL_MAIN_SOURCE_FILE = $(BUILDTOOL_SOURCE_ROOT)/$(BUILDTOOL_MAIN)
+BUILDTOOL_MANIFEST_FILE    = $(BUILDTOOLCLASSDIR)/$(PROGRAM)_manifest.mf
+BUILDTOOL_JAR_FILE         = $(BUILDTOOLJARDIR)/$(PROGRAM).jar
+
+FILES_java := $(shell $(CD) $(BUILDTOOL_SOURCE_ROOT) \
+    && $(FIND) $(PKGDIR) $(SCM_DIRS_prune) -o -type f -print)
+FILES_class = $(FILES_java:%.java=$(BUILDTOOLCLASSDIR)/%.class)
+
+all build: $(BUILDTOOL_JAR_FILE) tool_info
+
+$(BUILDTOOL_MANIFEST_FILE): $(BUILDTOOL_MAIN_SOURCE_FILE)
+	@$(prep-target)
+	$(ECHO) "Main-Class: $(BUILTTOOL_MAINCLASS)" > $@
+
+$(BUILDTOOLCLASSDIR)/%.class : $(BUILDTOOL_SOURCE_ROOT)/%.java
+	@$(prep-target)
+	$(JAVAC_CMD) \
+            -sourcepath $(BUILDTOOL_SOURCE_ROOT) \
+            -d $(BUILDTOOLCLASSDIR) $<
+
+$(BUILDTOOL_JAR_FILE): $(BUILDTOOL_MANIFEST_FILE) $(FILES_class)
+	@$(prep-target)
+	$(BOOT_JAR_CMD) cfm $@ $(BUILDTOOL_MANIFEST_FILE) \
+	    -C $(BUILDTOOLCLASSDIR) $(PKGDIR) \
+	    $(BOOT_JAR_JFLAGS) || $(RM) $@
+	$(java-vm-cleanup)
+
+# Printing out a build tool information line
+define printBuildToolSetting
+if [ "$2" != "" ] ; then $(PRINTF) "%-25s %s\n" "$1:" "$2"; fi
+endef
+
+# Print out the build tool information
+tool_info:
+	@$(ECHO) "========================================================="
+	@$(call printBuildToolSetting,BUILDTOOL,$(PROGRAM))
+	@$(call printBuildToolSetting,PACKAGE,$(PACKAGE))
+	@$(call printBuildToolSetting,BUILDTOOL_SOURCE_ROOT,$(BUILDTOOL_SOURCE_ROOT))
+	@$(call printBuildToolSetting,BUILTTOOL_MAINCLASS,$(BUILTTOOL_MAINCLASS))
+	@$(call printBuildToolSetting,BUILDTOOL_JAR_FILE,$(BUILDTOOL_JAR_FILE))
+	@$(ECHO) "========================================================="
+
+clean clobber::
+	@$(RM) -rf $(BUILDTOOLCLASSDIR)/$(PKGDIR)
+	@$(RM) $(BUILDTOOL_MANIFEST_FILE)
+	@$(RM) $(BUILDTOOL_JAR_FILE)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/make/modules/tools/build.xml	Wed Jul 05 17:04:56 2017 +0200
@@ -0,0 +1,33 @@
+<!--
+ Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+   - Redistributions of source code must retain the above copyright
+     notice, this list of conditions and the following disclaimer.
+
+   - Redistributions in binary form must reproduce the above copyright
+     notice, this list of conditions and the following disclaimer in the
+     documentation and/or other materials provided with the distribution.
+
+   - Neither the name of Sun Microsystems nor the names of its
+     contributors may be used to endorse or promote products derived
+     from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+-->
+
+<project name="classanalyzer" default="build" basedir=".">
+</project>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/make/modules/tools/nbproject/project.properties	Wed Jul 05 17:04:56 2017 +0200
@@ -0,0 +1,92 @@
+#
+# Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+#   - Redistributions of source code must retain the above copyright
+#     notice, this list of conditions and the following disclaimer.
+#
+#   - Redistributions in binary form must reproduce the above copyright
+#     notice, this list of conditions and the following disclaimer in the
+#     documentation and/or other materials provided with the distribution.
+#
+#   - Neither the name of Sun Microsystems nor the names of its
+#     contributors may be used to endorse or promote products derived
+#     from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+# IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+# PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+
+application.title=classanalyzer
+application.vendor=mchung
+build.classes.dir=${build.dir}/classes
+build.classes.excludes=**/*.java,**/*.form
+
+# This directory is removed when the project is cleaned:
+build.dir=build
+build.generated.dir=${build.dir}/generated
+build.generated.sources.dir=${build.dir}/generated-sources
+
+# Only compile against the classpath explicitly listed here:
+build.sysclasspath=ignore
+build.test.classes.dir=${build.dir}/test/classes
+build.test.results.dir=${build.dir}/test/results
+
+cp.extra=${tools.jar} 
+
+debug.classpath=\
+    ${run.classpath}
+debug.test.classpath=\
+    ${run.test.classpath}
+
+# This directory is removed when the project is cleaned:
+dist.dir=dist
+dist.jar=${dist.dir}/classanalyzer.jar
+dist.javadoc.dir=${dist.dir}/javadoc
+
+excludes=
+
+file.reference.tools.jar=${jdk.home}/lib/tools.jar
+file.reference.tools-src=src
+includes=**
+jar.compress=false
+javac.classpath=\
+    ${file.reference.tools.jar}
+javac.deprecation=false
+javac.source=1.5
+javac.target=1.5
+javac.test.classpath=
+javadoc.author=false
+javadoc.noindex=false
+javadoc.nonavbar=false
+javadoc.notree=false
+javadoc.private=false
+javadoc.splitindex=false
+javadoc.use=false
+javadoc.version=false
+main.class=com.sun.classanalyzer.ClassAnalyzer
+manifest.file=manifest.mf
+meta.inf.dir=${src.dir}/META-INF
+platform.active=JDK_1.6
+run.classpath=\
+    ${javac.classpath}:\
+    ${build.classes.dir}
+# Space-separated list of JVM arguments used when running the project
+# (you may also define separate properties like run-sys-prop.name=value instead of -Dname=value
+# or test-sys-prop.name=value to set system properties for unit tests):
+run.jvmargs=-Xmx256m
+run.test.classpath=
+source.encoding=UTF-8
+src.dir=${file.reference.tools-src}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/make/modules/tools/nbproject/project.xml	Wed Jul 05 17:04:56 2017 +0200
@@ -0,0 +1,45 @@
+<!--
+ Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+   - Redistributions of source code must retain the above copyright
+     notice, this list of conditions and the following disclaimer.
+
+   - Redistributions in binary form must reproduce the above copyright
+     notice, this list of conditions and the following disclaimer in the
+     documentation and/or other materials provided with the distribution.
+
+   - Neither the name of Sun Microsystems nor the names of its
+     contributors may be used to endorse or promote products derived
+     from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+-->
+
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://www.netbeans.org/ns/project/1">
+    <type>org.netbeans.modules.java.j2seproject</type>
+    <configuration>
+        <data xmlns="http://www.netbeans.org/ns/j2se-project/3">
+            <name>classanalyzer</name>
+            <explicit-platform explicit-source-supported="true"/>
+            <source-roots>
+                <root id="src.dir"/>
+            </source-roots>
+            <test-roots/>
+        </data>
+    </configuration>
+</project>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/make/modules/tools/src/com/sun/classanalyzer/AnnotatedDependency.java	Wed Jul 05 17:04:56 2017 +0200
@@ -0,0 +1,627 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ *
+ */
+package com.sun.classanalyzer;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+import java.util.TreeSet;
+import java.util.Map;
+
+import com.sun.classanalyzer.Module.Reference;
+import java.util.LinkedList;
+import java.util.TreeMap;
+
+/**
+ *
+ * @author Mandy Chung
+ */
+public abstract class AnnotatedDependency implements Comparable<AnnotatedDependency> {
+
+    final Klass from;
+    final List<String> classes;
+    protected boolean optional;
+    String description;
+    Klass.Method method;
+    private List<Filter> filters = null;
+
+    public AnnotatedDependency(Klass klass) {
+        this(klass, false);
+    }
+
+    public AnnotatedDependency(Klass klass, boolean optional) {
+        this.from = klass;
+        this.classes = new ArrayList<String>();
+        this.optional = optional;
+    }
+
+    abstract String getTag();
+
+    abstract boolean isDynamic();
+
+    void setMethod(Klass.Method m) {
+        this.method = m;
+    }
+
+    void addElement(String element, List<String> value) {
+        if (element.equals("value")) {
+            addValue(value);
+        } else if (element.equals("description")) {
+            description = value.get(0);
+        } else if (element.equals("optional")) {
+            optional = value.get(0).equals("1") || Boolean.parseBoolean(value.get(0));
+        }
+    }
+
+    void addValue(List<String> value) {
+        for (String s : value) {
+            if ((s = s.trim()).length() > 0) {
+                classes.add(s);
+            }
+        }
+    }
+
+    List<String> getValue() {
+        return classes;
+    }
+
+    boolean isOptional() {
+        return optional;
+    }
+
+    boolean isEmpty() {
+        return classes.isEmpty();
+    }
+
+    boolean matches(String classname) {
+        synchronized (this) {
+            // initialize filters
+            if (filters == null) {
+                filters = new ArrayList<Filter>();
+                for (String pattern : classes) {
+                    filters.add(new Filter(pattern));
+                }
+
+            }
+        }
+
+        for (Filter f : filters) {
+            if (f.matches(classname)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder();
+        for (String v : getValue()) {
+            if (sb.length() == 0) {
+                sb.append(getTag());
+                sb.append("\n");
+            } else {
+                sb.append("\n");
+            }
+            sb.append("  ");
+            sb.append(from.getClassName()).append(" -> ");
+            sb.append(v);
+        }
+        return sb.toString();
+    }
+
+    @Override
+    public int compareTo(AnnotatedDependency o) {
+        if (from == o.from) {
+            if (this.getClass().getName().equals(o.getClass().getName())) {
+                String s1 = classes.isEmpty() ? "" : classes.get(0);
+                String s2 = o.classes.isEmpty() ? "" : o.classes.get(0);
+                return s1.compareTo(s2);
+            } else {
+                return this.getClass().getName().compareTo(o.getClass().getName());
+            }
+
+        } else {
+            return from.compareTo(o.from);
+        }
+    }
+
+    @Override
+    public int hashCode() {
+        int hashcode = 7 + 73 * from.hashCode();
+        for (String s : classes) {
+            hashcode ^= s.hashCode();
+        }
+        return hashcode;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (!(obj instanceof AnnotatedDependency)) {
+            return false;
+        }
+        AnnotatedDependency other = (AnnotatedDependency) obj;
+        boolean ret = this.from.equals(other.from) && this.classes.size() == other.classes.size();
+        if (ret == true) {
+            for (int i = 0; i < this.classes.size(); i++) {
+                ret = ret && this.classes.get(i).equals(other.classes.get(i));
+            }
+        }
+        return ret;
+    }
+
+    static class ClassForName extends AnnotatedDependency {
+
+        public ClassForName(Klass klass, boolean optional) {
+            super(klass, optional);
+        }
+
+        @Override
+        String getTag() {
+            if (this.optional) {
+                return TAG + "(optional)";
+            } else {
+                return TAG;
+            }
+        }
+
+        @Override
+        boolean isDynamic() {
+            return true;
+        }
+        static final String TYPE = "sun.annotation.ClassForName";
+        static final String TAG = "@ClassForName";
+    }
+
+    static class NativeFindClass extends AnnotatedDependency {
+
+        public NativeFindClass(Klass klass, boolean optional) {
+            super(klass, optional);
+        }
+
+        @Override
+        String getTag() {
+            if (this.optional) {
+                return TAG + "(optional)";
+            } else {
+                return TAG;
+            }
+        }
+
+        @Override
+        boolean isDynamic() {
+            return true;
+        }
+        static final String TYPE = "sun.annotation.NativeFindClass";
+        static final String TAG = "@NativeFindClass";
+    }
+
+    static class Provider extends AnnotatedDependency {
+
+        private List<String> services = new ArrayList<String>();
+
+        Provider(Klass klass) {
+            super(klass, true);
+        }
+
+        @Override
+        boolean isDynamic() {
+            return true;
+        }
+
+        public List<String> services() {
+            return services;
+        }
+
+        @Override
+        void addElement(String element, List<String> value) {
+            if (element.equals("service")) {
+                List<String> configFiles = new ArrayList<String>();
+                for (String s : value) {
+                    if ((s = s.trim()).length() > 0) {
+                        configFiles.add(metaInfPath + s);
+                    }
+                }
+                addValue(configFiles);
+            }
+        }
+
+        @Override
+        void addValue(List<String> value) {
+            for (String s : value) {
+                if ((s = s.trim()).length() > 0) {
+                    if (s.startsWith("META-INF")) {
+                        services.add(s);
+                        readServiceConfiguration(s, classes);
+                    } else {
+                        throw new RuntimeException("invalid value" + s);
+                    }
+                }
+            }
+        }
+
+        boolean isEmpty() {
+            return services.isEmpty();
+        }
+        static final String metaInfPath =
+                "META-INF" + File.separator + "services" + File.separator;
+
+        static void readServiceConfiguration(String config, List<String> names) {
+            BufferedReader br = null;
+            try {
+                InputStream is = ClassPath.open(config);
+                if (is != null) {
+                    // Properties doesn't perserve the order of the input file
+                    br = new BufferedReader(new InputStreamReader(is, "utf-8"));
+                    int lc = 1;
+                    while ((lc = parseLine(br, lc, names)) >= 0);
+                }
+            } catch (IOException ex) {
+                throw new RuntimeException(ex);
+            } finally {
+                if (br != null) {
+                    try {
+                        br.close();
+                    } catch (IOException ex) {
+                        throw new RuntimeException(ex);
+                    }
+                }
+            }
+        }
+
+        // Parse a single line from the given configuration file, adding the name
+        // on the line to the names list.
+        //
+        private static int parseLine(BufferedReader r, int lc, List<String> names) throws IOException {
+            String ln = r.readLine();
+            if (ln == null) {
+                return -1;
+            }
+            int ci = ln.indexOf('#');
+            if (ci >= 0) {
+                ln = ln.substring(0, ci);
+            }
+            ln = ln.trim();
+            int n = ln.length();
+            if (n != 0) {
+                if ((ln.indexOf(' ') >= 0) || (ln.indexOf('\t') >= 0)) {
+                    throw new RuntimeException("Illegal configuration-file syntax");
+                }
+                int cp = ln.codePointAt(0);
+                if (!Character.isJavaIdentifierStart(cp)) {
+                    throw new RuntimeException("Illegal provider-class name: " + ln);
+                }
+                for (int i = Character.charCount(cp); i < n; i += Character.charCount(cp)) {
+                    cp = ln.codePointAt(i);
+                    if (!Character.isJavaIdentifierPart(cp) && (cp != '.')) {
+                        throw new RuntimeException("Illegal provider-class name: " + ln);
+                    }
+                }
+                if (!names.contains(ln)) {
+                    names.add(ln);
+                }
+            }
+            return lc + 1;
+        }
+
+        @Override
+        String getTag() {
+            return TAG;
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (!(obj instanceof AnnotatedDependency)) {
+                return false;
+            }
+            Provider other = (Provider) obj;
+            boolean ret = this.from.equals(other.from) &&
+                    this.services.size() == other.services.size();
+            if (ret == true) {
+                for (int i = 0; i < this.services.size(); i++) {
+                    ret = ret && this.services.get(i).equals(other.services.get(i));
+                }
+            }
+            return ret;
+        }
+
+        @Override
+        public int hashCode() {
+            int hashcode = 7 + 73 * from.hashCode();
+            for (String s : services) {
+                hashcode ^= s.hashCode();
+            }
+            return hashcode;
+        }
+
+        @Override
+        public List<String> getValue() {
+            List<String> result = new ArrayList<String>();
+            result.addAll(services);
+            return result;
+        }
+        static final String TYPE = "sun.annotation.Provider";
+        static final String TAG = "@Provider";
+    }
+
+    static class OptionalDependency extends AnnotatedDependency {
+
+        static boolean isOptional(Klass from, Klass to) {
+            synchronized (OptionalDependency.class) {
+                if (optionalDepsMap == null) {
+                    // Build a map of classes to its optional dependencies
+                    initDependencies();
+                }
+            }
+            for (Reference ref : optionalDepsMap.keySet()) {
+                if (ref.referrer() == from && ref.referree() == to) {
+                    return true;
+                }
+            }
+            return false;
+        }
+
+        OptionalDependency(Klass klass) {
+            super(klass, true);
+        }
+
+        @Override
+        boolean isDynamic() {
+            return false;
+        }
+
+        @Override
+        String getTag() {
+            return TAG;
+        }
+        static final String TYPE = "sun.annotation.Optional";
+        static final String TAG = "@Optional";
+    }
+
+    static class CompilerInline extends AnnotatedDependency {
+
+        public CompilerInline(Klass klass) {
+            super(klass);
+        }
+
+        @Override
+        String getTag() {
+            return TAG;
+        }
+
+        @Override
+        boolean isDynamic() {
+            return false;
+        }
+        static final String TYPE = "sun.annotation.Inline";
+        static final String TAG = "@Inline";
+    }
+
+    static class Filter {
+
+        final String pattern;
+        final String regex;
+
+        Filter(String pattern) {
+            this.pattern = pattern;
+
+            boolean isRegex = false;
+            for (int i = 0; i < pattern.length(); i++) {
+                char p = pattern.charAt(i);
+                if (p == '*' || p == '[' || p == ']') {
+                    isRegex = true;
+                    break;
+                }
+            }
+
+            if (isRegex) {
+                this.regex = convertToRegex(pattern);
+            } else {
+                this.regex = null;
+            }
+        }
+
+        private String convertToRegex(String pattern) {
+            StringBuilder sb = new StringBuilder();
+            int i = 0;
+            int index = 0;
+            int plen = pattern.length();
+            while (i < plen) {
+                char p = pattern.charAt(i);
+                if (p == '*') {
+                    sb.append("(").append(pattern.substring(index, i)).append(")");
+                    if (i + 1 < plen && pattern.charAt(i + 1) == '*') {
+                        sb.append(".*");
+                        index = i + 2;
+                    } else {
+                        sb.append("[^\\.]*");
+                        index = i + 1;
+                    }
+                } else if (p == '[') {
+                    int j = i + 1;
+                    while (j < plen) {
+                        if (pattern.charAt(j) == ']') {
+                            break;
+                        }
+                        j++;
+                    }
+                    if (j >= plen || pattern.charAt(j) != ']') {
+                        throw new RuntimeException("Malformed pattern " + pattern);
+                    }
+                    sb.append("(").append(pattern.substring(index, i)).append(")");
+                    sb.append(pattern.substring(i, j + 1));
+                    index = j + 1;
+                    i = j;
+                }
+                i++;
+            }
+            if (index < plen) {
+                sb.append("(").append(pattern.substring(index, plen)).append(")");
+            }
+            return sb.toString();
+        }
+
+        boolean matches(String name) {
+            if (regex == null) {
+                // the pattern is not a regex
+                return name.equals(pattern);
+            } else {
+                return name.matches(regex);
+            }
+        }
+    }
+
+    static boolean isValidType(String type) {
+        if (type.endsWith("(optional)")) {
+            int len = type.length() - "(optional)".length();
+            type = type.substring(0, len);
+        }
+        return type.equals(ClassForName.TYPE) || type.equals(ClassForName.TAG) ||
+                type.equals(NativeFindClass.TYPE) || type.equals(NativeFindClass.TAG) ||
+                type.equals(Provider.TYPE) || type.equals(Provider.TAG) ||
+                type.equals(CompilerInline.TYPE) || type.equals(CompilerInline.TAG) ||
+                type.equals(OptionalDependency.TYPE) || type.equals(OptionalDependency.TAG);
+    }
+
+    static AnnotatedDependency newAnnotatedDependency(String tag, String value, Klass klass) {
+        AnnotatedDependency dep = newAnnotatedDependency(tag, klass);
+        if (dep != null) {
+            dep.addValue(Collections.singletonList(value));
+        }
+        return dep;
+    }
+    static List<AnnotatedDependency> annotatedDependencies = new LinkedList<AnnotatedDependency>();
+    static List<AnnotatedDependency> optionalDependencies = new LinkedList<AnnotatedDependency>();
+
+    static AnnotatedDependency newAnnotatedDependency(String type, Klass klass) {
+        boolean optional = false;
+        if (type.endsWith("(optional)")) {
+            optional = true;
+            int len = type.length() - "(optional)".length();
+            type = type.substring(0, len);
+        }
+
+        if (type.equals(OptionalDependency.TYPE) || type.equals(OptionalDependency.TAG)) {
+            return newOptionalDependency(klass);
+        }
+
+        AnnotatedDependency dep;
+        if (type.equals(ClassForName.TYPE) || type.equals(ClassForName.TAG)) {
+            dep = new ClassForName(klass, optional);
+        } else if (type.equals(NativeFindClass.TYPE) || type.equals(NativeFindClass.TAG)) {
+            dep = new NativeFindClass(klass, optional);
+        } else if (type.equals(Provider.TYPE) || type.equals(Provider.TAG)) {
+            dep = new Provider(klass);
+        } else if (type.equals(CompilerInline.TYPE) || type.equals(CompilerInline.TAG)) {
+            dep = new CompilerInline(klass);
+        } else {
+            return null;
+        }
+        klass.addAnnotatedDep(dep);
+        annotatedDependencies.add(dep);
+        return dep;
+    }
+
+    static OptionalDependency newOptionalDependency(Klass klass) {
+        OptionalDependency dep = new OptionalDependency(klass);
+        optionalDependencies.add(dep);
+        return dep;
+    }
+    static Map<Reference, Set<AnnotatedDependency>> annotatedDepsMap = null;
+    static Map<Reference, Set<AnnotatedDependency>> optionalDepsMap = null;
+
+    static Map<Reference, Set<AnnotatedDependency>> getReferences(Module m) {
+        // ensure it's initialized
+        initDependencies();
+
+        Map<Reference, Set<AnnotatedDependency>> result = new TreeMap<Reference, Set<AnnotatedDependency>>();
+        for (Reference ref : annotatedDepsMap.keySet()) {
+            if (m.contains(ref.referrer()) && m.isModuleDependence(ref.referree())) {
+                result.put(ref, annotatedDepsMap.get(ref));
+            }
+        }
+        return result;
+    }
+
+    static Set<Module.Dependency> getDependencies(Module m) {
+        // ensure it's initialized
+        initDependencies();
+
+        Set<Module.Dependency> deps = new TreeSet<Module.Dependency>();
+        for (Reference ref : annotatedDepsMap.keySet()) {
+            if (m.contains(ref.referrer())) {
+                Module other = m.getModuleDependence(ref.referree());
+                if (other != null) {
+                    for (AnnotatedDependency ad : annotatedDepsMap.get(ref)) {
+                        Module.Dependency d = new Module.Dependency(other, ad.isOptional(), ad.isDynamic());
+                        deps.add(d);
+                    }
+                }
+            }
+        }
+        return deps;
+    }
+
+    synchronized static void initDependencies() {
+        if (annotatedDepsMap != null) {
+            return;
+        }
+
+        // Build a map of references to its dependencies
+        annotatedDepsMap = new TreeMap<Reference, Set<AnnotatedDependency>>();
+        optionalDepsMap = new TreeMap<Reference, Set<AnnotatedDependency>>();
+
+        for (Klass k : Klass.getAllClasses()) {
+            for (AnnotatedDependency ad : annotatedDependencies) {
+                if (ad.matches(k.getClassName())) {
+                    Reference ref = new Reference(ad.from, k);
+                    Set<AnnotatedDependency> set = annotatedDepsMap.get(ref);
+                    if (set == null) {
+                        set = new TreeSet<AnnotatedDependency>();
+                        annotatedDepsMap.put(ref, set);
+                    }
+                    set.add(ad);
+                }
+            }
+
+            for (AnnotatedDependency ad : optionalDependencies) {
+                if (ad.matches(k.getClassName())) {
+                    Reference ref = new Reference(ad.from, k);
+                    Set<AnnotatedDependency> set = optionalDepsMap.get(ref);
+                    if (set == null) {
+                        set = new TreeSet<AnnotatedDependency>();
+                        optionalDepsMap.put(ref, set);
+                    }
+                    set.add(ad);
+                }
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/make/modules/tools/src/com/sun/classanalyzer/AnnotationParser.java	Wed Jul 05 17:04:56 2017 +0200
@@ -0,0 +1,293 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+package com.sun.classanalyzer;
+
+import com.sun.tools.classfile.*;
+import com.sun.tools.classfile.Annotation;
+import com.sun.tools.classfile.ExtendedAnnotation;
+import com.sun.tools.classfile.Annotation.Annotation_element_value;
+import com.sun.tools.classfile.Annotation.Array_element_value;
+import com.sun.tools.classfile.Annotation.Class_element_value;
+import com.sun.tools.classfile.Annotation.Enum_element_value;
+import com.sun.tools.classfile.Annotation.Primitive_element_value;
+import com.sun.tools.classfile.ConstantPoolException;
+import com.sun.tools.classfile.Descriptor;
+import com.sun.tools.classfile.Descriptor.InvalidDescriptor;
+import java.util.ArrayList;
+import java.util.List;
+
+import com.sun.classanalyzer.AnnotatedDependency.*;
+import java.io.File;
+import java.io.PrintWriter;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ *
+ * @author Mandy Chung
+ */
+public class AnnotationParser {
+
+    static boolean parseAnnotation = false;
+    static void setParseAnnotation(boolean newValue) {
+        parseAnnotation = newValue;
+    }
+
+    private final ClassFileParser cfparser;
+    public AnnotationParser(ClassFileParser cfparser) {
+        this.cfparser = cfparser;
+    }
+
+    private AnnotatedDependency addAnnotation(Annotation annot, Klass.Method method) {
+        String type = getType(annot.type_index);
+        AnnotatedDependency dep = AnnotatedDependency.newAnnotatedDependency(type, cfparser.this_klass);
+        if (dep != null) {
+            for (int i = 0; i < annot.num_element_value_pairs; i++) {
+                Element element = getElement(annot.element_value_pairs[i]);
+                dep.addElement(element.name, element.value);
+            }
+            dep.setMethod(method);
+        }
+        return dep;
+    }
+
+    private AnnotatedDependency addAnnotation(ExtendedAnnotation annot, Klass.Method method) {
+        return addAnnotation(annot.annotation, method);
+    }
+
+    class Element {
+
+        String name;
+        List<String> value;
+
+        Element(String name) {
+            this.name = name;
+            this.value = new ArrayList<String>();
+        }
+
+        void add(String v) {
+            value.add(v);
+        }
+    }
+
+    Element getElement(Annotation.element_value_pair pair) {
+        Element element = new Element(getName(pair.element_name_index));
+        evp.parse(pair.value, element);
+        return element;
+    }
+
+    private String getType(int index) {
+        try {
+            Descriptor d = new Descriptor(index);
+            return d.getFieldType(cfparser.classfile.constant_pool);
+        } catch (ConstantPoolException ignore) {
+        } catch (InvalidDescriptor ignore) {
+        }
+        return "Unknown";
+    }
+
+    private String getName(int index) {
+        return cfparser.constantPoolParser.stringValue(index);
+    }
+    element_value_Parser evp = new element_value_Parser();
+
+    class element_value_Parser implements Annotation.element_value.Visitor<Void, Element> {
+
+        public Void parse(Annotation.element_value value, Element element) {
+            value.accept(this, element);
+            return null;
+        }
+
+        public Void visitPrimitive(Primitive_element_value ev, Element element) {
+            String value = getName(ev.const_value_index);
+            element.add(value);
+            return null;
+        }
+
+        public Void visitEnum(Enum_element_value ev, Element element) {
+            String value = getName(ev.type_name_index) + "." + getName(ev.const_name_index);
+            element.add(value);
+            return null;
+        }
+
+        public Void visitClass(Class_element_value ev, Element element) {
+            String value = getName(ev.class_info_index) + ".class";
+            element.add(value);
+            return null;
+        }
+
+        public Void visitAnnotation(Annotation_element_value ev, Element element) {
+            // AnnotationParser.this.addAnnotation(ev.annotation_value);
+            throw new UnsupportedOperationException("Not supported: " + ev);
+        }
+
+        public Void visitArray(Array_element_value ev, Element element) {
+            for (int i = 0; i < ev.num_values; i++) {
+                parse(ev.values[i], element);
+            }
+            return null;
+        }
+    }
+
+    void parseAttributes(Attributes attributes, Klass.Method method) {
+        if (!parseAnnotation) {
+            return;
+        }
+
+        visitRuntimeAnnotations((RuntimeVisibleAnnotations_attribute) attributes.get(Attribute.RuntimeVisibleAnnotations), method);
+        visitRuntimeAnnotations((RuntimeInvisibleAnnotations_attribute) attributes.get(Attribute.RuntimeInvisibleAnnotations), method);
+        visitRuntimeTypeAnnotations((RuntimeVisibleTypeAnnotations_attribute) attributes.get(Attribute.RuntimeVisibleTypeAnnotations), method);
+        visitRuntimeTypeAnnotations((RuntimeInvisibleTypeAnnotations_attribute) attributes.get(Attribute.RuntimeInvisibleTypeAnnotations), method);
+        visitRuntimeParameterAnnotations((RuntimeVisibleParameterAnnotations_attribute) attributes.get(Attribute.RuntimeVisibleParameterAnnotations), method);
+        visitRuntimeParameterAnnotations((RuntimeInvisibleParameterAnnotations_attribute) attributes.get(Attribute.RuntimeInvisibleParameterAnnotations), method);
+    }
+
+    public void visitRuntimeAnnotations(RuntimeAnnotations_attribute attr, Klass.Method method) {
+        if (attr == null) {
+            return;
+        }
+
+        for (int i = 0; i < attr.annotations.length; i++) {
+            addAnnotation(attr.annotations[i], method);
+        }
+    }
+
+    public void visitRuntimeTypeAnnotations(RuntimeTypeAnnotations_attribute attr, Klass.Method method) {
+        if (attr == null) {
+            return;
+        }
+
+        for (int i = 0; i < attr.annotations.length; i++) {
+            addAnnotation(attr.annotations[i], method);
+        }
+    }
+
+    public void visitRuntimeParameterAnnotations(RuntimeParameterAnnotations_attribute attr, Klass.Method method) {
+        if (attr == null) {
+            return;
+        }
+
+        for (int param = 0; param < attr.parameter_annotations.length; param++) {
+            for (int i = 0; i < attr.parameter_annotations[param].length; i++) {
+                addAnnotation(attr.parameter_annotations[param][i], method);
+            }
+        }
+    }
+
+    void parseAttributes(Attributes attributes) {
+        parseAttributes(attributes, null);
+    }
+
+    public static void main(String[] args) throws Exception {
+        String jdkhome = null;
+        String output = ".";
+
+        // process arguments
+        int i = 0;
+        while (i < args.length) {
+            String arg = args[i++];
+            if (arg.equals("-jdkhome")) {
+                if (i < args.length) {
+                    jdkhome = args[i++];
+                } else {
+                    usage();
+                }
+            } else if (arg.equals("-output")) {
+                output = args[i++];
+            } else {
+                usage();
+            }
+        }
+        if (jdkhome == null) {
+            usage();
+        }
+
+        // parse annotation and code attribute to find all references
+        // to Class.forName etc
+        CodeAttributeParser.setParseCodeAttribute(true);
+        AnnotationParser.setParseAnnotation(true);
+
+        ClassPath.setJDKHome(jdkhome);
+        ClassPath.parseAllClassFiles();
+
+        PrintWriter writer = new PrintWriter(new File(output, "jdk7.depconfig"));
+
+        try {
+            for (Klass k : Klass.getAllClasses()) {
+                for (AnnotatedDependency dep : k.getAnnotatedDeps()) {
+                    if (dep.isEmpty()) {
+                        continue;
+                    }
+                    writer.format("# %s \n", dep.method == null ? dep.from : dep.method);
+                    writer.format("%s\n\n", dep);
+                }
+            }
+        } finally {
+            writer.close();
+        }
+
+        writer = new PrintWriter(new File(output, "optional.depconfig"));
+        try {
+            AnnotatedDependency prev = null;
+            for (AnnotatedDependency dep : AnnotatedDependency.optionalDependencies) {
+                if (prev != null && !dep.equals(prev)) {
+                    writer.format("%s\n\n", prev);
+                }
+                writer.format("# %s \n", dep.method == null ? dep.from : dep.method);
+                prev = dep;
+            }
+            if (prev != null) {
+                writer.format("%s\n\n", prev);
+            }
+        } finally {
+            writer.close();
+        }
+
+        writer = new PrintWriter(new File(output, "runtime.references"));
+        try {
+            for (Map.Entry<String, Set<Klass.Method>> entry : CodeAttributeParser.runtimeReferences.entrySet()) {
+                writer.format("References to %s\n", entry.getKey());
+                Klass prev = null;
+                for (Klass.Method m : entry.getValue()) {
+                    if (prev == null || prev != m.getKlass()) {
+                        writer.format("  %-50s # %s\n", m.getKlass(), m);
+                    } else if (prev == m.getKlass()) {
+                        writer.format("  %-50s # %s\n", "", m);
+                    }
+                    prev = m.getKlass();
+                }
+            }
+        } finally {
+            writer.close();
+        }
+    }
+
+    private static void usage() {
+        System.out.println("Usage: AnnotationParser <options>");
+        System.out.println("Options: ");
+        System.out.println("\t-jdkhome <JDK home> where all jars will be parsed");
+        System.out.println("\t-depconfig <output file for annotated dependencies>");
+        System.out.println("\t-optional <output file for optional dependencies>");
+        System.exit(-1);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/make/modules/tools/src/com/sun/classanalyzer/BootAnalyzer.java	Wed Jul 05 17:04:56 2017 +0200
@@ -0,0 +1,819 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ *
+ */
+package com.sun.classanalyzer;
+
+import java.io.BufferedReader;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.PrintWriter;
+import java.io.File;
+import java.util.ArrayDeque;
+import java.util.Deque;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeSet;
+
+import com.sun.tools.classfile.*;
+import com.sun.tools.classfile.ConstantPool.*;
+import static com.sun.tools.classfile.ConstantPool.*;
+import com.sun.tools.classfile.Instruction.TypeKind;
+import com.sun.tools.classfile.Type.*;
+
+/**
+ * Generate the module config for the boot module with
+ * a given set of roots (classes or methods) and exclude list.
+ *
+ * This tool does method-level dependency analysis starting
+ * from the root set and follows references transitively as follows:
+ * <ul>
+ * <li>For a given class, it will parse the ClassFile to
+ *     find its superclass and superinterfaces and also
+ *     its static initializer &lt;clinit&gt;.</li>
+ * <li>For each method, it will parse its Code attribute
+ *     to look for a Methodref, Fieldref, and InterfaceMethodref.
+ *     </li>
+ * <li>For each Fieldref, it will include the type of
+ *     the field in the dependency.</li>
+ * <li>For each MethodRef, it will follow all references in
+ *     that method.</li>
+ * <li>For each InterfaceMethodref, it will follow all references in
+ *     that method defined its implementation classes in
+ *     the resulting dependency list.</li>
+ * </ul>
+ *
+ * Limitation:
+ * <ul>
+ * <li>For each Methodref, it only parses the method of
+ *     the specified type.  It doesn't analyze the class hierarchy
+ *     and follow references of its subclasses since it ends up
+ *     pulls in many unnecessary dependencies.  For now,
+ *     the list of subclasses and methods need to be listed in
+ *     the root set.</li>
+ * </ul>
+ *
+ * @author Mandy Chung
+ */
+public class BootAnalyzer {
+
+    public static void main(String[] args) throws Exception {
+        String jdkhome = null;
+        String config = null;
+        String output = ".";
+        boolean printClassList = false;
+
+        // process arguments
+        int i = 0;
+        while (i < args.length) {
+            String arg = args[i++];
+            if (arg.equals("-jdkhome")) {
+                if (i < args.length) {
+                    jdkhome = args[i++];
+                } else {
+                    usage();
+                }
+            } else if (arg.equals("-config")) {
+                config = args[i++];
+            } else if (arg.equals("-output")) {
+                output = args[i++];
+            } else if (arg.equals("-classlist")) {
+                printClassList = true;
+            } else {
+                usage();
+            }
+        }
+
+
+
+        if (jdkhome == null || config == null) {
+            usage();
+        }
+
+        File jre = new File(jdkhome, "jre");
+        if (jre.exists()) {
+            ClassPath.setJDKHome(jdkhome);
+        } else {
+            File classes = new File(jdkhome, "classes");
+            if (classes.exists()) {
+                ClassPath.setClassPath(classes.getCanonicalPath());
+            } else {
+                throw new RuntimeException("Invalid jdkhome: " + jdkhome);
+            }
+        }
+
+        parseConfigFile(config);
+        followRoots();
+
+        // create output directory if it doesn't exist
+        File dir = new File(output);
+        if (!dir.isDirectory()) {
+            if (!dir.exists()) {
+                boolean created = dir.mkdir();
+                if (!created) {
+                    throw new RuntimeException("Unable to create `" + dir + "'");
+                }
+            }
+        }
+
+        String bootmodule = "boot";
+        String bootconfig = resolve(dir, bootmodule, "config");
+        printBootConfig(bootconfig, bootmodule);
+
+        List<ModuleConfig> list = ModuleConfig.readConfigurationFile(bootconfig);
+        Module module = Module.addModule(list.get(0));
+        for (Klass k : Klass.getAllClasses()) {
+            module.addKlass(k);
+        }
+        module.fixupDependencies();
+
+        if (printClassList) {
+            module.printClassListTo(resolve(dir, bootmodule, "classlist"));
+            module.printSummaryTo(resolve(dir, bootmodule, "summary"));
+        }
+    }
+
+    // print boot.config file as an input to the ClassAnalyzer
+    private static void printBootConfig(String output, String bootmodule) throws IOException {
+
+        File f = new File(output);
+        PrintWriter writer = new PrintWriter(f);
+        try {
+            int count = 0;
+            writer.format("module %s {%n", bootmodule);
+            for (Klass k : Klass.getAllClasses()) {
+                if (count++ == 0) {
+                    writer.format("%4s%7s %s", "", "include", k);
+                } else {
+                    writer.format(",%n");
+                    writer.format("%4s%7s %s", "", "", k);
+                }
+            }
+            writer.format(";%n}%n");
+        } finally {
+            writer.close();
+        }
+    }
+
+    private static String resolve(File dir, String mname, String suffix) {
+        File f = new File(dir, mname + "." + suffix);
+        return f.toString();
+
+    }
+    static List<MethodDescriptor> methods = new LinkedList<MethodDescriptor>();
+    static Deque<MethodDescriptor> pending = new ArrayDeque<MethodDescriptor>();
+    static Deque<MethodDescriptor> interfaceMethodRefs = new ArrayDeque<MethodDescriptor>();
+    static Filter filter = new Filter();
+
+    private static void followRoots() throws IOException {
+        MethodDescriptor md = null;
+
+        while ((md = pending.poll()) != null) {
+            if (!methods.contains(md)) {
+                methods.add(md);
+                if (md.classname.isEmpty()) {
+                    trace("Warning: class missing %s%n", md);
+                    continue;
+                }
+
+                if (filter.isExcluded(md.classname)) {
+                    trace("excluded %s%n", md);
+                } else {
+                    KlassInfo kinfo = getKlassInfo(md.classname);
+                    if (kinfo.classname.contains("$")) {
+                        int pos = kinfo.classname.lastIndexOf('$');
+                        String outer = kinfo.classname.substring(0, pos);
+                        if (!cache.containsKey(outer)) {
+                            trace("  include outer class %s%n", outer);
+                            getKlassInfo(outer).ensureParse();
+                        }
+                    }
+
+                    kinfo.ensureParse();
+                    if (md.methodname.length() > 0) {
+                        if (filter.isExcluded(md.name)) {
+                            trace("excluded %s%n", md);
+                        } else {
+                            if (md.interfaceMethodRef) {
+                                trace("interface methodref %s%n", md);
+                                interfaceMethodRefs.add(md);
+                            } else {
+                                List<String> descriptors = kinfo.parse(md);
+                                if (descriptors.isEmpty()) {
+                                    if (kinfo.getSuperclass() != null) {
+                                        String sn = kinfo.getSuperclass().classname;
+                                        MethodDescriptor superMD = new MethodDescriptor(sn + "." + md.methodname, md.descriptor, false);
+                                        if (!methods.contains(superMD) && !pending.contains(superMD)) {
+                                            trace("  delegated %s to %s%n", md, superMD);
+                                            pending.add(superMD);
+                                        }
+                                    } else if (kinfo.isClass()) {
+                                        trace("  %s (not found)%n", md);
+                                    } else {
+                                        trace("  %s (interface)%n", md);
+                                    }
+                                } else {
+                                    if (md.descriptor.equals("*")) {
+                                        trace("  parsed %s : ", md.name);
+                                        for (String s : descriptors) {
+                                            trace(" %s", s);
+                                        }
+                                        trace("%n");
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+            if (pending.isEmpty()) {
+                for (Klass k : Klass.getAllClasses()) {
+                    if (k.getFileSize() == 0) {
+                        getKlassInfo(k.getClassName()).ensureParse();
+                    }
+                }
+                while ((md = interfaceMethodRefs.poll()) != null) {
+                    addSubClassMethods(md);
+                }
+            }
+        }
+    }
+
+    static void addSubClassMethods(MethodDescriptor md) throws IOException {
+        for (KlassInfo kinfo : getSubClasses(md.classname)) {
+            String methodname = kinfo.classname + "." + md.methodname;
+            MethodDescriptor other = new MethodDescriptor(methodname, md.descriptor, false);
+            if (!methods.contains(other) && !pending.contains(other)) {
+                trace("Warning: subclass from %s to %s%n", md.classname, other);
+                pending.add(other);
+            }
+        }
+    }
+    private final static String privilegedActionInterf = "java.security.PrivilegedAction";
+    private final static String privilegedExceptionActionInterf = "java.security.PrivilegedExceptionAction";
+
+    static boolean isPrivilegedAction(String classname) {
+        if (classname.isEmpty()) {
+            return false;
+        }
+        KlassInfo kinfo = getKlassInfo(classname);
+        for (KlassInfo ki : kinfo.getInterfaces()) {
+            String interf = ki.classname;
+            if (interf.equals(privilegedActionInterf) ||
+                    interf.equals(privilegedExceptionActionInterf)) {
+                return true;
+            }
+        }
+        return false;
+    }
+    static Map<String, KlassInfo> cache = new HashMap<String, KlassInfo>();
+
+    static KlassInfo getKlassInfo(String classname) {
+        classname = classname.replace('/', '.');
+
+        KlassInfo kinfo = cache.get(classname);
+        if (kinfo == null) {
+            kinfo = new KlassInfo(classname);
+            cache.put(classname, kinfo);
+        }
+        return kinfo;
+    }
+
+    static class KlassInfo {
+
+        final String classname;
+        private ClassFileParser parser;
+        private KlassInfo superclass;
+        private List<KlassInfo> interfaces = new LinkedList<KlassInfo>();
+
+        KlassInfo(String classname) {
+            this.classname = classname;
+        }
+
+        boolean isClass() {
+            ensureParse();
+            return parser.classfile.isClass();
+        }
+
+        KlassInfo getSuperclass() {
+            ensureParse();
+            return superclass;
+        }
+
+        List<KlassInfo> getInterfaces() {
+            ensureParse();
+            return java.util.Collections.unmodifiableList(interfaces);
+        }
+
+        void ensureParse() {
+            try {
+                getClassFileParser();
+            } catch (IOException e) {
+                throw new RuntimeException(e);
+            }
+        }
+
+        synchronized ClassFileParser getClassFileParser() throws IOException {
+            if (parser == null) {
+                parser = ClassPath.parserForClass(classname);
+                if (parser != null) {
+                    parseClassFile();
+                    List<String> descriptors = parse(new MethodDescriptor(classname + ".<clinit>", "()V", false));
+                }
+            }
+            return parser;
+        }
+
+        List<String> parse(MethodDescriptor md) {
+            ensureParse();
+            try {
+                List<String> descriptors = new LinkedList<String>();
+                for (Method m : parser.classfile.methods) {
+                    String name = m.getName(parser.classfile.constant_pool);
+                    String desc = parser.constantPoolParser.getDescriptor(m.descriptor.index);
+                    if (name.equals(md.methodname)) {
+                        if (md.descriptor.equals("*") || md.descriptor.equals(desc)) {
+                            parseMethod(parser, m);
+                            descriptors.add(desc);
+                        }
+                    }
+                }
+                return descriptors;
+            } catch (ConstantPoolException ex) {
+                throw new RuntimeException(ex);
+            }
+        }
+
+        private void parseClassFile() throws IOException {
+            parser.parseClassInfo();
+
+            ClassFile classfile = parser.classfile;
+            try {
+                if (classfile.super_class > 0) {
+                    superclass = getKlassInfo(classfile.getSuperclassName());
+                }
+                if (classfile.interfaces != null) {
+                    for (int i = 0; i < classfile.interfaces.length; i++) {
+                        interfaces.add(getKlassInfo(classfile.getInterfaceName(i)));
+                    }
+                }
+            } catch (ConstantPoolException ex) {
+                throw new RuntimeException(ex);
+            }
+        }
+    }
+
+    static List<KlassInfo> getSubClasses(String classname) throws IOException {
+        List<KlassInfo> result = new LinkedList<KlassInfo>();
+        List<KlassInfo> list = new LinkedList<KlassInfo>();
+        list.addAll(cache.values());
+        for (KlassInfo kinfo : list) {
+            if (kinfo.getSuperclass() != null && classname.equals(kinfo.getSuperclass().classname)) {
+                result.add(kinfo);
+            }
+            for (KlassInfo interf : kinfo.getInterfaces()) {
+                if (classname.equals(interf.classname)) {
+                    result.add(kinfo);
+                }
+            }
+        }
+        return result;
+    }
+
+    private static void parseConfigFile(String config) throws IOException {
+        FileInputStream in = new FileInputStream(config);
+        try {
+            BufferedReader reader = new BufferedReader(new InputStreamReader(in));
+            String line;
+            int lineNumber = 0;
+            while ((line = reader.readLine()) != null) {
+                lineNumber++;
+                if ((line = line.trim()).length() > 0) {
+                    if (line.startsWith("#")) {
+                        continue;
+                    }
+
+                    String[] s = line.split("\\s+");
+                    if ("exclude".equals(s[0])) {
+                        filter.exclude(s[1]);
+                    } else {
+                        String name = s[0].replace('/', '.');
+                        if (name.length() > 0) {
+                            String classname = name.replace('/', '.');
+                            if (s.length == 2) {
+                                // method name
+                                int pos = classname.lastIndexOf('.');
+                                classname = classname.substring(0, pos);
+                            }
+
+                            KlassInfo kinfo = getKlassInfo(classname);
+                            if (kinfo.getClassFileParser() != null) {
+                                // class exists
+                                MethodDescriptor md = (s.length == 1) ? new MethodDescriptor(name) : new MethodDescriptor(name, s[1], false);
+                                if (!pending.contains(md)) {
+                                    pending.add(md);
+                                }
+                            } else {
+                                // class not found
+                                trace("Class %s not found%n", classname);
+                            }
+                        }
+                    }
+                }
+            }
+
+        } finally {
+            in.close();
+        }
+    }
+
+    private static void parseMethod(ClassFileParser cfparser, Method m) {
+        Klass.Method kmethod = cfparser.parseMethod(m);
+        Code_attribute c_attr = (Code_attribute) m.attributes.get(Attribute.Code);
+        if (c_attr != null) {
+            LineNumberTable_attribute lineNumTable =
+                    (LineNumberTable_attribute) c_attr.attributes.get(Attribute.LineNumberTable);
+            InstructorVisitor visitor = new InstructorVisitor(cfparser, lineNumTable);
+            trace("parseMethod %s %s %n", cfparser.this_klass, kmethod);
+            for (Instruction instr : c_attr.getInstructions()) {
+                try {
+                    instr.accept(visitor, kmethod);
+                } catch (ArrayIndexOutOfBoundsException e) {
+                    throw new RuntimeException("error at or after byte " + instr.getPC());
+                }
+
+            }
+
+            if (c_attr.exception_table_langth > 0) {
+                for (int i = 0; i <
+                        c_attr.exception_table.length; i++) {
+                    Code_attribute.Exception_data handler = c_attr.exception_table[i];
+                    int catch_type = handler.catch_type;
+                    if (catch_type > 0) {
+                        visitor.addConstantPoolRef(catch_type, kmethod, handler.start_pc);
+                    }
+
+                }
+            }
+        }
+    }
+
+    static class MethodDescriptor {
+
+        final String name;
+        final String classname;
+        final String methodname;
+        final String descriptor;
+        final boolean interfaceMethodRef;
+
+        MethodDescriptor(String classname) {
+            this.classname = classname.replace('/', '.');
+            this.name = this.classname;
+            this.methodname = "";
+            this.descriptor = "";
+            this.interfaceMethodRef = false;
+            if (this.classname.length() == 1) {
+                throw new RuntimeException("invalid " + this);
+            }
+        }
+
+        MethodDescriptor(String name, String descriptor, boolean interfaceMethodRef) {
+            name = name.replace('/', '.');
+            this.name = name;
+            int pos = name.lastIndexOf('.');
+            this.classname = name.substring(0, pos);
+            this.methodname = name.substring(pos + 1, name.length());
+            this.descriptor = descriptor;
+            this.interfaceMethodRef = interfaceMethodRef;
+            if (this.classname.length() == 1) {
+                throw new RuntimeException("invalid " + this);
+            }
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            MethodDescriptor m = (MethodDescriptor) obj;
+
+            return this.name.equals(m.name) &&
+                    this.descriptor.equals(m.descriptor);
+        }
+
+        @Override
+        public int hashCode() {
+            int hash = 7;
+            hash = 97 * hash + (this.name != null ? this.name.hashCode() : 0);
+            hash = 97 * hash + (this.descriptor != null ? this.descriptor.hashCode() : 0);
+            return hash;
+        }
+
+        public String toString() {
+            if (descriptor.isEmpty()) {
+                return name;
+            } else {
+                return name + " : " + descriptor;
+            }
+        }
+    }
+
+    static class Filter {
+
+        private Set<String> excludes = new TreeSet<String>();
+
+        Filter exclude(String pattern) {
+            excludes.add(pattern);
+            return this;
+        }
+
+        boolean isExcluded(String klass) {
+            for (String pattern : excludes) {
+                if (matches(klass, pattern)) {
+                    return true;
+                }
+            }
+            return false;
+        }
+
+        private boolean matches(String klass, String pattern) {
+            int pos = klass.lastIndexOf('.');
+            String packageName = pos > 0 ? klass.substring(0, pos) : "<unnamed>";
+            if (pattern.endsWith("**")) {
+                String p = pattern.substring(0, pattern.length() - 2);
+                return klass.startsWith(p);
+            } else if (pattern.endsWith("*")) {
+                pos = pattern.lastIndexOf('.');
+                String pkg = pos > 0 ? pattern.substring(0, pos) : "<unnamed>";
+                if (packageName.equals(pkg)) {
+                    // package name has to be exact match
+                    String p = pattern.substring(0, pattern.length() - 1);
+                    return klass.startsWith(p);
+                } else {
+                    return false;
+                }
+            } else {
+                // exact match or inner class
+                return klass.equals(pattern) || klass.startsWith(pattern + "$");
+            }
+        }
+    }
+
+    static class InstructorVisitor implements Instruction.KindVisitor<Void, Klass.Method> {
+
+        private final ClassFileParser parser;
+        private final LineNumberTable_attribute lineNumTable;
+
+        InstructorVisitor(ClassFileParser parser, LineNumberTable_attribute lineNumTable) {
+            this.parser = parser;
+            this.lineNumTable = lineNumTable;
+        }
+
+        int getLineNumber(int pc) {
+            if (lineNumTable != null) {
+                int start_pc = 0;
+                int lineno = 0;
+                for (int i = 0; i < lineNumTable.line_number_table_length; i++) {
+                    int cur_start_pc = lineNumTable.line_number_table[i].start_pc;
+                    if (pc == 0 && cur_start_pc == 0) {
+                        return lineNumTable.line_number_table[i].line_number;
+                    } else if (pc >= start_pc && pc < cur_start_pc) {
+                        return lineno;
+                    }
+                    start_pc = cur_start_pc;
+                    lineno = lineNumTable.line_number_table[i].line_number;
+                }
+            }
+            return 0;
+        }
+
+        void addConstantPoolRef(int index, Klass.Method m, int pc) {
+            try {
+                CPInfo cpInfo = parser.classfile.constant_pool.get(index);
+                String name = cpInfo.accept(typeFinder, null);
+                if (name != null) {
+                    trace("   %s %s at line %d%n", parser.constantPoolParser.tagName(index), name, getLineNumber(pc));
+                }
+            } catch (InvalidIndex ex) {
+                throw new RuntimeException(ex);
+            }
+        }
+
+        public Void visitNoOperands(Instruction instr, Klass.Method m) {
+            return null;
+        }
+
+        public Void visitArrayType(Instruction instr, TypeKind kind, Klass.Method m) {
+            return null;
+        }
+
+        public Void visitBranch(Instruction instr, int offset, Klass.Method m) {
+            return null;
+        }
+
+        public Void visitConstantPoolRef(Instruction instr, int index, Klass.Method m) {
+            addConstantPoolRef(index, m, instr.getPC());
+            return null;
+        }
+
+        public Void visitConstantPoolRefAndValue(Instruction instr, int index, int value, Klass.Method m) {
+            addConstantPoolRef(index, m, instr.getPC());
+            return null;
+        }
+
+        public Void visitLocal(Instruction instr, int index, Klass.Method m) {
+            return null;
+        }
+
+        public Void visitLocalAndValue(Instruction instr, int index, int value, Klass.Method m) {
+            return null;
+        }
+
+        public Void visitLookupSwitch(Instruction instr, int default_, int npairs, int[] matches, int[] offsets, Klass.Method m) {
+            return null;
+        }
+
+        public Void visitTableSwitch(Instruction instr, int default_, int low, int high, int[] offsets, Klass.Method m) {
+            return null;
+        }
+
+        public Void visitValue(Instruction instr, int value, Klass.Method m) {
+            return null;
+        }
+
+        public Void visitUnknown(Instruction instr, Klass.Method m) {
+            return null;
+        }
+        private ConstantPool.Visitor<String, Void> typeFinder = new ConstantPool.Visitor<String, Void>() {
+
+            String getClassName(CPRefInfo info, Void p) {
+                try {
+                    return parser.checkClassName(info.getClassName()).replace('/', '.');
+                } catch (ConstantPoolException ex) {
+                    throw new RuntimeException(ex);
+                }
+            }
+
+            boolean addReferencedClass(String name) {
+                if (Klass.findKlass(name) == null) {
+                    MethodDescriptor md = new MethodDescriptor(name);
+                    if (!methods.contains(md) && !pending.contains(md)) {
+                        pending.add(md);
+                    }
+                    return true;
+                }
+                return false;
+            }
+            private String privilegedActionClass = "";
+
+            void cachePrivilegedAction(String classname) {
+                trace("   found PrivilegedAction %s%n", classname);
+                privilegedActionClass = classname;
+            }
+
+            void doPrivilegedCall(String method) {
+                if (privilegedActionClass.length() > 0) {
+                    MethodDescriptor md = new MethodDescriptor(privilegedActionClass + ".run", "*", false);
+                    if (!methods.contains(md) && !pending.contains(md)) {
+                        trace("   doPrivileged %s%n", md);
+                        pending.add(md);
+                    }
+                }
+            }
+
+            private String addMethodDescriptor(CPRefInfo info, Void p) {
+                try {
+                    String classname = getClassName(info, null);
+                    String method = classname + "." + info.getNameAndTypeInfo().getName();
+                    String descriptor = info.getNameAndTypeInfo().getType();
+
+                    if (method.endsWith(".<init>") && isPrivilegedAction(classname)) {
+                        cachePrivilegedAction(classname);
+                    }
+                    if (method.equals("java.security.AccessController.doPrivileged")) {
+                        doPrivilegedCall(method);
+                        return method;
+                    }
+
+                    boolean interfaceMethodRef = info instanceof CONSTANT_InterfaceMethodref_info;
+                    MethodDescriptor md = new MethodDescriptor(method, descriptor, interfaceMethodRef);
+                    if (!methods.contains(md) && !pending.contains(md)) {
+                        pending.add(md);
+                    }
+                    return method;
+                } catch (ConstantPoolException e) {
+                    throw new RuntimeException(e);
+                }
+            }
+
+            public String visitClass(CONSTANT_Class_info info, Void p) {
+                try {
+                    String classname = parser.checkClassName(info.getName()).replace('/', '.');
+                    if (classname.length() > 0) {
+                        addReferencedClass(classname);
+                    }
+                    return classname;
+                } catch (ConstantPoolException ex) {
+                    throw new RuntimeException(ex);
+                }
+            }
+
+            public String visitDouble(CONSTANT_Double_info info, Void p) {
+                // skip
+                return null;
+            }
+
+            public String visitFieldref(CONSTANT_Fieldref_info info, Void p) {
+                try {
+                    String classname = getClassName(info, p);
+                    if (classname.length() > 0) {
+                        addReferencedClass(classname);
+                    }
+
+                    String type = info.getNameAndTypeInfo().getType();
+                    String fieldType = parser.checkClassName(type).replace('/', '.');
+                    if (fieldType.length() > 0) {
+                        addReferencedClass(classname);
+                    }
+                    return parser.constantPoolParser.stringValue(info);
+                } catch (ConstantPoolException e) {
+                    throw new RuntimeException(e);
+                }
+            }
+
+            public String visitFloat(CONSTANT_Float_info info, Void p) {
+                // skip
+                return null;
+            }
+
+            public String visitInteger(CONSTANT_Integer_info info, Void p) {
+                // skip
+                return null;
+            }
+
+            public String visitInterfaceMethodref(CONSTANT_InterfaceMethodref_info info, Void p) {
+                return addMethodDescriptor(info, p);
+            }
+
+            public String visitLong(CONSTANT_Long_info info, Void p) {
+                // skip
+                return null;
+            }
+
+            public String visitNameAndType(CONSTANT_NameAndType_info info, Void p) {
+                // skip
+                return null;
+            }
+
+            public String visitMethodref(CONSTANT_Methodref_info info, Void p) {
+                return addMethodDescriptor(info, p);
+            }
+
+            public String visitString(CONSTANT_String_info info, Void p) {
+                // skip
+                return null;
+            }
+
+            public String visitUtf8(CONSTANT_Utf8_info info, Void p) {
+                return null;
+            }
+        };
+    }
+    static boolean traceOn = System.getProperty("classanalyzer.debug") != null;
+
+    private static void trace(String format, Object... args) {
+        if (traceOn) {
+            System.out.format(format, args);
+        }
+    }
+
+    private static void usage() {
+        System.out.println("Usage: BootAnalyzer <options>");
+        System.out.println("Options: ");
+        System.out.println("\t-jdkhome <JDK home> where all jars will be parsed");
+        System.out.println("\t-config  <roots for the boot module>");
+        System.out.println("\t-output  <output dir>");
+        System.out.println("\t-classlist print class list and summary");
+        System.exit(-1);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/make/modules/tools/src/com/sun/classanalyzer/CheckDeps.java	Wed Jul 05 17:04:56 2017 +0200
@@ -0,0 +1,181 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+package com.sun.classanalyzer;
+
+import java.io.*;
+import java.util.*;
+
+/**
+ * A simple tool to check module dependencies against a known list of
+ * dependencies. The tool fails (by throwing a RuntimeException) is an
+ * unexpected dependency is detected.
+ */
+
+public class CheckDeps {
+
+    /**
+     * Represents a dependency from one module to another module. The dependency
+     * may be optional.
+     */
+    static class Dependency {
+        private final String module;
+        private final String other;
+        private final boolean optional;
+
+        private Dependency(String module, String other, boolean optional) {
+            this.module = module;
+            this.other = other;
+            this.optional = optional;
+        }
+
+        String module()      { return module; }
+        String other()       { return other; }
+        boolean isOptional() { return optional; }
+
+        /**
+         * Parses a dependency in one of the following forms:
+         *   a -> b
+         *   [optional] a -> b
+         */
+        static Dependency fromString(String s) {
+            String[] components = s.split(" ");
+            int count = components.length;
+            if (count != 3 && count != 4)
+                throw new IllegalArgumentException(s);
+            boolean optional = (count == 4);
+            if (optional && !components[0].equals("[optional]"))
+                throw new IllegalArgumentException(s);
+            String arrow = optional ? components[2] : components[1];
+            if (!arrow.equals("->"))
+                throw new IllegalArgumentException(s);
+            String module = optional ? components[1] : components[0];
+            String other = optional ? components[3] : components[2];
+            return new Dependency(module, other, optional);
+        }
+
+        @Override public String toString() {
+            StringBuilder sb = new StringBuilder();
+            if (optional)
+                sb.append("[optional] ");
+            sb.append(module);
+            sb.append(" -> ");
+            sb.append(other);
+            return sb.toString();
+        }
+    }
+
+    /**
+     * Represents the "tail"
+     */
+    static class DependencyTail {
+        private final String module;
+        private final boolean optional;
+
+        DependencyTail(String module, boolean optional) {
+            this.module = module;
+            this.optional = optional;
+        }
+        String module()      { return module; }
+        boolean isOptional() { return optional; }
+    }
+
+    static void usage() {
+        System.out.println("java CheckDeps file1 file2");
+        System.out.println("  where file1 is the expected dependencies and file2 is");
+        System.out.println("  the actual dependencies. Both files are assumed to be");
+        System.out.println("  in modules.summary format (see ClassAnalyzer tool).");
+        System.out.println();
+        System.out.println("Example usages:");
+        System.out.println("  java CheckDeps make/modules/modules.summary " +
+            "$(OUTPUTDIR)/modules.summary");
+        System.exit(-1);
+    }
+
+    public static void main(String[] args) throws IOException {
+        if (args.length != 2)
+            usage();
+
+        // maps a module to the list of modules that it depends on
+        Map<String,List<DependencyTail>> expected =
+            new HashMap<String,List<DependencyTail>>();
+
+        // parse the expected dependencies file
+        Scanner s;
+        s = new Scanner(new FileInputStream(args[0]));
+        try {
+            while (s.hasNextLine()) {
+                Dependency ref = Dependency.fromString(s.nextLine());
+                if (ref != null) {
+                    String module = ref.module();
+                    List<DependencyTail> list = expected.get(module);
+                    if (list == null) {
+                        list = new ArrayList<DependencyTail>();
+                        expected.put(module, list);
+                    }
+                    list.add(new DependencyTail(ref.other(), ref.isOptional()));
+                }
+            }
+        } finally {
+            s.close();
+        }
+
+        // parse the actual dependencies file, checking each dependency
+        // against the expected list.
+        boolean fail = false;
+        s = new Scanner(new FileInputStream(args[1]));
+        try {
+            while (s.hasNextLine()) {
+                Dependency dep = Dependency.fromString(s.nextLine());
+
+                // check if this dependency is expected
+                List<DependencyTail> list = expected.get(dep.module());
+                DependencyTail tail = null;
+                if (list != null) {
+                    for (DependencyTail t: list) {
+                        if (t.module().equals(dep.other())) {
+                            tail = t;
+                            break;
+                        }
+                    }
+                }
+                if (tail == null) {
+                    System.err.println("Unexpected dependency: " + dep);
+                    fail = true;
+                } else {
+                    // hard dependency when optional dependency is expected
+                    if (tail.isOptional() != dep.isOptional()) {
+                        if (tail.isOptional()) {
+                            System.err.println("Unexpected dependency: " + dep);
+                            fail = true;
+                        }
+                    }
+                }
+            }
+        } finally {
+            s.close();
+        }
+
+        if (fail)
+            throw new RuntimeException("Unexpected dependencies found");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/make/modules/tools/src/com/sun/classanalyzer/ClassAnalyzer.java	Wed Jul 05 17:04:56 2017 +0200
@@ -0,0 +1,354 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+package com.sun.classanalyzer;
+
+import com.sun.classanalyzer.AnnotatedDependency.*;
+import com.sun.classanalyzer.Module.Dependency;
+import com.sun.classanalyzer.Module.PackageInfo;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.io.File;
+import java.io.PrintWriter;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeMap;
+import java.util.TreeSet;
+
+/**
+ *
+ * @author Mandy Chung
+ */
+public class ClassAnalyzer {
+
+    public static void main(String[] args) throws Exception {
+        String jdkhome = null;
+        String cpath = null;
+        List<String> configs = new ArrayList<String>();
+        List<String> depconfigs = new ArrayList<String>();
+        String output = ".";
+        boolean mergeModules = true;
+        boolean showDynamic = false;
+
+        // process arguments
+        int i = 0;
+        while (i < args.length) {
+            String arg = args[i++];
+            if (arg.equals("-jdkhome")) {
+                if (i < args.length) {
+                    jdkhome = args[i++];
+                } else {
+                    usage();
+                }
+            } else if (arg.equals("-cpath")) {
+                if (i < args.length) {
+                    cpath = args[i++];
+                } else {
+                    usage();
+                }
+            } else if (arg.equals("-config")) {
+                if (i < args.length) {
+                    configs.add(args[i++]);
+                } else {
+                    usage();
+                }
+            } else if (arg.equals("-depconfig")) {
+                if (i < args.length) {
+                    depconfigs.add(args[i++]);
+                } else {
+                    usage();
+                }
+            } else if (arg.equals("-output")) {
+                if (i < args.length) {
+                    output = args[i++];
+                } else {
+                    usage();
+                }
+            } else if (arg.equals("-base")) {
+                ModuleConfig.setBaseModule(args[i++]);
+            } else if (arg.equals("-nomerge")) {
+                // analyze the fine-grained module dependencies
+                mergeModules = false;
+            } else if (arg.equals("-showdynamic")) {
+                showDynamic = true;
+            } else {
+                System.err.println("Invalid option: " + arg);
+                usage();
+            }
+        }
+
+        if ((jdkhome == null && cpath == null) || (jdkhome != null && cpath != null)) {
+            usage();
+        }
+        if (configs.isEmpty()) {
+            usage();
+        }
+
+        if (jdkhome != null) {
+            ClassPath.setJDKHome(jdkhome);
+        } else if (cpath != null) {
+            ClassPath.setClassPath(cpath);
+        }
+
+        // create output directory if it doesn't exist
+        File dir = new File(output);
+        if (!dir.isDirectory()) {
+            if (!dir.exists()) {
+                boolean created = dir.mkdir();
+                if (!created) {
+                    throw new RuntimeException("Unable to create `" + dir + "'");
+                }
+            }
+        }
+
+        buildModules(configs, depconfigs, mergeModules);
+
+        // generate output files
+        for (Module m : modules) {
+            // only generate reports for top-level modules
+            if (m.group() == m) {
+                m.printClassListTo(resolve(dir, m.name(), "classlist"));
+                m.printResourceListTo(resolve(dir, m.name(), "resources"));
+                m.printSummaryTo(resolve(dir, m.name(), "summary"));
+                m.printDependenciesTo(resolve(dir, m.name(), "dependencies"), showDynamic);
+            }
+        }
+
+        // Generate other summary reports
+        printModulesSummary(dir, showDynamic);
+        printModulesDot(dir, showDynamic);
+        printModulesList(dir);
+        printPackagesSummary(dir);
+    }
+    private static List<Module> modules = new ArrayList<Module>();
+
+    static void buildModules(List<String> configs,
+            List<String> depconfigs,
+            boolean mergeModules) throws IOException {
+        // create modules based on the input config files
+        for (String file : configs) {
+            for (ModuleConfig mconfig : ModuleConfig.readConfigurationFile(file)) {
+                modules.add(Module.addModule(mconfig));
+            }
+        }
+
+        // parse class files
+        ClassPath.parseAllClassFiles();
+
+        // Add additional dependencies if specified
+        if (depconfigs != null && depconfigs.size() > 0) {
+            DependencyConfig.parse(depconfigs);
+        }
+
+        // process the roots and dependencies to get the classes for each module
+        for (Module m : modules) {
+            m.processRootsAndReferences();
+        }
+
+        // update the dependencies for classes that were subsequently allocated
+        // to modules
+        for (Module m : modules) {
+            m.fixupDependencies();
+        }
+
+        if (mergeModules) {
+            Module.buildModuleMembers();
+        }
+    }
+
+    private static void printModulesSummary(File dir, boolean showDynamic) throws IOException {
+        // print summary of dependencies
+        PrintWriter writer = new PrintWriter(new File(dir, "modules.summary"));
+        try {
+            for (Module m : modules) {
+                // only show top-level module dependencies
+                if (m.group() == m) {
+                    for (Dependency dep : m.dependents()) {
+                        if (!showDynamic && dep.dynamic && dep.optional) {
+                            continue;
+                        }
+                        if (dep.module == null || !dep.module.isBase()) {
+
+                            String prefix = "";
+                            if (dep.optional) {
+                                if (dep.dynamic) {
+                                    prefix = "[dynamic] ";
+                                } else {
+                                    prefix = "[optional] ";
+                                }
+                            }
+
+                            Module other = dep != null ? dep.module : null;
+                            writer.format("%s%s -> %s%n", prefix, m, other);
+                        }
+                    }
+                }
+            }
+        } finally {
+            writer.close();
+        }
+    }
+
+    private static void printModulesDot(File dir, boolean showDynamic) throws IOException {
+        PrintWriter writer = new PrintWriter(new File(dir, "modules.dot"));
+        try {
+            writer.println("digraph jdk {");
+            for (Module m : modules) {
+                if (m.group() == m) {
+                    for (Dependency dep : m.dependents()) {
+                        if (!showDynamic && dep.dynamic && dep.optional) {
+                            continue;
+                        }
+                        if (dep.module == null || !dep.module.isBase()) {
+                            String style = "";
+                            String color = "";
+                            String property = "";
+                            if (dep.optional) {
+                                style = "style=dotted";
+                            }
+                            if (dep.dynamic) {
+                                color = "color=red";
+                            }
+                            if (style.length() > 0 || color.length() > 0) {
+                                String comma = "";
+                                if (style.length() > 0 && color.length() > 0) {
+                                    comma = ", ";
+                                }
+                                property = String.format(" [%s%s%s]", style, comma, color);
+                            }
+                            Module other = dep != null ? dep.module : null;
+                            writer.format("    \"%s\" -> \"%s\"%s;%n", m, other, property);
+                        }
+                    }
+                }
+            }
+            writer.println("}");
+        } finally {
+            writer.close();
+        }
+    }
+
+    private static void printMembers(Module m, PrintWriter writer) {
+        for (Module member : m.members()) {
+            if (!member.isEmpty()) {
+                writer.format("%s ", member);
+                printMembers(member, writer);
+            }
+        }
+    }
+
+    private static void printModulesList(File dir) throws IOException {
+        // print module group / members relationship
+        PrintWriter writer = new PrintWriter(new File(dir, "modules.list"));
+        try {
+            for (Module m : modules) {
+                if (m.group() == m && !m.isEmpty()) {
+                    writer.format("%s ", m);
+                    printMembers(m, writer);
+                    writer.println();
+                }
+            }
+        } finally {
+            writer.close();
+        }
+    }
+
+    private static void printPackagesSummary(File dir) throws IOException {
+        // print package / module relationship
+        PrintWriter writer = new PrintWriter(new File(dir, "modules.pkginfo"));
+        try {
+            Map<String, Set<Module>> packages = new TreeMap<String, Set<Module>>();
+            Set<String> splitPackages = new TreeSet<String>();
+
+            for (Module m : modules) {
+                if (m.group() == m) {
+                    for (PackageInfo info : m.getPackageInfos()) {
+                        Set<Module> value = packages.get(info.pkgName);
+                        if (value == null) {
+                            value = new TreeSet<Module>();
+                            packages.put(info.pkgName, value);
+                        } else {
+                            // package in more than one module
+                            splitPackages.add(info.pkgName);
+                        }
+                        value.add(m);
+                    }
+                }
+            }
+
+            // packages that are splitted among multiple modules
+            writer.println("Packages splitted across modules:-\n");
+            writer.format("%-60s  %s\n", "Package", "Module");
+
+            for (String pkgname : splitPackages) {
+                writer.format("%-60s", pkgname);
+                for (Module m : packages.get(pkgname)) {
+                    writer.format("  %s", m);
+                }
+                writer.println();
+            }
+
+            writer.println("\nPackage-private dependencies:-");
+            for (String pkgname : splitPackages) {
+                for (Klass k : Klass.getAllClasses()) {
+                    if (k.getPackageName().equals(pkgname)) {
+                        Module m = k.getModule();
+                        // check if this klass references a package-private
+                        // class that is in a different module
+                        for (Klass other : k.getReferencedClasses()) {
+                            if (other.getModule() != m &&
+                                    !other.isPublic() &&
+                                    other.getPackageName().equals(pkgname)) {
+                                String from = k.getClassName() + " (" + m + ")";
+                                writer.format("%-60s -> %s (%s)\n", from, other, other.getModule());
+                            }
+                        }
+                    }
+                }
+            }
+        } finally {
+            writer.close();
+        }
+
+    }
+
+    private static String resolve(File dir, String mname, String suffix) {
+        File f = new File(dir, mname + "." + suffix);
+        return f.toString();
+
+    }
+
+    private static void usage() {
+        System.out.println("Usage: ClassAnalyzer <options>");
+        System.out.println("Options: ");
+        System.out.println("\t-jdkhome <JDK home> where all jars will be parsed");
+        System.out.println("\t-cpath   <classpath> where classes and jars will be parsed");
+        System.out.println("\t         Either -jdkhome or -cpath option can be used.");
+        System.out.println("\t-config  <module config file>");
+        System.out.println("\t         This option can be repeated for multiple module config files");
+        System.out.println("\t-output  <output dir>");
+        System.out.println("\t-nomerge specify not to merge modules");
+        System.out.println("\t-showdynamic show dynamic dependencies in the reports");
+        System.exit(-1);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/make/modules/tools/src/com/sun/classanalyzer/ClassFileParser.java	Wed Jul 05 17:04:56 2017 +0200
@@ -0,0 +1,629 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ *
+ */
+package com.sun.classanalyzer;
+
+import com.sun.tools.classfile.*;
+import com.sun.tools.classfile.Type.*;
+import com.sun.tools.classfile.Descriptor.InvalidDescriptor;
+import static com.sun.tools.classfile.AccessFlags.*;
+
+import java.io.BufferedInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.List;
+import java.util.Set;
+import java.util.TreeSet;
+
+/**
+ *
+ * @author Mandy Chung
+ */
+public class ClassFileParser {
+
+    final Klass this_klass;
+    final ClassFile classfile;
+    final ConstantPoolParser constantPoolParser;
+    final AnnotationParser annotationParser;
+    final CodeAttributeParser codeAttributeParser;
+    private final boolean buildDeps;
+
+    protected ClassFileParser(InputStream in, long size, boolean buildDeps) throws IOException {
+        try {
+            this.classfile = ClassFile.read(in);
+            this.this_klass = getKlass(this.classfile);
+            this.buildDeps = buildDeps;
+            this.constantPoolParser = new ConstantPoolParser(this);
+            this.annotationParser = new AnnotationParser(this);
+            this.codeAttributeParser = new CodeAttributeParser(this);
+        } catch (ConstantPoolException ex) {
+            throw new RuntimeException(ex);
+        }
+    }
+
+    private Klass getKlass(ClassFile cf) throws ConstantPoolException {
+        Klass k = Klass.getKlass(cf.getName());
+        k.setAccessFlags(cf.access_flags.flags);
+        k.setFileSize(cf.byteLength());
+        return k;
+    }
+
+    public static ClassFileParser newParser(InputStream in, long size, boolean buildDeps) throws IOException {
+        return new ClassFileParser(in, size, buildDeps);
+    }
+
+    public static ClassFileParser newParser(String classPathname, boolean buildDeps) throws IOException {
+        return newParser(new File(classPathname), buildDeps);
+    }
+
+    public static ClassFileParser newParser(File f, boolean buildDeps) throws IOException {
+        BufferedInputStream in = new BufferedInputStream(new FileInputStream(f));
+        try {
+            return newParser(in, f.length(), buildDeps);
+        } finally {
+            in.close();
+        }
+    }
+
+    public void parseDependency(boolean publicAPIs) throws IOException {
+        if (publicAPIs && !classfile.access_flags.is(ACC_PUBLIC)) {
+            // process public APIs only
+            return;
+        }
+
+        parseClassInfo();
+        if (!publicAPIs) {
+            // parse all references in the classfile
+            constantPoolParser.parseDependency();
+        }
+        parseMethods(publicAPIs);
+        parseFields(publicAPIs);
+    }
+
+    void parseClassInfo() throws IOException {
+        ConstantPool cpool = classfile.constant_pool;
+        try {
+            Signature_attribute sigAttr = (Signature_attribute) classfile.attributes.get(Attribute.Signature);
+            if (sigAttr == null) {
+                // use info from class file header
+                if (classfile.isClass() && classfile.super_class != 0) {
+                    String sn = classfile.getSuperclassName();
+                    addExtends(sn);
+                }
+                for (int i = 0; i < classfile.interfaces.length; i++) {
+                    String interf = classfile.getInterfaceName(i);
+                    if (classfile.isClass()) {
+                        addImplements(interf);
+                    } else {
+                        addExtends(interf);
+                    }
+                }
+            } else {
+                Type t = sigAttr.getParsedSignature().getType(cpool);
+                // The signature parser cannot disambiguate between a
+                // FieldType and a ClassSignatureType that only contains a superclass type.
+                if (t instanceof Type.ClassSigType) {
+                    Type.ClassSigType cst = Type.ClassSigType.class.cast(t);
+                    if (cst.superclassType != null) {
+                        for (Klass k : getKlass(cst.superclassType)) {
+                            addExtends(k);
+                        }
+                    }
+                    if (cst.superinterfaceTypes != null) {
+                        for (Type t1 : cst.superinterfaceTypes) {
+                            for (Klass k : getKlass(t1)) {
+                                addImplements(k);
+                            }
+                        }
+                    }
+                } else {
+                    for (Klass k : getKlass(t)) {
+                        addExtends(k);
+                    }
+                }
+            }
+            // parse attributes
+            annotationParser.parseAttributes(classfile.attributes);
+        } catch (ConstantPoolException ex) {
+            throw new RuntimeException(ex);
+        }
+    }
+
+    private void parseFields(boolean publicAPIs) throws IOException {
+        ConstantPool cpool = classfile.constant_pool;
+        for (Field f : classfile.fields) {
+            try {
+                AccessFlags flags = f.access_flags;
+                if (publicAPIs && !flags.is(ACC_PUBLIC) && !flags.is(ACC_PROTECTED)) {
+                    continue;
+                }
+                String fieldname = f.getName(cpool);
+                Signature_attribute sigAttr = (Signature_attribute) f.attributes.get(Attribute.Signature);
+
+                if (sigAttr == null) {
+                    Set<Klass> types = parseDescriptor(f.descriptor);
+                    String info = getFlag(flags) + " " + f.descriptor.getFieldType(cpool) + " " + fieldname;
+                    addFieldTypes(types, info, flags);
+                } else {
+                    Type t = sigAttr.getParsedSignature().getType(cpool);
+                    String info = getFlag(flags) + " " + t + " " + fieldname;
+                    addFieldTypes(getKlass(t), info, flags);
+                }
+                // parse attributes
+                annotationParser.parseAttributes(f.attributes);
+            } catch (ConstantPoolException ex) {
+                throw new RuntimeException(ex);
+            } catch (InvalidDescriptor ex) {
+                throw new RuntimeException(ex);
+            }
+        }
+    }
+
+    private void parseMethods(boolean publicAPIs) {
+        for (Method m : classfile.methods) {
+            if (publicAPIs && !m.access_flags.is(ACC_PUBLIC) && !m.access_flags.is(ACC_PROTECTED)) {
+                // only interest in the API level
+                return;
+            }
+
+            parseMethod(m);
+        }
+    }
+
+    String checkClassName(String classname) {
+        int i = 0;
+        while (i < classname.length()) {
+            switch (classname.charAt(i)) {
+                case 'Z':
+                case 'B':
+                case 'C':
+                case 'S':
+                case 'I':
+                case 'J':
+                case 'F':
+                case 'D':
+                    return "";
+                case 'L':
+                    if (!classname.endsWith(";")) {
+                        throw new RuntimeException("Invalid classname " + classname);
+                    }
+                    return classname.substring(i + 1, classname.length() - 1);
+                case '[':
+                    i++;
+                    break;
+                default:
+                    if (classname.endsWith(";")) {
+                        throw new RuntimeException("Invalid classname " + classname);
+                    }
+                    return classname;
+
+            }
+        }
+        throw new RuntimeException("Invalid classname " + classname);
+    }
+
+    private void addExtends(String classname) throws IOException {
+        if (!buildDeps) {
+            return;
+        }
+
+        addExtends(Klass.getKlass(classname));
+    }
+
+    private void addExtends(Klass k) {
+        if (!buildDeps) {
+            return;
+        }
+
+        ResolutionInfo resInfo = ResolutionInfo.resolvedExtends(this_klass, k);
+        resInfo.setPublicAccess(classfile.access_flags.is(ACC_PUBLIC));
+        this_klass.addDep(k, resInfo);
+        k.addReferrer(this_klass, resInfo);
+    }
+
+    private void addImplements(String classname) throws IOException {
+        if (!buildDeps) {
+            return;
+        }
+
+        addImplements(Klass.getKlass(classname));
+    }
+
+    private void addImplements(Klass k) {
+        if (!buildDeps) {
+            return;
+        }
+
+        ResolutionInfo resInfo = ResolutionInfo.resolvedImplements(this_klass, k);
+        resInfo.setPublicAccess(classfile.access_flags.is(ACC_PUBLIC));
+
+        this_klass.addDep(k, resInfo);
+
+        k.addReferrer(this_klass, resInfo);
+    }
+
+    private Set<Klass> getKlass(Type type) throws IOException {
+        Set<Klass> refTypes = new TreeSet<Klass>();
+        if (!buildDeps) {
+            return refTypes;
+        }
+
+        type.accept(typevisitor, refTypes);
+        return refTypes;
+    }
+    private Type.Visitor<Void, Set<Klass>> typevisitor = new Type.Visitor<Void, Set<Klass>>() {
+
+        public Void visitSimpleType(SimpleType type, Set<Klass> klasses) {
+            // nop
+            return null;
+        }
+
+        public Void visitArrayType(ArrayType type, Set<Klass> klasses) {
+            try {
+                klasses.addAll(getKlass(type.elemType));
+            } catch (IOException ex) {
+                throw new RuntimeException(ex);
+            }
+            return null;
+
+        }
+
+        public Void visitMethodType(MethodType type, Set<Klass> klasses) {
+            throw new InternalError("Unexpected type " + type);
+        }
+
+        public Void visitClassSigType(ClassSigType type, Set<Klass> klasses) {
+            try {
+                if (type.superclassType != null) {
+                    klasses.addAll(getKlass(type.superclassType));
+                }
+                if (type.superinterfaceTypes != null) {
+                    for (Type t : type.superinterfaceTypes) {
+                        klasses.addAll(getKlass(t));
+                    }
+                }
+                if (type.typeParamTypes != null) {
+                    for (Type t : type.typeParamTypes) {
+                        klasses.addAll(getKlass(t));
+                    }
+                }
+            } catch (IOException ex) {
+                throw new RuntimeException(ex);
+            }
+            return null;
+        }
+
+        public Void visitClassType(ClassType type, Set<Klass> klasses) {
+            klasses.add(Klass.getKlass(type.getBinaryName()));
+            if (type.typeArgs != null) {
+                for (Type t : type.typeArgs) {
+                    try {
+                        klasses.addAll(getKlass(t));
+                    } catch (IOException ex) {
+                        throw new RuntimeException(ex);
+                    }
+                }
+            }
+            return null;
+
+        }
+
+        public Void visitTypeParamType(TypeParamType type, Set<Klass> klasses) {
+            try {
+                if (type.classBound != null) {
+                    klasses.addAll(getKlass(type.classBound));
+                }
+                if (type.interfaceBounds != null) {
+                    for (Type t : type.interfaceBounds) {
+                        klasses.addAll(getKlass(t));
+                    }
+                }
+
+            } catch (IOException ex) {
+                throw new RuntimeException(ex);
+            }
+
+            return null;
+
+        }
+
+        public Void visitWildcardType(WildcardType type, Set<Klass> klasses) {
+            if (type.boundType != null) {
+                try {
+                    klasses.addAll(getKlass(type.boundType));
+                } catch (IOException ex) {
+                    throw new RuntimeException(ex);
+                }
+            }
+            return null;
+
+        }
+    };
+
+    private void printMethod(Method m) {
+        try {
+            System.out.println("parsing " + m.getName(classfile.constant_pool) + "(" +
+                    m.descriptor.getParameterTypes(classfile.constant_pool) + ") return type " +
+                    m.descriptor.getReturnType(classfile.constant_pool));
+
+        } catch (ConstantPoolException ex) {
+        } catch (InvalidDescriptor ex) {
+        }
+    }
+
+    private static StringBuilder appendWord(StringBuilder sb, String word) {
+        if (sb.length() > 0) {
+            sb.append(" ");
+        }
+        sb.append(word);
+        return sb;
+    }
+
+    private static String getFlag(AccessFlags flags) {
+        StringBuilder modifier = new StringBuilder();
+        if (flags.is(ACC_PUBLIC)) {
+            modifier.append("public");
+        }
+        if (flags.is(ACC_PRIVATE)) {
+            modifier.append("private");
+        }
+        if (flags.is(ACC_PROTECTED)) {
+            modifier.append("protected");
+        }
+        if (flags.is(ACC_STATIC)) {
+            appendWord(modifier, "static");
+        }
+        if (flags.is(ACC_FINAL)) {
+            appendWord(modifier, "final");
+        }
+        if (flags.is(ACC_SYNCHRONIZED)) {
+            // return "synchronized";
+        }
+        if (flags.is(0x80)) {
+            // return (t == Type.Field ? "transient" : null);
+            // return "transient";
+        }
+        if (flags.is(ACC_VOLATILE)) {
+            // return "volatile";
+        }
+        if (flags.is(ACC_NATIVE)) {
+            // return "native";
+        }
+        if (flags.is(ACC_ABSTRACT)) {
+            appendWord(modifier, "abstract");
+        }
+        if (flags.is(ACC_STRICT)) {
+            // return "strictfp";
+        }
+        if (flags.is(ACC_MODULE)) {
+            appendWord(modifier, "module");
+        }
+        return modifier.toString();
+    }
+
+    private Klass.Method toKlassMethod(Method m, Descriptor d) {
+        try {
+            ConstantPool cpool = classfile.constant_pool;
+            String methodname = m.getName(cpool);
+            StringBuilder sb = new StringBuilder();
+            sb.append(getFlag(m.access_flags));
+            if (methodname.equals("<init>")) {
+                String s = this_klass.getBasename() + d.getParameterTypes(cpool);
+                appendWord(sb, s);
+            } else if (methodname.equals("<clinit>")) {
+                // <clinit>
+                appendWord(sb, methodname);
+            } else {
+                String s = d.getReturnType(cpool) + " " + methodname + d.getParameterTypes(cpool);
+                appendWord(sb, s);
+            }
+            String signature = sb.toString().replace('/', '.');
+            return this_klass.getMethod(methodname, signature);
+        } catch (ConstantPoolException ex) {
+            throw new RuntimeException(ex);
+        } catch (InvalidDescriptor ex) {
+            throw new RuntimeException(ex);
+        }
+    }
+
+    Klass.Method parseMethod(Method m) {
+        AccessFlags flags = m.access_flags;
+        Descriptor d;
+        List<? extends Type> methodExceptions = null;
+        try {
+            ConstantPool cpool = classfile.constant_pool;
+            Klass.Method kmethod;
+            Signature_attribute sigAttr = (Signature_attribute) m.attributes.get(Attribute.Signature);
+            if (sigAttr == null) {
+                d = m.descriptor;
+                Set<Klass> types = parseDescriptor(d);
+
+                kmethod = toKlassMethod(m, d);
+                addMethodTypes(types, kmethod, flags);
+            } else {
+                Type.MethodType methodType;
+                Signature methodSig = sigAttr.getParsedSignature();
+                d = methodSig;
+                try {
+                    kmethod = toKlassMethod(m, d);
+                    methodType = (Type.MethodType) methodSig.getType(cpool);
+                    addMethodTypes(getKlass(methodType.returnType), kmethod, flags);
+                    if (methodType.paramTypes != null) {
+                        for (Type t : methodType.paramTypes) {
+                            addMethodTypes(getKlass(t), kmethod, flags);
+                        }
+                    }
+                    if (methodType.typeParamTypes != null) {
+                        for (Type t : methodType.typeParamTypes) {
+                            addMethodTypes(getKlass(t), kmethod, flags);
+                        }
+                    }
+
+                    methodExceptions = methodType.throwsTypes;
+                    if (methodExceptions != null) {
+                        if (methodExceptions.size() == 0) {
+                            methodExceptions = null;
+                        } else {
+                            for (Type t : methodExceptions) {
+                                addCheckedExceptionTypes(getKlass(t), kmethod, flags);
+                            }
+                        }
+                    }
+                } catch (ConstantPoolException e) {
+                    throw new RuntimeException(e);
+                }
+            }
+
+            Attribute e_attr = m.attributes.get(Attribute.Exceptions);
+            if (e_attr != null && methodExceptions == null) {
+                // if there are generic exceptions, there must be erased exceptions
+                if (e_attr instanceof Exceptions_attribute) {
+                    Exceptions_attribute exceptions = (Exceptions_attribute) e_attr;
+                    for (int i = 0; i < exceptions.number_of_exceptions; i++) {
+                        String classname = checkClassName(exceptions.getException(i, classfile.constant_pool));
+                        if (classname.length() > 0 && buildDeps) {
+                            Klass to = Klass.getKlass(classname);
+                            ResolutionInfo resInfo = ResolutionInfo.resolvedCheckedException(this_klass, to, kmethod);
+                            resInfo.setPublicAccess(flags.is(ACC_PUBLIC));
+
+                            this_klass.addDep(to, resInfo);
+                            to.addReferrer(this_klass, resInfo);
+                        }
+                    }
+                } else {
+                    throw new RuntimeException("Invalid attribute: " + e_attr);
+                }
+            }
+
+            Code_attribute c_attr = (Code_attribute) m.attributes.get(Attribute.Code);
+            if (c_attr != null) {
+                codeAttributeParser.parse(c_attr, kmethod);
+            }
+            kmethod.isAbstract = classfile.access_flags.is(ACC_ABSTRACT);
+            kmethod.setCodeLength(m.byteLength());
+
+            // parse annotation attributes
+            annotationParser.parseAttributes(m.attributes, kmethod);
+            return kmethod;
+        } catch (ConstantPoolException ex) {
+            throw new RuntimeException(ex);
+        } catch (IOException ex) {
+            throw new RuntimeException(ex);
+        }
+    }
+
+    private void addFieldTypes(Set<Klass> types, String info, AccessFlags flags) {
+        if (types.isEmpty() || !buildDeps) {
+            return;
+        }
+
+        for (Klass to : types) {
+            ResolutionInfo resInfo = ResolutionInfo.resolvedField(this_klass, to, info);
+            resInfo.setPublicAccess(flags.is(ACC_PUBLIC));
+
+            this_klass.addDep(to, resInfo);
+            to.addReferrer(this_klass, resInfo);
+        }
+    }
+
+    private void addReferencedTypes(Method m, Descriptor d, AccessFlags flags) {
+        Set<Klass> types = parseDescriptor(d);
+
+        Klass.Method method = toKlassMethod(m, d);
+        addMethodTypes(types, method, flags);
+    }
+
+    private void addMethodTypes(Set<Klass> types, Klass.Method method, AccessFlags flags) {
+        if (types.isEmpty() || !buildDeps) {
+            return;
+        }
+        for (Klass to : types) {
+            ResolutionInfo resInfo = ResolutionInfo.resolvedMethodSignature(this_klass, to, method);
+            resInfo.setPublicAccess(flags.is(ACC_PUBLIC));
+
+            this_klass.addDep(to, resInfo);
+            to.addReferrer(this_klass, resInfo);
+        }
+    }
+
+    private void addCheckedExceptionTypes(Set<Klass> types, Klass.Method method, AccessFlags flags) {
+        if (types.isEmpty() || !buildDeps) {
+            return;
+        }
+        for (Klass to : types) {
+            ResolutionInfo resInfo = ResolutionInfo.resolvedCheckedException(this_klass, to, method);
+            resInfo.setPublicAccess(flags.is(ACC_PUBLIC));
+
+            this_klass.addDep(to, resInfo);
+            to.addReferrer(this_klass, resInfo);
+        }
+    }
+
+    private Set<Klass> parseDescriptor(Descriptor d) {
+        Set<Klass> types = new TreeSet<Klass>();
+        try {
+            String desc = d.getValue(classfile.constant_pool);
+            int p = 0;
+            while (p < desc.length()) {
+                String type;
+                char ch;
+                switch (ch = desc.charAt(p++)) {
+                    case '(':
+                    case ')':
+                    case '[':
+                    case 'B':
+                    case 'C':
+                    case 'D':
+                    case 'F':
+                    case 'I':
+                    case 'J':
+                    case 'S':
+                    case 'Z':
+                    case 'V':
+                        continue;
+                    case 'L':
+                        int sep = desc.indexOf(';', p);
+                        if (sep == -1) {
+                            throw new RuntimeException("Invalid descriptor: " + (p - 1) + " " + desc);
+                        }
+                        type = checkClassName(desc.substring(p, sep));
+                        p = sep + 1;
+                        break;
+                    default:
+                        throw new RuntimeException("Invalid descriptor: " + (p - 1) + " " + desc);
+                }
+
+                if (!type.isEmpty() && buildDeps) {
+                    Klass to = Klass.getKlass(type);
+                    types.add(to);
+
+                }
+            }
+        } catch (ConstantPoolException ex) {
+            throw new RuntimeException(ex);
+        }
+        return types;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/make/modules/tools/src/com/sun/classanalyzer/ClassPath.java	Wed Jul 05 17:04:56 2017 +0200
@@ -0,0 +1,275 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ *
+ */
+package com.sun.classanalyzer;
+
+import java.io.BufferedInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+
+/**
+ *
+ * @author mchung
+ */
+public class ClassPath {
+
+    public class FileInfo {
+
+        File file;
+        JarFile jarfile;
+        int classCount;
+        long filesize;
+
+        FileInfo(File f) throws IOException {
+            this.file = f;
+            this.classCount = 0;
+            if (file.getName().endsWith(".jar")) {
+                this.filesize = file.length();
+                jarfile = new JarFile(f);
+            }
+        }
+
+        File getFile() {
+            return file;
+        }
+
+        JarFile getJarFile() {
+            return jarfile;
+        }
+
+        String getName() throws IOException {
+            return file.getCanonicalPath();
+        }
+    }
+    private List<FileInfo> fileList = new ArrayList<FileInfo>();
+    private static ClassPath instance = new ClassPath();
+
+    static List<FileInfo> getFileInfos() {
+        return instance.fileList;
+    }
+
+    static ClassPath setJDKHome(String jdkhome) throws IOException {
+        List<File> files = new ArrayList<File>();
+        File jre = new File(jdkhome, "jre");
+        File lib = new File(jdkhome, "lib");
+        if (jre.exists() && jre.isDirectory()) {
+            listFiles(new File(jre, "lib"), ".jar", files);
+        } else if (lib.exists() && lib.isDirectory()) {
+            // either a JRE or a jdk build image
+            listFiles(lib, ".jar", files);
+
+            File classes = new File(jdkhome, "classes");
+            if (classes.exists() && classes.isDirectory()) {
+                // jdk build outputdir
+                instance.add(classes);
+            }
+        } else {
+            throw new RuntimeException("\"" + jdkhome + "\" not a JDK home");
+        }
+
+        for (File f : files) {
+            instance.add(f);
+        }
+        return instance;
+    }
+
+    static ClassPath setClassPath(String path) throws IOException {
+        if (path.endsWith(".class")) {
+            // one class file
+            File f = new File(path);
+            if (!f.exists()) {
+                throw new RuntimeException("Classfile \"" + f + "\" doesn't exist");
+            }
+
+            instance.add(f);
+        } else {
+            List<File> jarFiles = new ArrayList<File>();
+            String[] locs = path.split(File.pathSeparator);
+            for (String p : locs) {
+                File f = new File(p);
+                if (!f.exists()) {
+                    throw new RuntimeException("\"" + f + "\" doesn't exist");
+                }
+
+                if (f.isDirectory()) {
+                    instance.add(f);  // add the directory to look up .class files
+                    listFiles(f, ".jar", jarFiles);
+                } else if (p.endsWith(".jar")) {
+                    // jar files
+                    jarFiles.add(f);
+                } else {
+                    throw new RuntimeException("Invalid file \"" + f);
+                }
+            }
+            // add jarFiles if any
+            for (File f : jarFiles) {
+                instance.add(f);
+            }
+        }
+
+        return instance;
+    }
+
+    private void add(File f) throws IOException {
+        fileList.add(new FileInfo(f));
+    }
+
+    public static InputStream open(String pathname) throws IOException {
+        for (FileInfo fi : instance.fileList) {
+            if (fi.getName().endsWith(".jar")) {
+                String path = pathname.replace(File.separatorChar, '/');
+                JarEntry e = fi.jarfile.getJarEntry(path);
+                if (e != null) {
+                    return fi.jarfile.getInputStream(e);
+                }
+            } else if (fi.getFile().isDirectory()) {
+                File f = new File(fi.getFile(), pathname);
+                if (f.exists()) {
+                    return new FileInputStream(f);
+                }
+            } else if (fi.file.isFile()) {
+                if (fi.getName().endsWith(File.separator + pathname)) {
+                    return new FileInputStream(fi.file);
+                }
+            }
+        }
+        return null;
+    }
+
+    static ClassFileParser parserForClass(String classname) throws IOException {
+        String pathname = classname.replace('.', File.separatorChar) + ".class";
+
+        ClassFileParser cfparser = null;
+        for (FileInfo fi : instance.fileList) {
+            if (fi.getName().endsWith(".class")) {
+                if (fi.getName().endsWith(File.separator + pathname)) {
+                    cfparser = ClassFileParser.newParser(fi.getFile(), true);
+                    break;
+                }
+            } else if (fi.getName().endsWith(".jar")) {
+                JarEntry e = fi.jarfile.getJarEntry(classname.replace('.', '/') + ".class");
+                if (e != null) {
+                    cfparser = ClassFileParser.newParser(fi.jarfile.getInputStream(e), e.getSize(), true);
+                    break;
+                }
+            } else if (fi.getFile().isDirectory()) {
+                File f = new File(fi.getFile(), pathname);
+                if (f.exists()) {
+                    cfparser = ClassFileParser.newParser(f, true);
+                    break;
+                }
+            }
+        }
+        return cfparser;
+    }
+
+    public static void parseAllClassFiles() throws IOException {
+        instance.parseFiles();
+    }
+
+    private void parseFiles() throws IOException {
+        Set<Klass> classes = new HashSet<Klass>();
+
+        int count = 0;
+        for (FileInfo fi : fileList) {
+            // filter out public generated classes (i.e. not public API)
+            // javax.management.remote.rmi._RMIConnectionImpl_Tie
+            // javax.management.remote.rmi._RMIServerImpl_Tie
+            if (fi.getName().endsWith(".class")) {
+                parseClass(fi);
+            } else if (fi.getName().endsWith(".jar")) {
+                Enumeration<JarEntry> entries = fi.jarfile.entries();
+                while (entries.hasMoreElements()) {
+                    JarEntry e = entries.nextElement();
+                    if (e.getName().endsWith(".class")) {
+                        ClassFileParser cfparser = ClassFileParser.newParser(fi.jarfile.getInputStream(e), e.getSize(), true);
+                        cfparser.parseDependency(false);
+                        fi.classCount++;
+                    } else if (!e.isDirectory() && ResourceFile.isResource(e.getName())) {
+                        ResourceFile.addResource(e.getName(), fi.jarfile.getInputStream(e));
+                    }
+                }
+            } else if (fi.getFile().isDirectory()) {
+                List<File> files = new ArrayList<File>();
+                listFiles(fi.getFile(), "", files);
+                for (File f : files) {
+                    if (f.getName().endsWith(".class")) {
+                        parseClass(fi, f);
+                    } else if (!f.isDirectory() && ResourceFile.isResource(f.getCanonicalPath())) {
+                        String pathname = f.getCanonicalPath();
+                        String dir = fi.getName();
+                        if (!pathname.startsWith(dir)) {
+                            throw new RuntimeException("Incorrect pathname " + pathname);
+                        }
+                        String name = pathname.substring(dir.length() + 1, pathname.length());
+                        BufferedInputStream in = new BufferedInputStream(new FileInputStream(f));
+                        try {
+                            ResourceFile.addResource(name, in);
+                        } finally {
+                            in.close();
+                        }
+                    }
+                }
+            } else {
+                // should not reach here
+                throw new RuntimeException("Unexpected class path: " + fi.getFile());
+            }
+        }
+    }
+
+    private void parseClass(FileInfo fi) throws IOException {
+        parseClass(fi, fi.getFile());
+    }
+
+    private void parseClass(FileInfo fi, File f) throws IOException {
+        ClassFileParser cfparser = ClassFileParser.newParser(f, true);
+        cfparser.parseDependency(false);
+        fi.classCount++;
+        // need to update the filesize for this directory
+        fi.filesize += fi.getFile().length();
+
+    }
+
+    public static void listFiles(File path, String suffix, List<File> result) {
+        if (path.isDirectory()) {
+            File[] children = path.listFiles();
+            for (File c : children) {
+                listFiles(c, suffix, result);
+            }
+
+        } else {
+            if (suffix.isEmpty() || path.getName().endsWith(suffix)) {
+                result.add(path);
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/make/modules/tools/src/com/sun/classanalyzer/CodeAttributeParser.java	Wed Jul 05 17:04:56 2017 +0200
@@ -0,0 +1,157 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ *
+ */
+
+package com.sun.classanalyzer;
+
+import com.sun.classanalyzer.Klass.Method;
+
+import com.sun.tools.classfile.*;
+import com.sun.tools.classfile.Instruction.*;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeSet;
+
+/**
+ *
+ * @author Mandy Chung
+ */
+public class CodeAttributeParser {
+    private final ClassFileParser cfparser;
+    private final ConstantPool cpool;
+    private final ConstantPoolParser constantPoolParser;
+
+
+    static final Map<String, Set<Method>> runtimeReferences =
+            new HashMap<String, Set<Method>>();
+
+
+    CodeAttributeParser(ClassFileParser parser) {
+        this.cfparser = parser;
+        this.cpool = cfparser.classfile.constant_pool;
+        this.constantPoolParser = cfparser.constantPoolParser;
+    }
+
+    static boolean parseCodeAttribute = false; // by default don't parse code attribute
+    static void setParseCodeAttribute(boolean newValue) {
+        parseCodeAttribute = newValue;
+    }
+
+    void parse(Code_attribute attr, Klass.Method method) {
+        if (!parseCodeAttribute) {
+            return;
+        }
+
+        for (Instruction instr : attr.getInstructions()) {
+            try {
+                instr.accept(instructionVisitor, method);
+            } catch (ArrayIndexOutOfBoundsException e) {
+                throw new RuntimeException("error at or after byte " + instr.getPC());
+            }
+
+        }
+
+        if (attr.exception_table_langth > 0) {
+            for (int i = 0; i <
+                    attr.exception_table.length; i++) {
+                Code_attribute.Exception_data handler = attr.exception_table[i];
+                int catch_type = handler.catch_type;
+                if (catch_type > 0) {
+                    addMethodReference(catch_type, method);
+                }
+
+            }
+        }
+
+    }
+
+
+    private void addMethodReference(int index, Klass.Method m) {
+        String method = constantPoolParser.getMethodName(index);
+
+        if (method != null &&
+               (method.equals("java.lang.Class.forName") ||
+                method.equals("java.lang.Class.loadClass") ||
+                method.startsWith("java.util.ServiceLoader.load") ||
+                method.equals("sun.misc.Service.providers"))) {
+            Set<Method> refs = runtimeReferences.get(method);
+            if (refs == null) {
+                refs = new TreeSet<Method>();
+                runtimeReferences.put(method, refs);
+            }
+            refs.add(m);
+        }
+    }
+
+    Instruction.KindVisitor<Void, Klass.Method> instructionVisitor =
+            new Instruction.KindVisitor<Void, Klass.Method>() {
+
+                public Void visitNoOperands(Instruction instr, Klass.Method m) {
+                    return null;
+                }
+
+                public Void visitArrayType(Instruction instr, TypeKind kind, Klass.Method m) {
+                    return null;
+                }
+
+                public Void visitBranch(Instruction instr, int offset, Klass.Method m) {
+                    return null;
+                }
+
+                public Void visitConstantPoolRef(Instruction instr, int index, Klass.Method m) {
+                    addMethodReference(index, m);
+                    return null;
+                }
+
+                public Void visitConstantPoolRefAndValue(Instruction instr, int index, int value, Klass.Method m) {
+                    addMethodReference(index, m);
+                    return null;
+                }
+
+                public Void visitLocal(Instruction instr, int index, Klass.Method m) {
+                    return null;
+                }
+
+                public Void visitLocalAndValue(Instruction instr, int index, int value, Klass.Method m) {
+                    return null;
+                }
+
+                public Void visitLookupSwitch(Instruction instr, int default_, int npairs, int[] matches, int[] offsets, Klass.Method m) {
+                    return null;
+                }
+
+                public Void visitTableSwitch(Instruction instr, int default_, int low, int high, int[] offsets, Klass.Method m) {
+                    return null;
+                }
+
+                public Void visitValue(Instruction instr, int value, Klass.Method m) {
+                    return null;
+                }
+
+                public Void visitUnknown(Instruction instr, Klass.Method m) {
+                    return null;
+                }
+            };
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/make/modules/tools/src/com/sun/classanalyzer/ConstantPoolAnalyzer.java	Wed Jul 05 17:04:56 2017 +0200
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package com.sun.classanalyzer;
+
+/**
+ *
+ * @author Mandy Chung
+ */
+public class ConstantPoolAnalyzer {
+    public static void main(String[] args) throws Exception {
+        String jdkhome = null;
+
+        // process arguments
+        int i = 0;
+        while (i < args.length) {
+            String arg = args[i++];
+            if (arg.equals("-jdkhome")) {
+                if (i < args.length) {
+                    jdkhome = args[i++];
+                } else {
+                    usage();
+                }
+            }
+        }
+        if (jdkhome == null) {
+            usage();
+        }
+        ClassPath.setJDKHome(jdkhome);
+        ClassPath.parseAllClassFiles();
+    }
+
+    private static void usage() {
+        System.out.println("Usage: ConstantPoolAnalyzer <options>");
+        System.out.println("Options: ");
+        System.out.println("\t-jdkhome <JDK home> where all jars will be parsed");
+        System.out.println("\t-cpath <classpath> where classes and jars will be parsed");
+        System.exit(-1);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/make/modules/tools/src/com/sun/classanalyzer/ConstantPoolParser.java	Wed Jul 05 17:04:56 2017 +0200
@@ -0,0 +1,377 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+package com.sun.classanalyzer;
+
+import com.sun.tools.classfile.*;
+import com.sun.tools.classfile.ConstantPool.*;
+import static com.sun.tools.classfile.ConstantPool.*;
+
+/**
+ *
+ * @author Mandy Chung
+ */
+public class ConstantPoolParser {
+
+    private final ClassFileParser cfparser;
+    private final StringValueVisitor visitor;
+    private final ConstantPool cpool;
+
+    ConstantPoolParser(ClassFileParser parser) {
+        this.cfparser = parser;
+        this.cpool = cfparser.classfile.constant_pool;
+        this.visitor = new StringValueVisitor();
+    }
+
+    public String stringValue(CPInfo cpInfo) {
+        return visitor.visit(cpInfo);
+    }
+
+    public String stringValue(int constant_pool_index) {
+        try {
+            return stringValue(cpool.get(constant_pool_index));
+        } catch (ConstantPool.InvalidIndex e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    public void parseDependency() {
+        ConstantPool.Visitor<Integer, Void> v = new ConstantPool.Visitor<Integer, Void>() {
+
+            public Integer visitClass(CONSTANT_Class_info info, Void p) {
+                try {
+                    String classname = cfparser.checkClassName(info.getName());
+                    if (classname.isEmpty()) {
+                        return 1;
+                    }
+
+                    Klass from = cfparser.this_klass;
+                    Klass to = Klass.getKlass(classname);
+                    ResolutionInfo resInfo = ResolutionInfo.resolvedConstantPool(from, to, info.name_index);
+
+                    from.addDep(to, resInfo);
+                    to.addReferrer(from, resInfo);
+                } catch (ConstantPoolException ex) {
+                    throw new RuntimeException(ex);
+                }
+                return 1;
+            }
+
+            public Integer visitDouble(CONSTANT_Double_info info, Void p) {
+                // skip
+                return 2;
+            }
+
+            public Integer visitFieldref(CONSTANT_Fieldref_info info, Void p) {
+                // skip
+                return 1;
+            }
+
+            public Integer visitFloat(CONSTANT_Float_info info, Void p) {
+                // skip
+                return 1;
+            }
+
+            public Integer visitInteger(CONSTANT_Integer_info info, Void p) {
+                // skip
+                return 1;
+            }
+
+            public Integer visitInterfaceMethodref(CONSTANT_InterfaceMethodref_info info, Void p) {
+                // skip
+                return 1;
+            }
+
+            public Integer visitLong(CONSTANT_Long_info info, Void p) {
+                // skip
+                return 2;
+            }
+
+            public Integer visitNameAndType(CONSTANT_NameAndType_info info, Void p) {
+                // skip
+                return 1;
+            }
+
+            public Integer visitMethodref(CONSTANT_Methodref_info info, Void p) {
+                // skip
+                return 1;
+            }
+
+            public Integer visitString(CONSTANT_String_info info, Void p) {
+                // skip
+                return 1;
+            }
+
+            public Integer visitUtf8(CONSTANT_Utf8_info info, Void p) {
+                // skip
+                return 1;
+            }
+        };
+        int cpx = 1;
+        while (cpx < cpool.size()) {
+            try {
+                CPInfo cpInfo = cpool.get(cpx);
+                cpx += cpInfo.accept(v, null);
+            } catch (ConstantPool.InvalidIndex ex) {
+                throw new RuntimeException(ex);
+            }
+        }
+    }
+
+    int getTag(int index) {
+        try {
+            return cpool.get(index).getTag();
+        } catch (ConstantPoolException ex) {
+            throw new RuntimeException(ex);
+        }
+    }
+
+    String getDescriptor(int index) {
+        CPInfo cpInfo;
+        try {
+            cpInfo = cpool.get(index);
+        } catch (ConstantPoolException ex) {
+            throw new RuntimeException(ex);
+        }
+
+        int tag = cpInfo.getTag();
+        switch (tag) {
+            case CONSTANT_Methodref:
+            case CONSTANT_InterfaceMethodref:
+            case CONSTANT_Fieldref:
+                // simplify references within this class
+                CPRefInfo ref = (CPRefInfo) cpInfo;
+                try {
+                    return ref.getNameAndTypeInfo().getType();
+                } catch (ConstantPoolException ex) {
+                }
+        }
+        return stringValue(cpInfo);
+    }
+
+    String getMethodName(int index) {
+        try {
+            CPInfo cpInfo = cpool.get(index);
+            if (cpInfo.getTag() == CONSTANT_Methodref ||
+                    cpInfo.getTag() == CONSTANT_InterfaceMethodref) {
+
+                // simplify references within this class
+                CPRefInfo ref = (CPRefInfo) cpInfo;
+                String classname;
+                if (ref.class_index == cfparser.classfile.this_class) {
+                    classname = cfparser.this_klass.getClassName();
+                } else {
+                    classname = cfparser.checkClassName(ref.getClassName()).replace('/', '.');
+                }
+                String methodname = ref.getNameAndTypeInfo().getName();
+                return classname + "." + methodname;
+            } else {
+                return null;
+            }
+        } catch (InvalidIndex ex) {
+            throw new RuntimeException(ex);
+        } catch (ConstantPoolException ex) {
+            throw new RuntimeException(ex);
+        }
+
+    }
+
+    class StringValueVisitor implements ConstantPool.Visitor<String, Void> {
+
+        public StringValueVisitor() {
+        }
+
+        public String visit(CPInfo info) {
+            return info.accept(this, null);
+        }
+
+        public String visitClass(CONSTANT_Class_info info, Void p) {
+            return getCheckedName(info);
+        }
+
+        String getCheckedName(CONSTANT_Class_info info) {
+            try {
+                return checkName(info.getName());
+            } catch (ConstantPoolException e) {
+                throw new RuntimeException(e);
+            }
+        }
+
+        public String visitDouble(CONSTANT_Double_info info, Void p) {
+            return info.value + "d";
+        }
+
+        public String visitFieldref(CONSTANT_Fieldref_info info, Void p) {
+            return visitRef(info, p);
+        }
+
+        public String visitFloat(CONSTANT_Float_info info, Void p) {
+            return info.value + "f";
+        }
+
+        public String visitInteger(CONSTANT_Integer_info info, Void p) {
+            return String.valueOf(info.value);
+        }
+
+        public String visitInterfaceMethodref(CONSTANT_InterfaceMethodref_info info, Void p) {
+            return visitRef(info, p);
+        }
+
+        public String visitLong(CONSTANT_Long_info info, Void p) {
+            return info.value + "l";
+        }
+
+        public String visitNameAndType(CONSTANT_NameAndType_info info, Void p) {
+            return getCheckedName(info) + ":" + getType(info);
+        }
+
+        String getCheckedName(CONSTANT_NameAndType_info info) {
+            try {
+                return checkName(info.getName());
+            } catch (ConstantPoolException e) {
+                throw new RuntimeException(e);
+            }
+        }
+
+        String getType(CONSTANT_NameAndType_info info) {
+            try {
+                return info.getType();
+            } catch (ConstantPoolException e) {
+                throw new RuntimeException(e);
+            }
+        }
+
+        public String visitMethodref(CONSTANT_Methodref_info info, Void p) {
+            return visitRef(info, p);
+        }
+
+        public String visitString(CONSTANT_String_info info, Void p) {
+            try {
+                int string_index = info.string_index;
+                return cpool.getUTF8Info(string_index).accept(this, p);
+            } catch (ConstantPoolException e) {
+                throw new RuntimeException(e);
+            }
+        }
+
+        public String visitUtf8(CONSTANT_Utf8_info info, Void p) {
+            String s = info.value;
+            StringBuilder sb = new StringBuilder();
+            for (int i = 0; i < s.length(); i++) {
+                char c = s.charAt(i);
+                switch (c) {
+                    case '\t':
+                        sb.append('\\').append('t');
+                        break;
+                    case '\n':
+                        sb.append('\\').append('n');
+                        break;
+                    case '\r':
+                        sb.append('\\').append('r');
+                        break;
+                    case '\"':
+                        sb.append('\\').append('\"');
+                        break;
+                    default:
+                        sb.append(c);
+                }
+            }
+            return sb.toString();
+        }
+
+        String visitRef(CPRefInfo info, Void p) {
+            String cn = getCheckedClassName(info);
+            String nat;
+            try {
+                nat = info.getNameAndTypeInfo().accept(this, p);
+            } catch (ConstantPoolException e) {
+                nat = e.getMessage();
+            }
+            return cn + "." + nat;
+        }
+
+        String getCheckedClassName(CPRefInfo info) {
+            try {
+                return checkName(info.getClassName());
+            } catch (ConstantPoolException e) {
+                throw new RuntimeException(e);
+            }
+        }
+    }
+    /* If name is a valid binary name, return it; otherwise quote it. */
+
+    private static String checkName(String name) {
+        if (name == null) {
+            return "null";
+        }
+
+        int len = name.length();
+        if (len == 0) {
+            return "\"\"";
+        }
+
+        int cc = '/';
+        int cp;
+        for (int k = 0; k < len; k += Character.charCount(cp)) {
+            cp = name.codePointAt(k);
+            if ((cc == '/' && !Character.isJavaIdentifierStart(cp)) || (cp != '/' && !Character.isJavaIdentifierPart(cp))) {
+                return "\"" + name + "\"";
+            }
+            cc = cp;
+        }
+        return name;
+    }
+
+    String tagName(int index) {
+        try {
+            int tag = cpool.get(index).getTag();
+            switch (tag) {
+                case CONSTANT_Utf8:
+                    return "Utf8";
+                case CONSTANT_Integer:
+                    return "int";
+                case CONSTANT_Float:
+                    return "float";
+                case CONSTANT_Long:
+                    return "long";
+                case CONSTANT_Double:
+                    return "double";
+                case CONSTANT_Class:
+                    return "class";
+                case CONSTANT_String:
+                    return "String";
+                case CONSTANT_Fieldref:
+                    return "Field";
+                case CONSTANT_Methodref:
+                    return "Method";
+                case CONSTANT_InterfaceMethodref:
+                    return "InterfaceMethod";
+                case CONSTANT_NameAndType:
+                    return "NameAndType";
+                default:
+                    return "(unknown tag)";
+            }
+        } catch (InvalidIndex e) {
+            throw new RuntimeException(e);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/make/modules/tools/src/com/sun/classanalyzer/DependencyConfig.java	Wed Jul 05 17:04:56 2017 +0200
@@ -0,0 +1,99 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+package com.sun.classanalyzer;
+
+import java.io.BufferedReader;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.util.List;
+
+/**
+ * Config file specifying additional dependency
+ * Each line consists of:
+ * <tag> <classname> -> <value>
+ * where <tag> can be:
+ *    @ClassForName and <value> is its dependency
+ *    @Provider and <value> is the service name
+ *    @Providers and <value> is the list of the service names
+ *
+ * @author Mandy Chung
+ */
+public class DependencyConfig {
+    private DependencyConfig() {
+    }
+
+    static void parse(List<String> configs) throws IOException {
+        for (String s : configs) {
+            parse(s);
+        }
+    }
+
+    private static void parse(String config) throws IOException {
+        // parse configuration file
+        FileInputStream in = new FileInputStream(config);
+        try {
+            BufferedReader reader = new BufferedReader(new InputStreamReader(in));
+            String line;
+            int lineNumber = 0;
+            String type = null;
+            while ((line = reader.readLine()) != null) {
+                lineNumber++;
+                line = line.trim();
+                if (line.length() == 0 || line.charAt(0) == '#') {
+                    continue;
+                }
+                if (line.charAt(0) == '@') {
+                    if (AnnotatedDependency.isValidType(line)) {
+                        type = line;
+                        continue;
+                    } else {
+                        throw new RuntimeException(config + ", line " +
+                            lineNumber + ", invalid annotation type.");
+                    }
+                }
+                String[] s = line.split("\\s+");
+                if (s.length < 3 || !s[1].equals("->")) {
+                    throw new RuntimeException(config + ", line " +
+                            lineNumber + ", is malformed");
+                }
+                String classname = s[0].trim();
+                String value = s[2].trim();
+
+                Klass k = Klass.findKlass(classname);
+                if (k == null) {
+                    // System.out.println("Warning: " + classname + " cannot be found");
+                    continue;
+                }
+                AnnotatedDependency dep = AnnotatedDependency.newAnnotatedDependency(type, value, k);
+                if (dep == null) {
+                    throw new RuntimeException(config + ", line " +
+                            lineNumber + ", is malformed. Fail to construct the dependency.");
+                }
+            }
+
+        } finally {
+            in.close();
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/make/modules/tools/src/com/sun/classanalyzer/Klass.java	Wed Jul 05 17:04:56 2017 +0200
@@ -0,0 +1,357 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ *
+ */
+
+package com.sun.classanalyzer;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.SortedMap;
+import java.util.TreeMap;
+import java.util.TreeSet;
+
+import com.sun.tools.classfile.AccessFlags;
+
+/**
+ *
+ * @author Mandy Chung
+ */
+public class Klass implements Comparable<Klass> {
+    private final String classname;
+    private final String packagename;
+    private Module module;
+    private boolean isJavaLangObject;
+    private String[] paths;
+    private Map<String, Set<Method>> methods;
+    private AccessFlags accessFlags;
+    private long filesize;
+
+    private SortedMap<Klass, Set<ResolutionInfo>> deps;
+    private SortedMap<Klass, Set<ResolutionInfo>> referrers;
+    private List<AnnotatedDependency> annotatedDeps;
+    private Set<String> classForNameRefs;
+
+    private Klass(String classname) {
+        this.classname = classname;
+        this.paths = classname.replace('.', '/').split("/");
+        this.isJavaLangObject = classname.equals("java.lang.Object");
+        this.deps = new TreeMap<Klass, Set<ResolutionInfo>>();
+        this.referrers = new TreeMap<Klass, Set<ResolutionInfo>>();
+        this.methods = new HashMap<String, Set<Method>>();
+        this.annotatedDeps = new ArrayList<AnnotatedDependency>();
+        this.classForNameRefs = new TreeSet<String>();
+
+        int pos = classname.lastIndexOf('.');
+        this.packagename = (pos > 0) ? classname.substring(0, pos) : "<unnamed>";
+    }
+
+    String getBasename() {
+        return paths[paths.length - 1];
+    }
+
+    String getClassName() {
+        return classname;
+    }
+
+    String getPackageName() {
+        return packagename;
+    }
+
+    String getClassFilePathname() {
+        StringBuilder sb = new StringBuilder(paths[0]);
+        for (int i = 1; i < paths.length; i++) {
+            String p = paths[i];
+            sb.append(File.separator).append(p);
+        }
+        return sb.append(".class").toString();
+    }
+
+    boolean isPublic() {
+        return accessFlags == null || accessFlags.is(AccessFlags.ACC_PUBLIC);
+    }
+
+    Module getModule() {
+        return module;
+    }
+
+    void setModule(Module m) {
+        if (module != null) {
+            throw new RuntimeException("Module for " + this + " already set");
+        }
+        this.module = m;
+    }
+
+    Set<Klass> getReferencedClasses() {
+        return deps.keySet();
+    }
+
+    Set<Klass> getReferencingClasses() {
+        return referrers.keySet();
+    }
+
+    void setAccessFlags(int flags) {
+        this.accessFlags = new AccessFlags(flags);
+    }
+
+    void setFileSize(long size) {
+        this.filesize = size;
+    }
+
+    long getFileSize() {
+        return this.filesize;
+    }
+
+    boolean exists() {
+        return filesize > 0;
+    }
+
+    boolean skip(Klass k) {
+        // skip if either class is a root or same class
+        return k.isJavaLangObject || this == k || k.classname.equals(classname);
+    }
+
+    void addDep(Method callee, ResolutionInfo resInfo) {
+        addDep(callee.getKlass(), resInfo);
+    }
+
+    void addDep(Klass ref, ResolutionInfo ri) {
+        if (skip(ref)) {
+            return;
+        }
+        Set<ResolutionInfo> resInfos;
+        if (!deps.containsKey(ref)) {
+            resInfos = new TreeSet<ResolutionInfo>();
+            deps.put(ref, resInfos);
+        } else {
+            resInfos = deps.get(ref);
+        }
+        resInfos.add(ri);
+    }
+
+    void addReferrer(Method caller, ResolutionInfo resInfo) {
+        addReferrer(caller.getKlass(), resInfo);
+    }
+
+    void addReferrer(Klass k, ResolutionInfo ri) {
+        if (skip(k)) {
+            return;
+        }
+        Set<ResolutionInfo> resInfos;
+        if (!referrers.containsKey(k)) {
+            resInfos = new TreeSet<ResolutionInfo>();
+            referrers.put(k, resInfos);
+        } else {
+            resInfos = referrers.get(k);
+        }
+        resInfos.add(ri);
+    }
+
+    Method getMethod(String name) {
+        return getMethod(name, "");
+    }
+
+    Method getMethod(String name, String signature) {
+        Set<Method> set;
+        if (methods.containsKey(name)) {
+            set = methods.get(name);
+        } else {
+            set = new TreeSet<Method>();
+            methods.put(name, set);
+        }
+
+        for (Method m : set) {
+            if (m.getName().equals(name) && m.getSignature().equals(signature)) {
+                return m;
+            }
+        }
+        Method m = new Method(this, name, signature);
+        set.add(m);
+        return m;
+    }
+
+    @Override
+    public String toString() {
+        return classname;
+    }
+
+    @Override
+    public int compareTo(Klass o) {
+        return classname.compareTo(o.classname);
+    }
+
+    void addAnnotatedDep(AnnotatedDependency dep) {
+        annotatedDeps.add(dep);
+    }
+
+    void addClassForNameReference(String method) {
+        classForNameRefs.add(method);
+    }
+
+    List<AnnotatedDependency> getAnnotatedDeps() {
+        return annotatedDeps;
+    }
+
+    private static Map<String, Klass> classes = new TreeMap<String, Klass>();
+    static Set<Klass> getAllClasses() {
+        return new TreeSet<Klass>(classes.values());
+    }
+
+    static Klass findKlassFromPathname(String filename) {
+        String name = filename;
+        if (filename.endsWith(".class")) {
+            name = filename.substring(0, filename.length() - 6);
+        }
+
+        // trim ".class"
+        name = name.replace('/', '.');
+        for (Klass k : classes.values()) {
+            if (name.endsWith(k.getClassName())) {
+                return k;
+            }
+        }
+        return null;
+    }
+
+    static Klass findKlass(String classname) {
+        return classes.get(classname);
+    }
+
+    static Klass getKlass(String name) {
+        Klass k;
+        String classname = name.replace('/', '.');
+        if (classname.charAt(classname.length() - 1) == ';') {
+            classname = classname.substring(0, classname.length() - 1);
+        }
+        if (classes.containsKey(classname)) {
+            k = classes.get(classname);
+        } else {
+            k = new Klass(classname);
+            classes.put(classname, k);
+        }
+        return k;
+    }
+
+    public class Method implements Comparable<Method> {
+
+        private final Klass k;
+        private final String method;
+        private final String signature;
+        private long codeLength;
+        // non-primitive types only
+        private final List<Klass> argTypes;
+        private final Klass returnType;
+        boolean isAbstract = false;
+        boolean marked = false;
+
+        public Method(Klass k, String method, String signature) {
+            this(k, method, signature, null, null);
+        }
+
+        public Method(Klass k, String method, String signature, Klass returnType, List<Klass> argTypes) {
+            this.k = k;
+            this.method = method;
+            this.signature = signature;
+            this.argTypes = argTypes;
+            this.returnType = returnType;
+            this.codeLength = 0;
+        }
+
+        public Klass getKlass() {
+            return k;
+        }
+
+        public String getName() {
+            return method;
+        }
+
+        public String getSignature() {
+            return signature;
+        }
+
+        public Klass getReturnType() {
+            return returnType;
+        }
+
+        public List<Klass> argTypes() {
+            return argTypes;
+        }
+
+        public void setCodeLength(long len) {
+            this.codeLength = len;
+        }
+
+        public long getCodeLength() {
+            return codeLength;
+        }
+
+        @Override
+        public boolean equals(Object o) {
+            if (o instanceof Method) {
+                return compareTo((Method) o) == 0;
+            } else {
+                return false;
+            }
+        }
+
+        @Override
+        public int hashCode() {
+            int hash = 3;
+            hash = 71 * hash + (this.k != null ? this.k.hashCode() : 0);
+            hash = 71 * hash + (this.method != null ? this.method.hashCode() : 0);
+            return hash;
+        }
+
+        @Override
+        public String toString() {
+            if (signature.isEmpty()) {
+                return k.classname + "." + method;
+            } else {
+                return signature;
+            }
+        }
+
+        public String toHtmlString() {
+            return toString().replace("<", "&lt;").replace(">", "&gt;");
+        }
+
+        boolean isClinit() {
+            return method.equals("<clinit>");
+        }
+
+        public int compareTo(Method m) {
+            if (k == m.getKlass()) {
+                if (method.equals(m.method)) {
+                    return signature.compareTo(m.signature);
+                } else {
+                    return method.compareTo(m.method);
+                }
+            } else {
+                return k.compareTo(m.getKlass());
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/make/modules/tools/src/com/sun/classanalyzer/Module.java	Wed Jul 05 17:04:56 2017 +0200
@@ -0,0 +1,693 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ *
+ */
+package com.sun.classanalyzer;
+
+import com.sun.classanalyzer.AnnotatedDependency.OptionalDependency;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.ArrayDeque;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Deque;
+import java.util.HashSet;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeMap;
+import java.util.TreeSet;
+
+/**
+ *
+ * @author Mandy Chung
+ */
+public class Module implements Comparable<Module> {
+
+    private static Map<String, Module> modules = new LinkedHashMap<String, Module>();
+
+    public static Module addModule(ModuleConfig config) {
+        String name = config.module;
+        if (modules.containsKey(name)) {
+            throw new RuntimeException("module \"" + name + "\" already exists");
+        }
+
+        Module m = new Module(config);
+        modules.put(name, m);
+        return m;
+    }
+
+    public static Module findModule(String name) {
+        return modules.get(name);
+    }
+
+    static Collection<Module> getAllModules() {
+        return Collections.unmodifiableCollection(modules.values());
+    }
+    private final String name;
+    private final ModuleConfig config;
+    private final Set<Klass> classes;
+    private final Set<ResourceFile> resources;
+    private final Set<Reference> unresolved;
+    private final Set<Dependency> dependents;
+    private final Map<String, PackageInfo> packages;
+    private final Set<Module> members;
+    private Module group;
+    private boolean isBaseModule;
+
+    private Module(ModuleConfig config) {
+        this.name = config.module;
+        this.isBaseModule = config.isBase;
+        this.classes = new TreeSet<Klass>();
+        this.resources = new TreeSet<ResourceFile>();
+        this.config = config;
+        this.unresolved = new HashSet<Reference>();
+        this.dependents = new TreeSet<Dependency>();
+        this.packages = new TreeMap<String, PackageInfo>();
+        this.members = new TreeSet<Module>();
+        this.group = this; // initialize to itself
+    }
+
+    String name() {
+        return name;
+    }
+
+    Module group() {
+        return group;
+    }
+
+    boolean isBase() {
+        return isBaseModule;
+    }
+
+    Set<Module> members() {
+        return members;
+    }
+
+    boolean contains(Klass k) {
+        return k != null && classes.contains(k);
+    }
+
+    boolean isEmpty() {
+        return classes.isEmpty() && resources.isEmpty();
+    }
+
+    /**
+     * Returns an Iterable of Dependency, only one for each dependent
+     * module of the strongest dependency (i.e.
+     * hard static > hard dynamic > optional static > optional dynamic
+     */
+    Iterable<Dependency> dependents() {
+        Map<Module, Dependency> deps = new LinkedHashMap<Module, Dependency>();
+        for (Dependency dep : dependents) {
+            Dependency d = deps.get(dep.module);
+            if (d == null || dep.compareTo(d) > 0) {
+                deps.put(dep.module, dep);
+            }
+        }
+        return deps.values();
+    }
+
+    @Override
+    public int compareTo(Module o) {
+        if (o == null) {
+            return -1;
+        }
+        return name.compareTo(o.name);
+    }
+
+    @Override
+    public String toString() {
+        return name;
+    }
+
+    void addKlass(Klass k) {
+        classes.add(k);
+        k.setModule(this);
+
+        // update package statistics
+        String pkg = k.getPackageName();
+        PackageInfo pkginfo = packages.get(pkg);
+        if (pkginfo == null) {
+            pkginfo = new PackageInfo(pkg);
+            packages.put(pkg, pkginfo);
+        }
+        if (k.exists()) {
+            // only count the class that is parsed
+            pkginfo.add(k.getFileSize());
+        }
+    }
+
+    void addResource(ResourceFile res) {
+        resources.add(res);
+        res.setModule(this);
+    }
+
+    void processRootsAndReferences() {
+        // start with the root set
+        Deque<Klass> pending = new ArrayDeque<Klass>();
+        for (Klass k : Klass.getAllClasses()) {
+            if (k.getModule() != null) {
+                continue;
+            }
+            String classname = k.getClassName();
+            if (config.matchesRoot(classname) && !config.isExcluded(classname)) {
+                addKlass(k);
+                pending.add(k);
+            }
+        }
+
+        // follow all references
+        Klass k;
+        while ((k = pending.poll()) != null) {
+            if (!classes.contains(k)) {
+                addKlass(k);
+            }
+            for (Klass other : k.getReferencedClasses()) {
+                Module otherModule = other.getModule();
+                if (otherModule != null && otherModule != this) {
+                    // this module is dependent on otherModule
+                    addDependency(k, other);
+                    continue;
+                }
+
+                if (!classes.contains(other)) {
+                    if (config.isExcluded(other.getClassName())) {
+                        // reference to an excluded class
+                        unresolved.add(new Reference(k, other));
+                    } else {
+                        pending.add(other);
+                    }
+                }
+            }
+        }
+
+        // add other matching classes that don't require dependency analysis
+        for (Klass c : Klass.getAllClasses()) {
+            if (c.getModule() == null) {
+                String classname = c.getClassName();
+                if (config.matchesIncludes(classname) && !config.isExcluded(classname)) {
+                    addKlass(c);
+                    // dependencies
+                    for (Klass other : c.getReferencedClasses()) {
+                        Module otherModule = other.getModule();
+                        if (otherModule == null) {
+                            unresolved.add(new Reference(c, other));
+                        } else {
+                            if (otherModule != this) {
+                                // this module is dependent on otherModule
+                                addDependency(c, other);
+                            }
+                        }
+                    }
+                }
+            }
+        }
+
+
+        // add other matching classes that don't require dependency analysis
+        for (ResourceFile res : ResourceFile.getAllResources()) {
+            if (res.getModule() == null) {
+                String name = res.getName();
+                if (config.matchesIncludes(name) && !config.isExcluded(name)) {
+                    addResource(res);
+                }
+            }
+        }
+    }
+
+    void addDependency(Klass from, Klass to) {
+        Dependency dep = new Dependency(from, to);
+        dependents.add(dep);
+    }
+
+    void fixupDependencies() {
+        // update dependencies for classes that were allocated to modules after
+        // this module was processed.
+        for (Reference ref : unresolved) {
+            Module m = ref.referree().getModule();
+            if (m == null || m != this) {
+                addDependency(ref.referrer, ref.referree);
+            }
+        }
+
+        fixupAnnotatedDependencies();
+    }
+
+    private void fixupAnnotatedDependencies() {
+        // add dependencies that this klass may depend on due to the AnnotatedDependency
+        dependents.addAll(AnnotatedDependency.getDependencies(this));
+    }
+
+    boolean isModuleDependence(Klass k) {
+        Module m = k.getModule();
+        return m == null || (!classes.contains(k) && !m.isBase());
+    }
+
+    Module getModuleDependence(Klass k) {
+        if (isModuleDependence(k)) {
+            Module m = k.getModule();
+            if (group == this && m != null) {
+                // top-level module
+                return m.group;
+            } else {
+                return m;
+            }
+        }
+        return null;
+    }
+
+    <P> void visit(Set<Module> visited, Visitor<P> visitor, P p) {
+        if (!visited.contains(this)) {
+            visited.add(this);
+            visitor.preVisit(this, p);
+            for (Module m : members) {
+                m.visit(visited, visitor, p);
+                visitor.postVisit(this, m, p);
+            }
+        } else {
+            throw new RuntimeException("Cycle detected: module " + this.name);
+        }
+    }
+
+    void addMember(Module m) {
+        // merge class list
+        for (Klass k : m.classes) {
+            classes.add(k);
+        }
+
+        // merge resource list
+        for (ResourceFile res : m.resources) {
+            resources.add(res);
+        }
+
+        // merge the package statistics
+        for (PackageInfo pinfo : m.getPackageInfos()) {
+            String packageName = pinfo.pkgName;
+            PackageInfo pkginfo = packages.get(packageName);
+            if (pkginfo == null) {
+                pkginfo = new PackageInfo(packageName);
+                packages.put(packageName, pkginfo);
+            }
+            pkginfo.add(pinfo);
+        }
+    }
+
+    static void buildModuleMembers() {
+        // set up module member relationship
+        for (Module m : modules.values()) {
+            m.group = m; // initialize to itself
+            for (String name : m.config.members()) {
+                Module member = modules.get(name);
+                if (member == null) {
+                    throw new RuntimeException("module \"" + name + "\" doesn't exist");
+                }
+                m.members.add(member);
+            }
+        }
+
+        // set up the top-level module
+        Visitor<Module> groupSetter = new Visitor<Module>() {
+
+            public void preVisit(Module m, Module p) {
+                m.group = p;
+                if (p.isBaseModule) {
+                    // all members are also base
+                    m.isBaseModule = true;
+                }
+            }
+
+            public void postVisit(Module m, Module child, Module p) {
+                // nop - breadth-first search
+            }
+        };
+
+        // propagate the top-level module to all its members
+        for (Module p : modules.values()) {
+            for (Module m : p.members) {
+                if (m.group == m) {
+                    m.visit(new TreeSet<Module>(), groupSetter, p);
+                }
+            }
+        }
+
+        Visitor<Module> mergeClassList = new Visitor<Module>() {
+
+            public void preVisit(Module m, Module p) {
+                // nop - depth-first search
+            }
+
+            public void postVisit(Module m, Module child, Module p) {
+                m.addMember(child);
+            }
+        };
+
+        Set<Module> visited = new TreeSet<Module>();
+        for (Module m : modules.values()) {
+            if (m.group() == m) {
+                if (m.members().size() > 0) {
+                    // merge class list from all its members
+                    m.visit(visited, mergeClassList, m);
+                }
+
+                // clear the dependencies before fixup
+                m.dependents.clear();
+
+                // fixup dependencies
+                for (Klass k : m.classes) {
+                    for (Klass other : k.getReferencedClasses()) {
+                        if (m.isModuleDependence(other)) {
+                            // this module is dependent on otherModule
+                            m.addDependency(k, other);
+                        }
+                    }
+                }
+
+                // add dependencies that this klass may depend on due to the AnnotatedDependency
+                m.fixupAnnotatedDependencies();
+            }
+        }
+    }
+
+    class PackageInfo implements Comparable {
+
+        final String pkgName;
+        int count;
+        long filesize;
+
+        PackageInfo(String name) {
+            this.pkgName = name;
+            this.count = 0;
+            this.filesize = 0;
+        }
+
+        void add(PackageInfo pkg) {
+            this.count += pkg.count;
+            this.filesize += pkg.filesize;
+        }
+
+        void add(long size) {
+            count++;
+            filesize += size;
+
+        }
+
+        @Override
+        public int compareTo(Object o) {
+            return pkgName.compareTo(((PackageInfo) o).pkgName);
+        }
+    }
+
+    Set<PackageInfo> getPackageInfos() {
+        return new TreeSet<PackageInfo>(packages.values());
+    }
+
+    void printSummaryTo(String output) throws IOException {
+        PrintWriter writer = new PrintWriter(output);
+        try {
+            long total = 0L;
+            int count = 0;
+            writer.format("%10s\t%10s\t%s\n", "Bytes", "Classes", "Package name");
+            for (String pkg : packages.keySet()) {
+                PackageInfo info = packages.get(pkg);
+                if (info.count > 0) {
+                    writer.format("%10d\t%10d\t%s\n", info.filesize, info.count, pkg);
+                    total += info.filesize;
+                    count += info.count;
+                }
+            }
+
+            writer.format("\nTotal: %d bytes (uncompressed) %d classes\n", total, count);
+        } finally {
+            writer.close();
+        }
+
+    }
+
+    void printClassListTo(String output) throws IOException {
+        // no file created if the module doesn't have any class
+        if (classes.isEmpty()) {
+            return;
+        }
+
+        PrintWriter writer = new PrintWriter(output);
+        try {
+            for (Klass c : classes) {
+                if (c.exists()) {
+                    writer.format("%s\n", c.getClassFilePathname());
+                } else {
+                    trace("%s in module %s missing\n", c, this);
+                }
+            }
+
+        } finally {
+            writer.close();
+        }
+    }
+
+    void printResourceListTo(String output) throws IOException {
+        // no file created if the module doesn't have any resource file
+        if (resources.isEmpty()) {
+            return;
+        }
+
+        PrintWriter writer = new PrintWriter(output);
+        try {
+            for (ResourceFile res : resources) {
+                writer.format("%s\n", res.getPathname());
+            }
+        } finally {
+            writer.close();
+        }
+    }
+
+    void printDependenciesTo(String output, boolean showDynamic) throws IOException {
+        // no file created if the module doesn't have any class
+        if (classes.isEmpty()) {
+            return;
+        }
+
+        PrintWriter writer = new PrintWriter(output);
+        try {
+            // classes that this klass may depend on due to the AnnotatedDependency
+            Map<Reference, Set<AnnotatedDependency>> annotatedDeps = AnnotatedDependency.getReferences(this);
+
+            for (Klass klass : classes) {
+                Set<Klass> references = klass.getReferencedClasses();
+                for (Klass other : references) {
+                    String classname = klass.getClassName();
+                    boolean optional = OptionalDependency.isOptional(klass, other);
+                    if (optional) {
+                        classname = "[optional] " + classname;
+                    }
+
+                    Module m = getModuleDependence(other);
+                    if (m != null || other.getModule() == null) {
+                        writer.format("%-40s -> %s (%s)", classname, other, m);
+                        Reference ref = new Reference(klass, other);
+                        if (annotatedDeps.containsKey(ref)) {
+                            for (AnnotatedDependency ad : annotatedDeps.get(ref)) {
+                                writer.format(" %s", ad.getTag());
+                            }
+                            // printed; so remove the dependency from the annotated deps list
+                            annotatedDeps.remove(ref);
+                        }
+                        writer.format("\n");
+                    }
+                }
+            }
+
+
+            // print remaining dependencies specified in AnnotatedDependency list
+            if (annotatedDeps.size() > 0) {
+                for (Map.Entry<Reference, Set<AnnotatedDependency>> entry : annotatedDeps.entrySet()) {
+                    Reference ref = entry.getKey();
+                    Module m = getModuleDependence(ref.referree);
+                    if (m != null || ref.referree.getModule() == null) {
+                        String classname = ref.referrer.getClassName();
+                        boolean optional = true;
+                        boolean dynamic = true;
+                        String tag = "";
+                        for (AnnotatedDependency ad : entry.getValue()) {
+                            if (optional && !ad.isOptional()) {
+                                optional = false;
+                                tag = ad.getTag();
+                            }
+                            if (!ad.isDynamic()) {
+                                dynamic = false;
+                            }
+                        }
+                        if (!showDynamic && optional && dynamic) {
+                            continue;
+                        }
+                        if (optional) {
+                            if (dynamic) {
+                                classname = "[dynamic] " + classname;
+                            } else {
+                                classname = "[optional] " + classname;
+                            }
+                        }
+                        writer.format("%-40s -> %s (%s) %s%n", classname, ref.referree, m, tag);
+                    }
+                }
+            }
+
+        } finally {
+            writer.close();
+        }
+    }
+
+    static class Dependency implements Comparable<Dependency> {
+
+        final Module module;
+        final boolean optional;
+        final boolean dynamic;
+
+        Dependency(Klass from, Klass to) {
+            // static dependency
+            this.module = to.getModule() != null ? to.getModule().group() : null;
+            this.optional = OptionalDependency.isOptional(from, to);
+            this.dynamic = false;
+        }
+
+        Dependency(Module m, boolean optional, boolean dynamic) {
+            this.module = m != null ? m.group() : null;
+            this.optional = optional;
+            this.dynamic = dynamic;
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (!(obj instanceof Dependency)) {
+                return false;
+            }
+            if (this == obj) {
+                return true;
+            }
+
+            Dependency d = (Dependency) obj;
+            if (this.module != d.module) {
+                return false;
+            } else {
+                return this.optional == d.optional && this.dynamic == d.dynamic;
+            }
+        }
+
+        @Override
+        public int hashCode() {
+            int hash = 3;
+            hash = 19 * hash + (this.module != null ? this.module.hashCode() : 0);
+            hash = 19 * hash + (this.optional ? 1 : 0);
+            hash = 19 * hash + (this.dynamic ? 1 : 0);
+            return hash;
+        }
+
+        @Override
+        public int compareTo(Dependency d) {
+            if (this.equals(d)) {
+                return 0;
+            }
+
+            // Hard static > hard dynamic > optional static > optional dynamic
+            if (this.module == d.module) {
+                if (this.optional == d.optional) {
+                    return this.dynamic ? -1 : 1;
+                } else {
+                    return this.optional ? -1 : 1;
+                }
+            } else if (this.module != null && d.module != null) {
+                return (this.module.compareTo(d.module));
+            } else {
+                return (this.module == null) ? -1 : 1;
+            }
+        }
+
+        @Override
+        public String toString() {
+            String s = module.name();
+            if (dynamic && optional) {
+                s += " (dynamic)";
+            } else if (optional) {
+                s += " (optional)";
+            }
+            return s;
+        }
+    }
+
+    static class Reference implements Comparable<Reference> {
+
+        private final Klass referrer, referree;
+
+        Reference(Klass referrer, Klass referree) {
+            this.referrer = referrer;
+            this.referree = referree;
+        }
+
+        Klass referrer() {
+            return referrer;
+        }
+
+        Klass referree() {
+            return referree;
+        }
+
+        @Override
+        public int hashCode() {
+            return referrer.hashCode() ^ referree.hashCode();
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (!(obj instanceof Reference)) {
+                return false;
+            }
+            if (this == obj) {
+                return true;
+            }
+
+            Reference r = (Reference) obj;
+            return (this.referrer.equals(r.referrer) &&
+                    this.referree.equals(r.referree));
+        }
+
+        @Override
+        public int compareTo(Reference r) {
+            int ret = referrer.compareTo(r.referrer);
+            if (ret == 0) {
+                ret = referree.compareTo(r.referree);
+            }
+            return ret;
+        }
+    }
+
+    interface Visitor<P> {
+
+        public void preVisit(Module m, P param);
+
+        public void postVisit(Module m, Module child, P param);
+    }
+    private static boolean traceOn = System.getProperty("classanalyzer.debug") != null;
+
+    private static void trace(String format, Object... params) {
+        System.err.format(format, params);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/make/modules/tools/src/com/sun/classanalyzer/ModuleConfig.java	Wed Jul 05 17:04:56 2017 +0200
@@ -0,0 +1,562 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+package com.sun.classanalyzer;
+
+import java.io.BufferedReader;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Set;
+import java.util.TreeSet;
+import java.util.regex.Pattern;
+
+/**
+ *
+ * @author Mandy Chung
+ */
+public class ModuleConfig {
+
+    private static String baseModuleName = "base";
+    private final Set<String> roots;
+    private final Set<String> includes;
+    private final Filter filter;
+    private List<String> members;
+    final String module;
+    final boolean isBase;
+
+    private ModuleConfig(String name) throws IOException {
+        this.roots = new TreeSet<String>();
+        this.includes = new TreeSet<String>();
+        this.module = name;
+        this.isBase = name.equals(baseModuleName);
+        this.filter = new Filter(this);
+    }
+
+    List<String> members() {
+        if (members == null) {
+            members = new LinkedList<String>();
+
+            for (String s : includes) {
+                if (!s.contains("*") && Module.findModule(s) != null) {
+                    // module member
+                    members.add(s);
+                }
+            }
+        }
+        return members;
+    }
+
+    boolean matchesRoot(String name) {
+        for (String pattern : roots) {
+            if (matches(name, pattern)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    boolean matchesIncludes(String name) {
+        for (String pattern : includes) {
+            if (matches(name, pattern)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    boolean isExcluded(String name) {
+        return filter.isExcluded(name);
+    }
+
+    boolean matchesPackage(String packageName, String pattern) {
+        int pos = pattern.lastIndexOf('.');
+        String pkg = pos > 0 ? pattern.substring(0, pos) : "<unnamed>";
+        return packageName.equals(pkg);
+    }
+
+
+    boolean matches(String name, String pattern) {
+        if (pattern.contains("**") && !pattern.endsWith("**")) {
+            throw new UnsupportedOperationException("Not yet implemented");
+        }
+
+        String javaName = name;
+
+        boolean isResourceFile = name.indexOf('/') >= 0;
+        if (isResourceFile) {
+            // it's a resource file; convert the name as a java
+            javaName = name.replace('/', '.');
+        }
+        if (pattern.indexOf('/') < 0) {
+            // if the pattern doesn't contain '/
+            return matchesJavaName(javaName, pattern);
+        } else {
+            if (isResourceFile) {
+                // the pattern is for matching resource file
+                return matchesNameWithSlash(name, pattern);
+            } else {
+                return false;
+            }
+        }
+    }
+
+    boolean matchesJavaName(String name, String pattern) {
+        int pos = name.lastIndexOf('.');
+        String packageName = pos > 0 ? name.substring(0, pos) : "<unnamed>";
+        if (pattern.endsWith("**")) {
+            String p = pattern.substring(0, pattern.length() - 2);
+            return name.startsWith(p);
+        } else if (pattern.endsWith("*") && pattern.indexOf('*') == pattern.lastIndexOf('*')) {
+            if (matchesPackage(packageName, pattern)) {
+                // package name has to be exact match
+                String p = pattern.substring(0, pattern.length() - 1);
+                return name.startsWith(p);
+            } else {
+                return false;
+            }
+        } else if (pattern.contains("*")) {
+            String basename = pos > 0 ? name.substring(pos + 1, name.length()) : name;
+            pos = pattern.indexOf('*');
+            String prefix = pattern.substring(0, pos);
+            String suffix = pattern.substring(pos + 1, pattern.length());
+            if (name.startsWith(prefix) && matchesPackage(packageName, prefix)) {
+                // package name has to be exact match
+                if (suffix.contains("*")) {
+                    return name.matches(convertToRegex(pattern));
+                } else {
+                    return basename.endsWith(suffix);
+                }
+            } else {
+                // we don't support wildcard be used in the package name
+                return false;
+            }
+        } else {
+            // exact match or inner class
+            return name.equals(pattern) || name.startsWith(pattern + "$");
+        }
+    }
+
+    boolean matchesNameWithSlash(String name, String pattern) {
+        if (pattern.endsWith("**")) {
+            String p = pattern.substring(0, pattern.length() - 2);
+            return name.startsWith(p);
+        } else if (pattern.contains("*")) {
+            int pos = pattern.indexOf('*');
+            String prefix = pattern.substring(0, pos);
+            String suffix = pattern.substring(pos + 1, pattern.length());
+            String tail = name.substring(pos, name.length());
+
+            if (!name.startsWith(prefix)) {
+                // prefix has to exact match
+                return false;
+            }
+
+            if (pattern.indexOf('*') == pattern.lastIndexOf('*')) {
+                // exact match prefix with no '/' in the tail string
+                String wildcard = tail.substring(0, tail.length() - suffix.length());
+                return tail.indexOf('/') < 0 && tail.endsWith(suffix);
+            }
+
+            if (suffix.contains("*")) {
+                return matchesNameWithSlash(tail, suffix);
+            } else {
+                // tail ends with the suffix while no '/' in the wildcard matched string
+                String any = tail.substring(0, tail.length() - suffix.length());
+                return tail.endsWith(suffix) && any.indexOf('/') < 0;
+            }
+        } else {
+            // exact match
+            return name.equals(pattern);
+        }
+    }
+
+    private String convertToRegex(String pattern) {
+        StringBuilder sb = new StringBuilder();
+        int i = 0;
+        int index = 0;
+        int plen = pattern.length();
+        while (i < plen) {
+            char p = pattern.charAt(i);
+            if (p == '*') {
+                sb.append("(").append(pattern.substring(index, i)).append(")");
+                if (i + 1 < plen && pattern.charAt(i + 1) == '*') {
+                    sb.append(".*");
+                    index = i + 2;
+                } else {
+                    sb.append("[^\\.]*");
+                    index = i + 1;
+                }
+            }
+            i++;
+        }
+        if (index < plen) {
+            sb.append("(").append(pattern.substring(index, plen)).append(")");
+        }
+        return sb.toString();
+    }
+
+    static class Filter {
+
+        final ModuleConfig config;
+        final Set<String> exclude = new TreeSet<String>();
+        final Set<String> allow = new TreeSet<String>();
+
+        Filter(ModuleConfig config) {
+            this.config = config;
+        }
+
+        Filter exclude(String pattern) {
+            exclude.add(pattern);
+            return this;
+        }
+
+        Filter allow(String pattern) {
+            allow.add(pattern);
+            return this;
+        }
+
+        String allowedBy(String name) {
+            String allowedBy = null;
+            for (String pattern : allow) {
+                if (config.matches(name, pattern)) {
+                    if (name.equals(pattern)) {
+                        return pattern;  // exact match
+                    }
+                    if (allowedBy == null) {
+                        allowedBy = pattern;
+                    } else {
+                        if (pattern.length() > allowedBy.length()) {
+                            allowedBy = pattern;
+                        }
+                    }
+                }
+            }
+            return allowedBy;
+        }
+
+        String excludedBy(String name) {
+            String allowedBy = allowedBy(name);
+            String excludedBy = null;
+
+            if (allowedBy != null && name.equals(allowedBy)) {
+                return null;  // exact match
+            }
+            for (String pattern : exclude) {
+                if (config.matches(name, pattern)) {
+                    // not matched by allowed rule or exact match
+                    if (allowedBy == null || name.equals(pattern)) {
+                        return pattern;
+                    }
+                    if (excludedBy == null) {
+                        excludedBy = pattern;
+                    } else {
+                        if (pattern.length() > excludedBy.length()) {
+                            excludedBy = pattern;
+                        }
+                    }
+                }
+            }
+            return excludedBy;
+        }
+
+        boolean isExcluded(String name) {
+            String allowedBy = allowedBy(name);
+            String excludedBy = excludedBy(name);
+
+            if (excludedBy == null) {
+                return false;
+            }
+            // not matched by allowed rule or exact match
+            if (allowedBy == null || name.equals(excludedBy)) {
+                return true;
+            }
+
+            if (allowedBy == null) {
+                return true;
+            }
+            if (allowedBy != null &&
+                    excludedBy.length() > allowedBy.length()) {
+                return true;
+            }
+            return false;
+        }
+    }
+
+    private static String trimComment(String line) {
+        StringBuilder sb = new StringBuilder();
+
+        int pos = 0;
+        while (pos >= 0 && pos < line.length()) {
+            int c1 = line.indexOf("//", pos);
+            if (c1 > 0 && !Character.isWhitespace(line.charAt(c1-1))) {
+                // not a comment
+                c1 = -1;
+            }
+
+            int c2 = line.indexOf("/*", pos);
+            if (c2 > 0 && !Character.isWhitespace(line.charAt(c2-1))) {
+                // not a comment
+                c2 = -1;
+            }
+
+            int c = line.length();
+            int n = line.length();
+            if (c1 >= 0 || c2 >= 0) {
+                if (c1 >= 0) {
+                    c = c1;
+                }
+                if (c2 >= 0 && c2 < c) {
+                    c = c2;
+                }
+                int c3 = line.indexOf("*/", c2 + 2);
+                if (c == c2 && c3 > c2) {
+                    n = c3 + 2;
+                }
+            }
+            if (c > 0) {
+                if (sb.length() > 0) {
+                    // add a whitespace if multiple comments on one line
+                    sb.append(" ");
+                }
+                sb.append(line.substring(pos, c));
+            }
+            pos = n;
+        }
+        return sb.toString();
+    }
+
+    private static boolean beginBlockComment(String line) {
+        int pos = 0;
+        while (pos >= 0 && pos < line.length()) {
+            int c = line.indexOf("/*", pos);
+            if (c < 0) {
+                return false;
+            }
+
+            if (c > 0 && !Character.isWhitespace(line.charAt(c-1))) {
+                return false;
+            }
+
+            int c1 = line.indexOf("//", pos);
+            if (c1 >= 0 && c1 < c) {
+                return false;
+            }
+
+            int c2 = line.indexOf("*/", c + 2);
+            if (c2 < 0) {
+                return true;
+            }
+            pos = c + 2;
+        }
+        return false;
+    }
+
+    static void setBaseModule(String name) {
+        baseModuleName = name;
+    }
+    // TODO: we shall remove "-" from the regex once we define
+    // the naming convention for the module names without dashes
+    static final Pattern classNamePattern = Pattern.compile("[\\w\\.\\*_$-/]+");
+
+    static List<ModuleConfig> readConfigurationFile(String file) throws IOException {
+        List<ModuleConfig> result = new ArrayList<ModuleConfig>();
+        // parse configuration file
+        FileInputStream in = new FileInputStream(file);
+        try {
+            BufferedReader reader = new BufferedReader(new InputStreamReader(in));
+            String line;
+
+            int lineNumber = 0;
+            boolean inRoots = false;
+            boolean inIncludes = false;
+            boolean inAllows = false;
+            boolean inExcludes = false;
+            boolean inBlockComment = false;
+            ModuleConfig config = null;
+
+            while ((line = reader.readLine()) != null) {
+                lineNumber++;
+
+                if (inBlockComment) {
+                    int c = line.indexOf("*/");
+                    if (c >= 0) {
+                        line = line.substring(c + 2, line.length());
+                        inBlockComment = false;
+                    } else {
+                        // skip lines until end of comment block
+                        continue;
+                    }
+                }
+
+                inBlockComment = beginBlockComment(line);
+
+                line = trimComment(line).trim();
+                // ignore empty lines
+                if (line.length() == 0) {
+                    continue;
+                }
+
+                String values;
+                if (inRoots || inIncludes || inExcludes || inAllows) {
+                    values = line;
+                } else {
+                    String[] s = line.split("\\s+");
+                    String keyword = s[0].trim();
+                    if (keyword.equals("module")) {
+                        if (s.length != 3 || !s[2].trim().equals("{")) {
+                            throw new RuntimeException(file + ", line " +
+                                    lineNumber + ", is malformed");
+                        }
+                        config = new ModuleConfig(s[1].trim());
+                        result.add(config);
+                        // switch to a new module; so reset the flags
+                        inRoots = false;
+                        inIncludes = false;
+                        inExcludes = false;
+                        inAllows = false;
+                        continue;
+                    } else if (keyword.equals("roots")) {
+                        inRoots = true;
+                    } else if (keyword.equals("include")) {
+                        inIncludes = true;
+                    } else if (keyword.equals("exclude")) {
+                        inExcludes = true;
+                    } else if (keyword.equals("allow")) {
+                        inAllows = true;
+                    } else if (keyword.equals("}")) {
+                        if (config == null || s.length != 1) {
+                            throw new RuntimeException(file + ", line " +
+                                    lineNumber + ", is malformed");
+                        } else {
+                            // end of a module
+                            config = null;
+                            continue;
+                        }
+                    } else {
+                        throw new RuntimeException(file + ", \"" + keyword + "\" on line " +
+                                lineNumber + ", is not recognized");
+                    }
+                    values = line.substring(keyword.length(), line.length()).trim();
+                }
+
+                if (config == null) {
+                    throw new RuntimeException(file + ", module not specified");
+                }
+
+                int len = values.length();
+                if (len == 0) {
+                    continue;
+                }
+                char lastchar = values.charAt(len - 1);
+                if (lastchar != ',' && lastchar != ';') {
+                    throw new RuntimeException(file + ", line " +
+                            lineNumber + ", is malformed:" +
+                            " ',' or ';' is missing.");
+                }
+
+                values = values.substring(0, len - 1);
+                // parse the values specified for a keyword specified
+                for (String s : values.split(",")) {
+                    s = s.trim();
+                    if (s.length() > 0) {
+                        if (!classNamePattern.matcher(s).matches()) {
+                            throw new RuntimeException(file + ", line " +
+                                    lineNumber + ", is malformed: \"" + s + "\"");
+                        }
+                        if (inRoots) {
+                            config.roots.add(s);
+                        } else if (inIncludes) {
+                            config.includes.add(s);
+                        } else if (inExcludes) {
+                            config.filter.exclude(s);
+                        } else if (inAllows) {
+                            config.filter.allow(s);
+                        }
+
+                    }
+                }
+                if (lastchar == ';') {
+                    inRoots = false;
+                    inIncludes = false;
+                    inExcludes = false;
+                    inAllows = false;
+                }
+            }
+
+            if (inBlockComment) {
+                throw new RuntimeException(file + ", line " +
+                        lineNumber + ", missing \"*/\" to end a block comment");
+            }
+            if (config != null) {
+                throw new RuntimeException(file + ", line " +
+                        lineNumber + ", missing \"}\" to end module definition" +
+                        " for \"" + config.module + "\"");
+            }
+
+        } finally {
+            in.close();
+        }
+
+        return result;
+    }
+
+    private String format(String keyword, Collection<String> values) {
+        if (values.size() == 0) {
+            return "";
+        }
+
+        StringBuilder sb = new StringBuilder();
+        String format = "%4s%-9s";
+        String spaces = String.format(format, "", "");
+        sb.append(String.format(format, "", keyword));
+        int count = 0;
+        for (String s : values) {
+            if (count > 0) {
+                sb.append(",\n").append(spaces);
+            } else if (count++ > 0) {
+                sb.append(", ");
+            }
+            sb.append(s);
+        }
+        if (count > 0) {
+            sb.append(";\n");
+        }
+        return sb.toString();
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder();
+        sb.append("module " + module).append(" {\n");
+        sb.append(format("include", includes));
+        sb.append(format("root", roots));
+        sb.append(format("allow", filter.allow));
+        sb.append(format("exclude", filter.exclude));
+        sb.append("}\n");
+        return sb.toString();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/make/modules/tools/src/com/sun/classanalyzer/ResolutionInfo.java	Wed Jul 05 17:04:56 2017 +0200
@@ -0,0 +1,201 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ *
+ */
+
+package com.sun.classanalyzer;
+
+import com.sun.classanalyzer.Klass.Method;
+
+/**
+ *
+ * @author mchung
+ */
+public class ResolutionInfo implements Comparable<ResolutionInfo> {
+
+    enum Type {
+
+        REFLECTION("reflection", true),
+        NATIVE("native", true),
+        INTERFACE("interface", false),
+        SUPER("super", false),
+        EXPLICIT("explicit", false),
+        VERIFICATION("verification", false),
+        METHODTRACE("method trace", true),
+        CONSTANT_POOL("constant pool", true),
+        CHECKED_EXCEPTION("throws", true),
+        METHOD("method", true),
+        FIELD("field", true),
+        EXTENDS("extends", true),
+        IMPLEMENTS("implements", true),
+        NOINFO("No info", false);
+
+        private final String name;
+        private final boolean hasInfo;
+
+        private Type(String name, boolean hasInfo) {
+            this.name = name;
+            this.hasInfo = hasInfo;
+        }
+
+        public String getName() {
+            return name;
+        }
+
+        public boolean hasInfo() {
+            return hasInfo;
+        }
+
+        public static Type getType(String s) {
+            if (s.isEmpty()) {
+                return NOINFO;
+            }
+            for (Type t : values()) {
+                if (s.equals(t.name)) {
+                    return t;
+                }
+            }
+            // Need to fix the VM output to add "native"
+            // throw new IllegalArgumentException("Invalid ResolutionInfo.type \"" + s + "\"");
+            System.out.println("WARNING: Invalid ResolutionInfo.type \"" + s + "\"");
+            return null;
+        }
+    }
+    final Klass fromClass;
+    final Method method;
+    final Klass toClass;
+    final int linenumber;
+    final Type type;
+    final String info;
+    private boolean isPublic = false;
+
+    private ResolutionInfo(Klass from, Klass to, int linenumber, Type type, String info) {
+        this.fromClass = from;
+        this.method = null;
+        this.toClass = to;
+        this.linenumber = linenumber;
+        this.type = type;
+        this.info = info;
+    }
+
+    private ResolutionInfo(Klass from, Method m, Klass to, int linenumber, Type type) {
+        this.fromClass = from;
+        this.method = m;
+        this.toClass = to;
+        this.linenumber = linenumber;
+        this.type = type;
+        this.info = m.toString();
+    }
+
+    public boolean isPublic() {
+        return isPublic;
+    }
+
+    public void setPublicAccess(boolean value) {
+        isPublic = value;
+    }
+    static ResolutionInfo resolved(Klass from, Klass to) {
+        return new ResolutionInfo(from, to, 0, Type.NOINFO, "");
+    }
+
+    static ResolutionInfo resolved(Klass from, Klass to, int linenumber) {
+        return new ResolutionInfo(from, to, linenumber, Type.NOINFO, "");
+    }
+
+    static ResolutionInfo resolved(Klass from, Klass to, int linenumber, String reason) {
+        String[] ss = reason.split("\\s+");
+        Type type;
+        String info;
+        if (linenumber == -1) {
+            type = Type.NATIVE;
+            info = ss[0];  // native method name
+        } else {
+            info = ss.length == 2 ? ss[1] : "";
+            type = Type.getType(ss[0]);
+            if (type == null) {
+                if (reason.isEmpty()) {
+                    throw new IllegalArgumentException("Invalid type: " + reason + " (" + ss[0] + ")" + ss.length);
+                }
+                // assume it's native
+                type = Type.NATIVE;
+                info = reason.isEmpty() ? ss[0] : reason;
+            }
+        }
+
+        return new ResolutionInfo(from, to, linenumber, type, info);
+    }
+
+    static ResolutionInfo resolved(Klass from, Klass to, Method callee) {
+        return new ResolutionInfo(from, callee, to, 0, Type.METHODTRACE);
+    }
+
+    static ResolutionInfo resolvedConstantPool(Klass from, Klass to, int index) {
+        return new ResolutionInfo(from, to, 0, Type.CONSTANT_POOL, "#" + index);
+    }
+
+    static ResolutionInfo resolvedField(Klass from, Klass to, String fieldname) {
+        return new ResolutionInfo(from, to, 0, Type.FIELD, fieldname);
+    }
+
+    static ResolutionInfo resolvedMethodSignature(Klass from, Klass to, Method m) {
+        return new ResolutionInfo(from, m, to, 0, Type.METHOD);
+    }
+
+    static ResolutionInfo resolvedCheckedException(Klass from, Klass to, Method m) {
+        return new ResolutionInfo(from, m, to, 0, Type.CHECKED_EXCEPTION);
+    }
+
+    static ResolutionInfo resolvedExtends(Klass from, Klass to) {
+        String info = from.getClassName() + " implements " + to.getClassName();
+        return new ResolutionInfo(from, to, 0, Type.EXTENDS, info);
+    }
+
+    static ResolutionInfo resolvedImplements(Klass from, Klass to) {
+        String info = from.getClassName() + " implements " + to.getClassName();
+        return new ResolutionInfo(from, to, 0, Type.IMPLEMENTS, info);
+    }
+
+    @Override
+    public int compareTo(ResolutionInfo ri) {
+        if (this.fromClass == ri.fromClass &&
+                this.toClass == ri.toClass &&
+                this.linenumber == ri.linenumber &&
+                this.type == ri.type &&
+                this.info.equals(ri.info)) {
+            return 0;
+        } else if (this.fromClass == ri.fromClass) {
+            if (this.linenumber > ri.linenumber) {
+                return 1;
+            } else if (this.linenumber < ri.linenumber) {
+                return -1;
+            } else if (this.type != ri.type) {
+                return this.type.getName().compareTo(ri.type.getName());
+            } else if (this.toClass != ri.toClass) {
+                return this.toClass.compareTo(ri.toClass);
+            } else {
+                return this.info.compareTo(ri.info);
+            }
+        } else {
+            return this.fromClass.compareTo(ri.fromClass);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/make/modules/tools/src/com/sun/classanalyzer/ResourceFile.java	Wed Jul 05 17:04:56 2017 +0200
@@ -0,0 +1,186 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ *
+ */
+package com.sun.classanalyzer;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+import java.util.TreeSet;
+
+/**
+ *
+ * @author Mandy Chung
+ */
+public class ResourceFile implements Comparable<ResourceFile> {
+
+    private final String pathname;
+    private Module module;
+
+    ResourceFile(String pathname) {
+        this.pathname = pathname.replace(File.separatorChar, '/');
+    }
+
+    Module getModule() {
+        return module;
+    }
+
+    void setModule(Module m) {
+        if (module != null) {
+            throw new RuntimeException("Module for " + this + " already set");
+        }
+        this.module = m;
+    }
+
+    String getName() {
+        return pathname;
+    }
+
+    String getPathname() {
+        return pathname;
+    }
+
+    @Override
+    public String toString() {
+        return pathname;
+    }
+
+    @Override
+    public int compareTo(ResourceFile o) {
+        return pathname.compareTo(o.pathname);
+    }
+    static Set<ResourceFile> resources = new TreeSet<ResourceFile>();
+
+    static boolean isResource(String pathname) {
+        String name = pathname.replace(File.separatorChar, '/');
+
+        if (name.endsWith("META-INF/MANIFEST.MF")) {
+            return false;
+        }
+        if (name.contains("META-INF/JCE_RSA.")) {
+            return false;
+        }
+
+        return true;
+    }
+
+    static void addResource(String name, InputStream in) {
+        ResourceFile res;
+        name = name.replace(File.separatorChar, '/');
+        if (name.startsWith("META-INF/services")) {
+            res = new ServiceProviderConfigFile(name, in);
+        } else {
+            res = new ResourceFile(name);
+        }
+        resources.add(res);
+    }
+
+    static Set<ResourceFile> getAllResources() {
+        return Collections.unmodifiableSet(resources);
+    }
+
+    static class ServiceProviderConfigFile extends ResourceFile {
+
+        private final List<String> providers = new ArrayList<String>();
+        private final String service;
+        ServiceProviderConfigFile(String pathname, InputStream in) {
+            super(pathname);
+            readServiceConfiguration(in, providers);
+            this.service = pathname.substring("META-INF/services".length() + 1, pathname.length());
+        }
+
+        @Override
+        String getName() {
+            if (providers.isEmpty()) {
+                return service;
+            } else {
+                // just use the first one for matching
+                return providers.get(0);
+            }
+        }
+
+        @SuppressWarnings("empty-statement")
+        void readServiceConfiguration(InputStream in, List<String> names) {
+            BufferedReader br = null;
+            try {
+                if (in != null) {
+                    // Properties doesn't perserve the order of the input file
+                    br = new BufferedReader(new InputStreamReader(in, "utf-8"));
+                    int lc = 1;
+                    while ((lc = parseLine(br, lc, names)) >= 0);
+                }
+            } catch (IOException ex) {
+                throw new RuntimeException(ex);
+            } finally {
+                if (br != null) {
+                    try {
+                        br.close();
+                    } catch (IOException ex) {
+                        throw new RuntimeException(ex);
+                    }
+                }
+            }
+        }
+
+        // Parse a single line from the given configuration file, adding the name
+        // on the line to the names list.
+        //
+        private int parseLine(BufferedReader r, int lc, List<String> names) throws IOException {
+            String ln = r.readLine();
+            if (ln == null) {
+                return -1;
+            }
+            int ci = ln.indexOf('#');
+            if (ci >= 0) {
+                ln = ln.substring(0, ci);
+            }
+            ln = ln.trim();
+            int n = ln.length();
+            if (n != 0) {
+                if ((ln.indexOf(' ') >= 0) || (ln.indexOf('\t') >= 0)) {
+                    throw new RuntimeException("Illegal configuration-file syntax");
+                }
+                int cp = ln.codePointAt(0);
+                if (!Character.isJavaIdentifierStart(cp)) {
+                    throw new RuntimeException("Illegal provider-class name: " + ln);
+                }
+                for (int i = Character.charCount(cp); i < n; i += Character.charCount(cp)) {
+                    cp = ln.codePointAt(i);
+                    if (!Character.isJavaIdentifierPart(cp) && (cp != '.')) {
+                        throw new RuntimeException("Illegal provider-class name: " + ln);
+                    }
+                }
+                if (!names.contains(ln)) {
+                    names.add(ln);
+                }
+            }
+            return lc + 1;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/make/modules/tools/src/com/sun/classanalyzer/ShowDeps.java	Wed Jul 05 17:04:56 2017 +0200
@@ -0,0 +1,100 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+package com.sun.classanalyzer;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.*;
+
+/**
+ * A simple tool to print out the static dependencies for a given set of JAR,
+ * class files, or combinations of. The tools supports an -ignore option to
+ * ignore references to classes listed in the file (including .classlists
+ * created by the ClassAnalyzer tool).
+ */
+
+public class ShowDeps {
+
+    static void usage() {
+        System.out.println("java ShowDeps [-ignore <classlist>] file...");
+        System.out.println("   where <file> is a class or JAR file, or a directory");
+        System.out.println();
+        System.out.println("Example usages:");
+        System.out.println("  java ShowDeps Foo.jar");
+        System.out.println("  java ShowDeps -ignore base.classlist Foo.jar");
+        System.out.println("  java ShowDeps -ignore base.classlist -ignore " +
+            "jaxp-parsers.classlist <dir>");
+        System.exit(-1);
+    }
+
+    public static void main(String[] args) throws IOException {
+        // process -ignore options
+        int argi = 0;
+        Set<String> ignore = new HashSet<String>();
+        while (argi < args.length && args[argi].equals("-ignore")) {
+            argi++;
+            Scanner s = new Scanner(new File(args[argi++]));
+            try {
+                while (s.hasNextLine()) {
+                    String line = s.nextLine();
+                    if (!line.endsWith(".class"))
+                        continue;
+                    int len = line.length();
+                    // convert to class names
+                    String clazz = line.replace('\\', '.').replace('/', '.')
+                        .substring(0, len-6);
+                    ignore.add(clazz);
+                }
+            } finally {
+                s.close();
+            }
+        }
+
+        if (argi >= args.length)
+            usage();
+
+        // parse all classes
+        while (argi < args.length)
+            ClassPath.setClassPath(args[argi++]);
+        ClassPath.parseAllClassFiles();
+
+        // find the classes that don't exist
+        Set<Klass> unresolved = new TreeSet<Klass>();
+        for (Klass k : Klass.getAllClasses()) {
+            if (k.getFileSize() == 0)
+                unresolved.add(k);
+        }
+
+        // print references to classes that don't exist
+        for (Klass k: Klass.getAllClasses()) {
+            for (Klass other : k.getReferencedClasses()) {
+                if (unresolved.contains(other)) {
+                    String name = other.toString();
+                    if (!ignore.contains(name)) {
+                        System.out.format("%s -> %s\n", k, other);
+                    }
+                }
+            }
+        }
+    }
+}
--- a/jdk/src/share/bin/java.c	Thu Dec 17 14:10:20 2009 -0800
+++ b/jdk/src/share/bin/java.c	Wed Jul 05 17:04:56 2017 +0200
@@ -93,6 +93,7 @@
  * Prototypes for functions internal to launcher.
  */
 static void SetClassPath(const char *s);
+static void SetModulesBootClassPath(const char *s);
 static void SelectVersion(int argc, char **argv, char **main_class);
 static jboolean ParseArguments(int *pargc, char ***pargv, char **pjarfile,
                                char **pclassname, int *pret, const char *jvmpath);
@@ -277,6 +278,9 @@
         return(ret);
     }
 
+    /* Set bootclasspath for modules */
+    SetModulesBootClassPath(jrepath);
+
     /* Override class path if -jar flag was specified */
     if (jarfile != 0) {
         SetClassPath(jarfile);
@@ -694,6 +698,44 @@
 }
 
 /*
+ * Set the bootclasspath for modules.
+ * A temporary workaround until jigsaw is integrated into JDK 7.
+ */
+static void
+SetModulesBootClassPath(const char *jrepath)
+{
+    char *def, *s;
+    char pathname[MAXPATHLEN];
+    const char separator[] = { FILE_SEPARATOR, '\0' };
+    const char *orig = jrepath;
+    static const char format[] = "-Xbootclasspath/p:%s";
+    struct stat statbuf;
+
+    /* return if jre/lib/rt.jar exists */
+    sprintf(pathname, "%s%slib%srt.jar", jrepath, separator, separator);
+    if (stat(pathname, &statbuf) == 0) {
+        return;
+    }
+
+    /* return if jre/classes exists */
+    sprintf(pathname, "%s%sclasses", jrepath, separator);
+    if (stat(pathname, &statbuf) == 0) {
+        return;
+    }
+
+    /* modularized jre */
+    sprintf(pathname, "%s%slib%s*", jrepath, separator, separator);
+    s = (char *) JLI_WildcardExpandClasspath(pathname);
+    def = JLI_MemAlloc(sizeof(format)
+                       - 2 /* strlen("%s") */
+                       + JLI_StrLen(s));
+    sprintf(def, format, s);
+    AddOption(def, NULL);
+    if (s != orig)
+        JLI_MemFree((char *) s);
+}
+
+/*
  * The SelectVersion() routine ensures that an appropriate version of
  * the JRE is running.  The specification for the appropriate version
  * is obtained from either the manifest of a jar file (preferred) or
--- a/jdk/src/share/classes/com/sun/jndi/toolkit/corba/CorbaUtils.java	Thu Dec 17 14:10:20 2009 -0800
+++ b/jdk/src/share/classes/com/sun/jndi/toolkit/corba/CorbaUtils.java	Wed Jul 05 17:04:56 2017 +0200
@@ -33,10 +33,10 @@
 import java.util.Hashtable;
 import java.util.Properties;
 import java.util.Enumeration;
-import java.applet.Applet;
 
 import org.omg.CORBA.ORB;
 
+import javax.naming.Context;
 import javax.naming.ConfigurationException;
 
 /**
@@ -191,16 +191,48 @@
         }
 
         // Get Applet from environment
-        Applet applet = null;
         if (env != null) {
-            applet = (Applet) env.get("java.naming.applet");
+            Object applet = env.get(Context.APPLET);
+            if (applet != null) {
+                // Create ORBs for an applet
+                return initAppletORB(applet, orbProp);
+            }
         }
 
-        // Create ORBs using applet and orbProp
-        if (applet != null) {
-            return ORB.init(applet, orbProp);
-        } else {
-            return ORB.init(new String[0], orbProp);
+        // Create ORBs using orbProp for a standalone application
+        return ORB.init(new String[0], orbProp);
+    }
+
+    /**
+     * This method returns a new ORB instance for the given applet
+     * without creating a static dependency on java.applet.
+     */
+    private static ORB initAppletORB(Object applet, Properties orbProp) {
+        try {
+            Class<?> appletClass  = Class.forName("java.applet.Applet", true, null);
+            if (!appletClass.isInstance(applet)) {
+                throw new ClassCastException(applet.getClass().getName());
+            }
+
+            // invoke the static method ORB.init(applet, orbProp);
+            Method method = ORB.class.getMethod("init", appletClass, Properties.class);
+            return (ORB) method.invoke(null, applet, orbProp);
+        } catch (ClassNotFoundException e) {
+            // java.applet.Applet doesn't exist and the applet parameter is
+            // non-null; so throw CCE
+            throw new ClassCastException(applet.getClass().getName());
+        } catch (NoSuchMethodException e) {
+            throw new AssertionError(e);
+        } catch (InvocationTargetException e) {
+            Throwable cause = e.getCause();
+            if (cause instanceof RuntimeException) {
+                throw (RuntimeException) cause;
+            } else if (cause instanceof Error) {
+                throw (Error) cause;
+            }
+            throw new AssertionError(e);
+        } catch (IllegalAccessException iae) {
+            throw new AssertionError(iae);
         }
     }
 
--- a/jdk/src/share/classes/java/dyn/CallSite.java	Thu Dec 17 14:10:20 2009 -0800
+++ b/jdk/src/share/classes/java/dyn/CallSite.java	Wed Jul 05 17:04:56 2017 +0200
@@ -26,6 +26,9 @@
 package java.dyn;
 
 import sun.dyn.util.BytecodeName;
+import sun.dyn.Access;
+import sun.dyn.CallSiteImpl;
+import sun.dyn.MethodHandleImpl;
 
 /**
  * An {@code invokedynamic} call site, as reified by the
@@ -52,15 +55,25 @@
  * @see Linkage#registerBootstrapMethod(java.lang.Class, java.dyn.MethodHandle)
  * @author John Rose, JSR 292 EG
  */
-public class CallSite {
+public class CallSite
+        // Note: This is an implementation inheritance hack, and will be removed
+        // with a JVM change which moves the required hidden state onto this class.
+        extends CallSiteImpl
+{
+    private static final Access IMPL_TOKEN = Access.getToken();
+
+    /*
+
     // Fields used only by the JVM.  Do not use or change.
     private Object vmmethod;
     int callerMID, callerBCI;  // supplied by the JVM
 
-    MethodHandle target;
+    private MethodHandle target;
+
     final Object caller;  // usually a class
     final String name;
     final MethodType type;
+    */
 
     /**
      * Make a call site given the parameters from a call to the bootstrap method.
@@ -72,16 +85,21 @@
      * @param type the method handle type derived from descriptor of the {@code invokedynamic} instruction
      */
     public CallSite(Object caller, String name, MethodType type) {
-        this.caller = caller;
-        this.name = name;
-        this.type = type;
+        super(IMPL_TOKEN, caller, name, type);
     }
 
     private static void privateInitializeCallSite(CallSite site, int callerMID, int callerBCI) {
         site.callerMID = callerMID;
         site.callerBCI = callerBCI;
-        if (site.target == null)
-            site.setTarget(site.initialTarget());
+        site.ensureTarget();
+    }
+    private void ensureTarget() {
+        // Note use of super, which accesses the field directly,
+        // without deferring to possible subclass overrides.
+        if (super.getTarget() == null) {
+            super.setTarget(this.initialTarget());
+            super.getTarget().type();  // provoke NPE if still null
+        }
     }
 
     /**
@@ -102,10 +120,11 @@
 
     /**
      * Report the current linkage state of the call site.  (This is mutable.)
-     * The value maybe null only if the call site is currently unlinked.
-     * When a linked call site is invoked, the target method is used directly.
-     * When an unlinked call site is invoked, its bootstrap method receives
-     * the call, as if via {@link Linkage#bootstrapInvokeDynamic}.
+     * The value may not be null after the {@code CallSite} object is returned
+     * from the bootstrap method of the {@code invokedynamic} instruction.
+     * When an {@code invokedynamic} instruction is executed, the target method
+     * of its associated {@code call site} object is invoked directly,
+     * as if via {@link MethodHandle}{@code .invoke}.
      * <p>
      * The interactions of {@code getTarget} with memory are the same
      * as of a read from an ordinary variable, such as an array element or a
@@ -118,7 +137,7 @@
      * @see #setTarget
      */
     public MethodHandle getTarget() {
-        return target;
+        return super.getTarget();
     }
 
     /**
@@ -140,13 +159,13 @@
      */
     public void setTarget(MethodHandle target) {
         checkTarget(target);
-        this.target = target;
+        super.setTarget(target);
     }
 
     protected void checkTarget(MethodHandle target) {
         target.type();  // provoke NPE
         if (!canSetTarget(target))
-            throw new WrongMethodTypeException(String.valueOf(target));
+            throw new WrongMethodTypeException(String.valueOf(target)+target.type()+" should be of type "+type());
     }
 
     protected boolean canSetTarget(MethodHandle target) {
@@ -219,6 +238,10 @@
 
     @Override
     public String toString() {
-        return "CallSite#"+hashCode()+"["+name+type+" => "+target+"]";
+        return "CallSite#"+hashCode()+"["+name+type+" => "+getTarget()+"]";
     }
+
+    // Package-local constant:
+    static final MethodHandle GET_TARGET = MethodHandleImpl.getLookup(IMPL_TOKEN).
+            findVirtual(CallSite.class, "getTarget", MethodType.methodType(MethodHandle.class));
 }
--- a/jdk/src/share/classes/java/dyn/InvokeDynamic.java	Thu Dec 17 14:10:20 2009 -0800
+++ b/jdk/src/share/classes/java/dyn/InvokeDynamic.java	Wed Jul 05 17:04:56 2017 +0200
@@ -45,6 +45,24 @@
  * class or interface supertype, or an object type; it can never be instantiated.
  * Logically, it denotes a source of all dynamically typed methods.
  * It may be viewed as a pure syntactic marker (an importable one) of static calls.
+ * <p>
+ * Here are some examples of usage:
+ * <p><blockquote><pre>
+ * Object x; String s; int i;
+ * x = InvokeDynamic.greet("world"); // greet(Ljava/lang/String;)Ljava/lang/Object;
+ * s = InvokeDynamic.&lt;String&gt;hail(x); // hail(Ljava/lang/Object;)Ljava/lang/String;
+ * InvokeDynamic.&lt;void&gt;cogito(); // cogito()V
+ * i = InvokeDynamic.&lt;int&gt;#"op:+"(2, 3); // "op:+"(II)I
+ * </pre></blockquote>
+ * Each of the above calls generates a single invokedynamic instruction
+ * with the name-and-type descriptors indicated in the comments.
+ * The argument types are taken directly from the actual arguments,
+ * while the return type is taken from the type parameter.
+ * (This type parameter may be a primtive, and it defaults to {@code Object}.)
+ * The final example uses a special syntax for uttering non-Java names.
+ * Any name legal to the JVM may be given between the double quotes.
+ * None of these calls is complete without a bootstrap method,
+ * which must be registered by the static initializer of the enclosing class.
  * @author John Rose, JSR 292 EG
  */
 public final class InvokeDynamic {
--- a/jdk/src/share/classes/java/dyn/InvokeDynamicBootstrapError.java	Thu Dec 17 14:10:20 2009 -0800
+++ b/jdk/src/share/classes/java/dyn/InvokeDynamicBootstrapError.java	Wed Jul 05 17:04:56 2017 +0200
@@ -52,4 +52,16 @@
     public InvokeDynamicBootstrapError(String s) {
         super(s);
     }
+
+    /**
+     * Constructs a {@code InvokeDynamicBootstrapError} with the specified
+     * detail message and cause.
+     *
+     * @param s the detail message.
+     * @param cause the cause.
+     */
+    public InvokeDynamicBootstrapError(String s, Throwable cause) {
+        super(s);
+        this.initCause(cause);
+    }
 }
--- a/jdk/src/share/classes/java/dyn/JavaMethodHandle.java	Thu Dec 17 14:10:20 2009 -0800
+++ b/jdk/src/share/classes/java/dyn/JavaMethodHandle.java	Wed Jul 05 17:04:56 2017 +0200
@@ -25,6 +25,8 @@
 
 package java.dyn;
 
+import sun.dyn.Access;
+
 /**
  * A Java method handle extends the basic method handle type with additional
  * programmer defined methods and fields.
@@ -39,31 +41,105 @@
  * of the entry point method handle, with the leading parameter type
  * omitted.
  * <p>
- * Here is an example of usage:
+ * Here is an example of usage, creating a hybrid object/functional datum:
  * <p><blockquote><pre>
- *     class Greeter extends JavaMethodHandle {
+ * class Greeter extends JavaMethodHandle {
+ *     private String greeting = "hello";
+ *     public void setGreeting(String s) { greeting = s; }
+ *     public void run() { System.out.println(greeting+", "+greetee); }
+ *     private final String greetee;
+ *     Greeter(String greetee) {
+ *         super(RUN); // alternatively, super("run")
+ *         this.greetee = greetee;
+ *     }
+ *     // the entry point function is computed once:
+ *     private static final MethodHandle RUN
+ *         = MethodHandles.lookup().findVirtual(Greeter.class, "run",
+ *               MethodType.make(void.class));
+ * }
+ * // class Main { public static void main(String... av) { ...
+ * Greeter greeter = new Greeter("world");
+ * greeter.run();  // prints "hello, world"
+ * // Statically typed method handle invocation (most direct):
+ * MethodHandle mh = greeter;
+ * mh.&lt;void&gt;invoke();  // also prints "hello, world"
+ * // Dynamically typed method handle invocation:
+ * MethodHandles.invoke(greeter);  // also prints "hello, world"
+ * greeter.setGreeting("howdy");
+ * mh.invoke();  // prints "howdy, world" (object-like mutable behavior)
+ * </pre></blockquote>
+ * <p>
+ * In the example of {@code Greeter}, the method {@code run} provides the entry point.
+ * The entry point need not be a constant value; it may be independently
+ * computed in each call to the constructor.  The entry point does not
+ * even need to be a method on the {@code Greeter} class, though
+ * that is the typical case.
+ * <p>
+ * The entry point may also be provided symbolically, in which case the the
+ * {@code JavaMethodHandle} constructor performs the lookup of the entry point.
+ * This makes it possible to use {@code JavaMethodHandle} to create an anonymous
+ * inner class:
+ * <p><blockquote><pre>
+ * // We can also do this with symbolic names and/or inner classes:
+ * MethodHandles.invoke(new JavaMethodHandle("yow") {
+ *     void yow() { System.out.println("yow, world"); }
+ * });
+ * </pre></blockquote>
+ * <p>
+ * Here is similar lower-level code which works in terms of a bound method handle.
+ * <p><blockquote><pre>
+ *     class Greeter {
  *         public void run() { System.out.println("hello, "+greetee); }
  *         private final String greetee;
- *         Greeter(String greetee) {
- *             super(RUN);
- *             this.greetee = greetee;
- *         }
+ *         Greeter(String greetee) { this.greetee = greetee; }
  *         // the entry point function is computed once:
  *         private static final MethodHandle RUN
- *             = MethodHandles.findVirtual(MyMethodHandle.class, "run",
+ *             = MethodHandles.findVirtual(Greeter.class, "run",
  *                   MethodType.make(void.class));
  *     }
+ *     // class Main { public static void main(String... av) { ...
  *     Greeter greeter = new Greeter("world");
  *     greeter.run();  // prints "hello, world"
- *     MethodHandle mh = greeter;
+ *     MethodHandle mh = MethodHanndles.insertArgument(Greeter.RUN, 0, greeter);
  *     mh.invoke();  // also prints "hello, world"
  * </pre></blockquote>
+ * Note that the method handle must be separately created as a view on the base object.
+ * This increases footprint, complexity, and dynamic indirections.
+ * <p>
+ * Here is a pure functional value expressed most concisely as an anonymous inner class:
+ * <p><blockquote><pre>
+ *     // class Main { public static void main(String... av) { ...
+ *     final String greetee = "world";
+ *     MethodHandle greeter = new JavaMethodHandle("run") {
+ *         private void run() { System.out.println("hello, "+greetee); }
+ *     }
+ *     greeter.invoke();  // prints "hello, world"
+ * </pre></blockquote>
  * <p>
- * In this example, the method {@code run} provides the entry point.
- * The entry point need not be a constant value; it may be independently
- * computed in each call to the constructor.  The entry point does not
- * even need to be a method on the Java method handle class, though
- * that is the typical case.
+ * Here is an abstract parameterized lvalue, efficiently expressed as a subtype of MethodHandle,
+ * and instantiated as an anonymous class.  The data structure is a handle to 1-D array,
+ * with a specialized index type (long).  It is created by inner class, and uses
+ * signature-polymorphic APIs throughout.
+ * <p><blockquote><pre>
+ *     abstract class AssignableMethodHandle extends JavaMethodHandle {
+ *       private final MethodHandle setter;
+ *       public MethodHandle setter() { return setter; }
+ *       public AssignableMethodHandle(String get, String set) {
+ *         super(get);
+ *         MethodType getType = this.type();
+ *         MethodType setType = getType.insertParameterType(getType.parameterCount(), getType.returnType()).changeReturnType(void.class);
+ *         this.setter = MethodHandles.publicLookup().bind(this, set, setType);
+ *       }
+ *     }
+ *     // class Main { public static void main(String... av) { ...
+ *     final Number[] stuff = { 123, 456 };
+ *     AssignableMethodHandle stuffPtr = new AssignableMethodHandle("get", "set") {
+ *         public Number get(long i)           { return stuff[(int)i]; }
+ *         public void   set(long i, Object x) {        stuff[(int)i] = x; }
+ *     }
+ *     int x = (Integer) stuffPtr.&lt;Number&gt;invoke(1L);  // 456
+ *     stuffPtr.setter().&lt;void&gt;invoke(0L, (Number) 789);  // replaces 123 with 789
+ * </pre></blockquote>
  * @see MethodHandle
  * @author John Rose, JSR 292 EG
  */
@@ -72,12 +148,87 @@
         // with a JVM change which moves the required hidden behavior onto this class.
         extends sun.dyn.BoundMethodHandle
 {
+    private static final Access IMPL_TOKEN = Access.getToken();
+
     /**
-     * When creating a, pass in {@code entryPoint}, any method handle which
-     * can take the current object
-     * @param entryPoint
+     * When creating a {@code JavaMethodHandle}, the actual method handle
+     * invocation behavior will be delegated to the specified {@code entryPoint}.
+     * This may be any method handle which can take the newly constructed object
+     * as a leading parameter.
+     * <p>
+     * The method handle type of {@code this} (i.e, the fully constructed object)
+     * will be {@code entryPoint}, minus the leading argument.
+     * The leading argument will be bound to {@code this} on every method
+     * handle invocation.
+     * @param entryPoint the method handle to handle calls
      */
     protected JavaMethodHandle(MethodHandle entryPoint) {
-        super(entryPoint, 0);
+        super(entryPoint);
+    }
+
+    /**
+     * Create a method handle whose entry point is a non-static method
+     * visible in the exact (most specific) class of
+     * the newly constructed object.
+     * <p>
+     * The method is specified by name and type, as if via this expression:
+     * {@code MethodHandles.lookup().findVirtual(this.getClass(), name, type)}.
+     * The class defining the method might be an anonymous inner class.
+     * <p>
+     * The method handle type of {@code this} (i.e, the fully constructed object)
+     * will be the given method handle type.
+     * A call to {@code this} will invoke the selected method.
+     * The receiver argument will be bound to {@code this} on every method
+     * handle invocation.
+     * <p>
+     * <i>Rationale:</i>
+     * Although this constructor may seem to be a mere luxury,
+     * it is not subsumed by the more general constructor which
+     * takes any {@code MethodHandle} as the entry point argument.
+     * In order to convert an entry point name to a method handle,
+     * the self-class of the object is required (in order to do
+     * the lookup).  The self-class, in turn, is generally not
+     * available at the time of the constructor invocation,
+     * due to the rules of Java and the JVM verifier.
+     * One cannot call {@code this.getClass()}, because
+     * the value of {@code this} is inaccessible at the point
+     * of the constructor call.  (Changing this would require
+     * change to the Java language, verifiers, and compilers.)
+     * In particular, this constructor allows {@code JavaMethodHandle}s
+     * to be created in combination with the anonymous inner class syntax.
+     * @param entryPointName the name of the entry point method
+     * @param type (optional) the desired type of the method handle
+     */
+    protected JavaMethodHandle(String entryPointName, MethodType type) {
+        super(entryPointName, type, true);
+
+    }
+
+    /**
+     * Create a method handle whose entry point is a non-static method
+     * visible in the exact (most specific) class of
+     * the newly constructed object.
+     * <p>
+     * The method is specified only by name.
+     * There must be exactly one method of that name visible in the object class,
+     * either inherited or locally declared.
+     * (That is, the method must not be overloaded.)
+     * <p>
+     * The method handle type of {@code this} (i.e, the fully constructed object)
+     * will be the same as the type of the selected non-static method.
+     * The receiver argument will be bound to {@code this} on every method
+     * handle invocation.
+     * <p>ISSUE: This signature wildcarding feature does not correspond to
+     * any MethodHandles.Lookup API element.  Can we eliminate it?
+     * Alternatively, it is useful for naming non-overloaded methods.
+     * Shall we make type arguments optional in the Lookup methods,
+     * throwing an error in cases of ambiguity?
+     * <p>
+     * For this method's rationale, see the documentation
+     * for {@link #JavaMethodHandle(String,MethodType)}.
+     * @param entryPointName the name of the entry point method
+     */
+    protected JavaMethodHandle(String entryPointName) {
+        super(entryPointName, (MethodType) null, false);
     }
 }
--- a/jdk/src/share/classes/java/dyn/Linkage.java	Thu Dec 17 14:10:20 2009 -0800
+++ b/jdk/src/share/classes/java/dyn/Linkage.java	Wed Jul 05 17:04:56 2017 +0200
@@ -25,7 +25,9 @@
 
 package java.dyn;
 
+import java.dyn.MethodHandles.Lookup;
 import java.util.WeakHashMap;
+import sun.dyn.Access;
 import sun.reflect.Reflection;
 import static sun.dyn.util.VerifyAccess.checkBootstrapPrivilege;
 
@@ -34,6 +36,8 @@
  * @author John Rose, JSR 292 EG
  */
 public class Linkage {
+    private static final Access IMPL_TOKEN = Access.getToken();
+
     private Linkage() {}  // do not instantiate
 
     /**
@@ -53,19 +57,23 @@
      *     call to this method.
      * <li>The given class is already fully initialized.
      * <li>The given class is in the process of initialization, in another thread.
+     * <li>The same {@code CallSite} object has already been returned from
+     * a bootstrap method call to another {@code invokedynamic} call site.
      * </ul>
      * Because of these rules, a class may install its own bootstrap method in
      * a static initializer.
+     * @param callerClass a class that may have {@code invokedynamic} sites
+     * @param bootstrapMethod the method to use to bootstrap all such sites
      */
     public static
-    void registerBootstrapMethod(Class callerClass, MethodHandle mh) {
+    void registerBootstrapMethod(Class callerClass, MethodHandle bootstrapMethod) {
         Class callc = Reflection.getCallerClass(2);
         checkBootstrapPrivilege(callc, callerClass, "registerBootstrapMethod");
-        checkBSM(mh);
+        checkBSM(bootstrapMethod);
         synchronized (bootstrapMethods) {
             if (bootstrapMethods.containsKey(callerClass))
                 throw new IllegalStateException("bootstrap method already declared in "+callerClass);
-            bootstrapMethods.put(callerClass, mh);
+            bootstrapMethods.put(callerClass, bootstrapMethod);
         }
     }
 
@@ -88,8 +96,9 @@
     public static
     void registerBootstrapMethod(Class<?> runtime, String name) {
         Class callc = Reflection.getCallerClass(2);
+        Lookup lookup = new Lookup(IMPL_TOKEN, callc);
         MethodHandle bootstrapMethod =
-            MethodHandles.findStaticFrom(callc, runtime, name, BOOTSTRAP_METHOD_TYPE);
+            lookup.findStatic(runtime, name, BOOTSTRAP_METHOD_TYPE);
         // FIXME: exception processing wrong here
         checkBSM(bootstrapMethod);
         Linkage.registerBootstrapMethod(callc, bootstrapMethod);
@@ -106,8 +115,9 @@
     public static
     void registerBootstrapMethod(String name) {
         Class callc = Reflection.getCallerClass(2);
+        Lookup lookup = new Lookup(IMPL_TOKEN, callc);
         MethodHandle bootstrapMethod =
-            MethodHandles.findStaticFrom(callc, callc, name, BOOTSTRAP_METHOD_TYPE);
+            lookup.findStatic(callc, name, BOOTSTRAP_METHOD_TYPE);
         // FIXME: exception processing wrong here
         checkBSM(bootstrapMethod);
         Linkage.registerBootstrapMethod(callc, bootstrapMethod);
@@ -116,8 +126,7 @@
     /**
      * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
      * Report the bootstrap method registered for a given class.
-     * Returns null if the class has never yet registered a bootstrap method,
-     * or if the class has explicitly registered a null bootstrap method.
+     * Returns null if the class has never yet registered a bootstrap method.
      * Only callers privileged to set the bootstrap method may inquire
      * about it, because a bootstrap method is potentially a back-door entry
      * point into its class.
@@ -137,12 +146,12 @@
      * {@code (Class, String, MethodType)} returning a {@code CallSite}.
      */
     public static final MethodType BOOTSTRAP_METHOD_TYPE
-            = MethodType.make(CallSite.class,
-                              Class.class, String.class, MethodType.class);
+            = MethodType.methodType(CallSite.class,
+                                    Class.class, String.class, MethodType.class);
 
     private static final MethodType OLD_BOOTSTRAP_METHOD_TYPE
-            = MethodType.make(Object.class,
-                              CallSite.class, Object[].class);
+            = MethodType.methodType(Object.class,
+                                    CallSite.class, Object[].class);
 
     private static final WeakHashMap<Class, MethodHandle> bootstrapMethods =
             new WeakHashMap<Class, MethodHandle>();
@@ -173,8 +182,8 @@
 
     /**
      * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
-     * Invalidate all <code>invokedynamic</code> call sites associated
-     * with the given class.
+     * Invalidate all <code>invokedynamic</code> call sites in the bytecodes
+     * of any methods of the given class.
      * (These are exactly those sites which report the given class
      * via the {@link CallSite#callerClass()} method.)
      * <p>
--- a/jdk/src/share/classes/java/dyn/LinkagePermission.java	Thu Dec 17 14:10:20 2009 -0800
+++ b/jdk/src/share/classes/java/dyn/LinkagePermission.java	Wed Jul 05 17:04:56 2017 +0200
@@ -88,7 +88,7 @@
     /**
      * Create a new LinkagePermission with the given name.
      * The name is the symbolic name of the LinkagePermission, such as
-     * "registerBootstrapMethod", "invalidateClass.*", etc. An asterisk
+     * "registerBootstrapMethod", "invalidateCallerClass.*", etc. An asterisk
      * may appear at the end of the name, following a ".", or by itself, to
      * signify a wildcard match.
      *
--- a/jdk/src/share/classes/java/dyn/MethodHandle.java	Thu Dec 17 14:10:20 2009 -0800
+++ b/jdk/src/share/classes/java/dyn/MethodHandle.java	Wed Jul 05 17:04:56 2017 +0200
@@ -30,6 +30,9 @@
 import sun.dyn.Access;
 import sun.dyn.MethodHandleImpl;
 
+import static java.dyn.MethodHandles.invokers;  // package-private API
+import static sun.dyn.MemberName.newIllegalArgumentException;  // utility
+
 /**
  * A method handle is a typed reference to the entry point of a method.
  * <p>
@@ -45,8 +48,9 @@
  * Every method handle appears as an object containing a method named
  * <code>invoke</code>, whose signature exactly matches
  * the method handle's type.
- * A normal Java method call (using the <code>invokevirtual</code> instruction)
- * can invoke this method from Java source code (if language support is present).
+ * A Java method call expression, which compiles to an
+ * <code>invokevirtual</code> instruction,
+ * can invoke this method from Java source code.
  * <p>
  * Every call to a method handle specifies an intended method type,
  * which must exactly match the type of the method handle.
@@ -57,6 +61,10 @@
  * The call fails with a {@link WrongMethodTypeException}
  * if the method does not exist, even if there is an <code>invoke</code>
  * method of a closely similar signature.
+ * As with other kinds
+ * of methods in the JVM, signature matching during method linkage
+ * is exact, and does not allow for language-level implicit conversions
+ * such as {@code String} to {@code Object} or {@code short} to {@code int}.
  * <p>
  * A method handle is an unrestricted capability to call a method.
  * A method handle can be formed on a non-public method by a class
@@ -74,6 +82,15 @@
  * (after resolving symbolic type names) must exactly match the method type
  * of the target method.
  * <p>
+ * Every <code>invoke</code> method always throws {@link Exception},
+ * which is to say that there is no static restriction on what a method handle
+ * can throw.  Since the JVM does not distinguish between checked
+ * and unchecked exceptions (other than by their class, of course),
+ * there is no particular effect on bytecode shape from ascribing
+ * checked exceptions to method handle invocations.  But in Java source
+ * code, methods which perform method handle calls must either explicitly
+ * throw {@code Exception}, or else must catch all checked exceptions locally.
+ * <p>
  * Bytecode in an extended JVM can directly obtain a method handle
  * for any accessible method from a <code>ldc</code> instruction
  * which refers to a <code>CONSTANT_Methodref</code> or
@@ -97,6 +114,59 @@
  * can also be created.  These do not perform virtual lookup based on
  * receiver type.  Such a method handle simulates the effect of
  * an <code>invokespecial</code> instruction to the same method.
+ * <p>
+ * Here are some examples of usage:
+ * <p><blockquote><pre>
+ * Object x, y; String s; int i;
+ * MethodType mt; MethodHandle mh;
+ * MethodHandles.Lookup lookup = MethodHandles.lookup();
+ * // mt is {(char,char) =&gt; String}
+ * mt = MethodType.make(String.class, char.class, char.class);
+ * mh = lookup.findVirtual(String.class, "replace", mt);
+ * // (Ljava/lang/String;CC)Ljava/lang/String;
+ * s = mh.&lt;String&gt;invoke("daddy",'d','n');
+ * assert(s.equals("nanny"));
+ * // weakly typed invocation (using MHs.invoke)
+ * s = (String) MethodHandles.invoke(mh, "sappy", 'p', 'v');
+ * assert(s.equals("savvy"));
+ * // mt is {Object[] =&gt; List}
+ * mt = MethodType.make(java.util.List.class, Object[].class);
+ * mh = lookup.findStatic(java.util.Arrays.class, "asList", mt);
+ * // mt is {(Object,Object,Object) =&gt; Object}
+ * mt = MethodType.makeGeneric(3);
+ * mh = MethodHandles.collectArguments(mh, mt);
+ * // mt is {(Object,Object,Object) =&gt; Object}
+ * // (Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
+ * x = mh.invoke((Object)1, (Object)2, (Object)3);
+ * assert(x.equals(java.util.Arrays.asList(1,2,3)));
+ * // mt is { =&gt; int}
+ * mt = MethodType.make(int.class);
+ * mh = lookup.findVirtual(java.util.List.class, "size", mt);
+ * // (Ljava/util/List;)I
+ * i = mh.&lt;int&gt;invoke(java.util.Arrays.asList(1,2,3));
+ * assert(i == 3);
+ * </pre></blockquote>
+ * Each of the above calls generates a single invokevirtual instruction
+ * with the name {@code invoke} and the type descriptors indicated in the comments.
+ * The argument types are taken directly from the actual arguments,
+ * while the return type is taken from the type parameter.
+ * (This type parameter may be a primitive, and it defaults to {@code Object}.)
+ * <p>
+ * <em>A note on generic typing:</em>  Method handles do not represent
+ * their function types in terms of Java parameterized (generic) types,
+ * because there are three mismatches between function types and parameterized
+ * Java types.
+ * <ol>
+ * <li>Method types range over all possible arities,
+ * from no arguments to an arbitrary number of arguments.
+ * Generics are not variadic, and so cannot represent this.</li>
+ * <li>Method types can specify arguments of primitive types,
+ * which Java generic types cannot range over.</li>
+ * <li>Higher order functions over method handles (combinators) are
+ * often generic across a wide range of function types, including
+ * those of multiple arities.  It is impossible to represent such
+ * genericity with a Java type parameter.</li>
+ * </ol>
  *
  * @see MethodType
  * @see MethodHandles
@@ -107,17 +177,19 @@
         // with a JVM change which moves the required hidden state onto this class.
         extends MethodHandleImpl
 {
-    // interface MethodHandle<T extends MethodType<R,A...>>
-    // { T type(); <R,A...> public R invoke(A...); }
+    private static Access IMPL_TOKEN = Access.getToken();
 
-    final private MethodType type;
+    // interface MethodHandle<R throws X extends Exception,A...>
+    // { MethodType<R throws X,A...> type(); public R invoke(A...) throws X; }
+
+    private MethodType type;
 
     /**
      * Report the type of this method handle.
      * Every invocation of this method handle must exactly match this type.
      * @return the method handle type
      */
-    public MethodType type() {
+    public final MethodType type() {
         return type;
     }
 
@@ -130,6 +202,369 @@
      */
     protected MethodHandle(Access token, MethodType type) {
         super(token);
+        Access.check(token);
+        this.type = type;
+    }
+
+    private void initType(MethodType type) {
+        type.getClass();  // elicit NPE
+        if (this.type != null)  throw new InternalError();
         this.type = type;
     }
+
+    static {
+        // This hack allows the implementation package special access to
+        // the internals of MethodHandle.  In particular, the MTImpl has all sorts
+        // of cached information useful to the implementation code.
+        MethodHandleImpl.setMethodHandleFriend(IMPL_TOKEN, new MethodHandleImpl.MethodHandleFriend() {
+            public void initType(MethodHandle mh, MethodType type) { mh.initType(type); }
+        });
+    }
+
+    /** The string of a direct method handle is the simple name of its target method.
+     * The string of an adapter or bound method handle is the string of its
+     * target method handle.
+     * The string of a Java method handle is the string of its entry point method,
+     * unless the Java method handle overrides the toString method.
+     */
+    @Override
+    public String toString() {
+        return MethodHandleImpl.getNameString(IMPL_TOKEN, this);
+    }
+
+    //// First draft of the "Method Handle Kernel API" discussed at the JVM Language Summit, 9/2009.
+    //// Implementations here currently delegate to statics in MethodHandles.  Some of those statics
+    //// will be deprecated.  Others will be kept as "algorithms" to supply degrees of freedom
+    //// not present in the Kernel API.
+
+    /**
+     * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
+     * Perform an exact invocation.  The signature at the call site of {@code invokeExact} must
+     * exactly match this method handle's {@code type}.
+     * No conversions are allowed on arguments or return values.
+     * <em>This is not yet implemented, pending required compiler and JVM support.</em>
+     */
+    public final <T> T invokeExact(Object... arguments) throws Throwable {
+        // This is an approximate implementation, which discards the caller's signature and refuses the call.
+        throw new InternalError("not yet implemented");
+    }
+
+    /**
+     * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
+     * Perform a generic invocation.  The signature at the call site of {@code invokeExact} must
+     * have the same arity as this method handle's {@code type}.
+     * The same conversions are allowed on arguments or return values as are supported by
+     * by {@link MethodHandles#convertArguments}.
+     * If the call site signature exactly matches this method handle's {@code type},
+     * the call proceeds as if by {@link #invokeExact}.
+     * <em>This is not fully implemented, pending required compiler and JVM support.</em>
+     */
+    // This is an approximate implementation, which discards the caller's signature.
+    // When it is made signature polymorphic, the overloadings will disappear.
+    public final <T> T invokeGeneric() throws Throwable {
+        MethodHandle invoker = invokers(this.type()).genericInvoker();
+        return invoker.<T>invoke(this);
+    }
+    public final <T> T invokeGeneric(Object a0) throws Throwable {
+        MethodHandle invoker = invokers(this.type()).genericInvoker();
+        return invoker.<T>invoke(this, a0);
+    }
+    public final <T> T invokeGeneric(Object a0, Object a1) throws Throwable {
+        MethodHandle invoker = invokers(this.type()).genericInvoker();
+        return invoker.<T>invoke(this, a0, a1);
+    }
+    public final <T> T invokeGeneric(Object a0, Object a1, Object a2) throws Throwable {
+        MethodHandle invoker = invokers(this.type()).genericInvoker();
+        return invoker.<T>invoke(this, a0, a1, a2);
+    }
+    public final <T> T invokeGeneric(Object a0, Object a1, Object a2, Object a3) throws Throwable {
+        MethodHandle invoker = invokers(this.type()).genericInvoker();
+        return invoker.<T>invoke(this, a0, a1, a2, a3);
+    }
+    public final <T> T invokeGeneric(Object a0, Object a1, Object a2, Object a3,
+                  Object a4) throws Throwable {
+        MethodHandle invoker = invokers(this.type()).genericInvoker();
+        return invoker.<T>invoke(this, a0, a1, a2, a3, a4);
+    }
+    public final <T> T invokeGeneric(Object a0, Object a1, Object a2, Object a3,
+                  Object a4, Object a5) throws Throwable {
+        MethodHandle invoker = invokers(this.type()).genericInvoker();
+        return invoker.<T>invoke(this, a0, a1, a2, a3, a4, a5);
+    }
+    public final <T> T invokeGeneric(Object a0, Object a1, Object a2, Object a3,
+                  Object a4, Object a5, Object a6) throws Throwable {
+        MethodHandle invoker = invokers(this.type()).genericInvoker();
+        return invoker.<T>invoke(this, a0, a1, a2, a3, a4, a5, a6);
+    }
+    public final <T> T invokeGeneric(Object a0, Object a1, Object a2, Object a3,
+                  Object a4, Object a5, Object a6, Object a7) throws Throwable {
+        MethodHandle invoker = invokers(this.type()).genericInvoker();
+        return invoker.<T>invoke(this, a0, a1, a2, a3, a4, a5, a6, a7);
+    }
+    public final <T> T invokeGeneric(Object a0, Object a1, Object a2, Object a3,
+                  Object a4, Object a5, Object a6, Object a7, Object a8) throws Throwable {
+        MethodHandle invoker = invokers(this.type()).genericInvoker();
+        return invoker.<T>invoke(this, a0, a1, a2, a3, a4, a5, a6, a7, a8);
+    }
+    public final <T> T invokeGeneric(Object a0, Object a1, Object a2, Object a3,
+                  Object a4, Object a5, Object a6, Object a7, Object a8, Object a9) throws Throwable {
+        MethodHandle invoker = invokers(this.type()).genericInvoker();
+        return invoker.<T>invoke(this, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9);
+    }
+
+    /**
+     * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
+     * Perform a varargs invocation, passing the arguments in the given array
+     * to the method handle, as if via {@link #invokeGeneric} from a call site
+     * which mentions only the type {@code Object}, and whose arity is the length
+     * of the argument array.
+     * <p>
+     * The length of the arguments array must equal the parameter count
+     * of the target's type.
+     * The arguments array is spread into separate arguments.
+     * <p>
+     * In order to match the type of the target, the following argument
+     * conversions are applied as necessary:
+     * <ul>
+     * <li>reference casting
+     * <li>unboxing
+     * </ul>
+     * The following conversions are not applied:
+     * <ul>
+     * <li>primitive conversions (e.g., {@code byte} to {@code int}
+     * <li>varargs conversions other than the initial spread
+     * <li>any application-specific conversions (e.g., string to number)
+     * </ul>
+     * The result returned by the call is boxed if it is a primitive,
+     * or forced to null if the return type is void.
+     * <p>
+     * This call is equivalent to the following code:
+     * <p><blockquote><pre>
+     *   MethodHandle invoker = MethodHandles.genericInvoker(this.type(), 0, true);
+     *   Object result = invoker.invoke(this, arguments);
+     * </pre></blockquote>
+     * @param arguments the arguments to pass to the target
+     * @return the result returned by the target
+     * @see MethodHandles#genericInvoker
+     */
+    public final Object invokeVarargs(Object[] arguments) throws Throwable {
+        int argc = arguments == null ? 0 : arguments.length;
+        MethodType type = type();
+        if (argc <= 10) {
+            MethodHandle invoker = MethodHandles.invokers(type).genericInvoker();
+            switch (argc) {
+                case 0:  return invoker.invoke(this);
+                case 1:  return invoker.invoke(this,
+                                    arguments[0]);
+                case 2:  return invoker.invoke(this,
+                                    arguments[0], arguments[1]);
+                case 3:  return invoker.invoke(this,
+                                    arguments[0], arguments[1], arguments[2]);
+                case 4:  return invoker.invoke(this,
+                                    arguments[0], arguments[1], arguments[2],
+                                    arguments[3]);
+                case 5:  return invoker.invoke(this,
+                                    arguments[0], arguments[1], arguments[2],
+                                    arguments[3], arguments[4]);
+                case 6:  return invoker.invoke(this,
+                                    arguments[0], arguments[1], arguments[2],
+                                    arguments[3], arguments[4], arguments[5]);
+                case 7:  return invoker.invoke(this,
+                                    arguments[0], arguments[1], arguments[2],
+                                    arguments[3], arguments[4], arguments[5],
+                                    arguments[6]);
+                case 8:  return invoker.invoke(this,
+                                    arguments[0], arguments[1], arguments[2],
+                                    arguments[3], arguments[4], arguments[5],
+                                    arguments[6], arguments[7]);
+                case 9:  return invoker.invoke(this,
+                                    arguments[0], arguments[1], arguments[2],
+                                    arguments[3], arguments[4], arguments[5],
+                                    arguments[6], arguments[7], arguments[8]);
+                case 10:  return invoker.invoke(this,
+                                    arguments[0], arguments[1], arguments[2],
+                                    arguments[3], arguments[4], arguments[5],
+                                    arguments[6], arguments[7], arguments[8],
+                                    arguments[9]);
+            }
+        }
+
+        // more than ten arguments get boxed in a varargs list:
+        MethodHandle invoker = MethodHandles.invokers(type).varargsInvoker(0);
+        return invoker.invoke(this, arguments);
+    }
+    /** Equivalent to {@code invokeVarargs(arguments.toArray())}. */
+    public final Object invokeVarargs(java.util.List<?> arguments) throws Throwable {
+        return invokeVarargs(arguments.toArray());
+    }
+
+    /*  --- this is intentionally NOT a javadoc yet ---
+     * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
+     * Produce an adapter method handle which adapts the type of the
+     * current method handle to a new type by pairwise argument conversion.
+     * The original type and new type must have the same number of arguments.
+     * The resulting method handle is guaranteed to confess a type
+     * which is equal to the desired new type.
+     * <p>
+     * If the original type and new type are equal, returns {@code this}.
+     * <p>
+     * The following conversions are applied as needed both to
+     * arguments and return types.  Let T0 and T1 be the differing
+     * new and old parameter types (or old and new return types)
+     * for corresponding values passed by the new and old method types.
+     * Given those types T0, T1, one of the following conversions is applied
+     * if possible:
+     * <ul>
+     * <li>If T0 and T1 are references, and T1 is not an interface type,
+     *     then a cast to T1 is applied.
+     *     (The types do not need to be related in any particular way.)
+     * <li>If T0 and T1 are references, and T1 is an interface type,
+     *     then the value of type T0 is passed as a T1 without a cast.
+     *     (This treatment of interfaces follows the usage of the bytecode verifier.)
+     * <li>If T0 and T1 are primitives, then a Java casting
+     *     conversion (JLS 5.5) is applied, if one exists.
+     * <li>If T0 and T1 are primitives and one is boolean,
+     *     the boolean is treated as a one-bit unsigned integer.
+     *     (This treatment follows the usage of the bytecode verifier.)
+     *     A conversion from another primitive type behaves as if
+     *     it first converts to byte, and then masks all but the low bit.
+     * <li>If T0 is a primitive and T1 a reference, a boxing
+     *     conversion is applied if one exists, possibly followed by
+     *     an reference conversion to a superclass.
+     *     T1 must be a wrapper class or a supertype of one.
+     *     If T1 is a wrapper class, T0 is converted if necessary
+     *     to T1's primitive type by one of the preceding conversions.
+     *     Otherwise, T0 is boxed, and its wrapper converted to T1.
+     * <li>If T0 is a reference and T1 a primitive, an unboxing
+     *     conversion is applied if one exists, possibly preceded by
+     *     a reference conversion to a wrapper class.
+     *     T0 must be a wrapper class or a supertype of one.
+     *     If T0 is a wrapper class, its primitive value is converted
+     *     if necessary to T1 by one of the preceding conversions.
+     *     Otherwise, T0 is converted directly to the wrapper type for T1,
+     *     which is then unboxed.
+     * <li>If the return type T1 is void, any returned value is discarded
+     * <li>If the return type T0 is void and T1 a reference, a null value is introduced.
+     * <li>If the return type T0 is void and T1 a primitive, a zero value is introduced.
+     * </ul>
+     * <p>
+     */
+    /**
+     * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
+     * Produce an adapter method handle which adapts the type of the
+     * current method handle to a new type by pairwise argument conversion.
+     * The original type and new type must have the same number of arguments.
+     * The resulting method handle is guaranteed to confess a type
+     * which is equal to the desired new type.
+     * <p>
+     * If the original type and new type are equal, returns {@code this}.
+     * <p>
+     * This method is equivalent to {@link MethodHandles#convertArguments}.
+     * @param newType the expected type of the new method handle
+     * @return a method handle which delegates to {@code this} after performing
+     *           any necessary argument conversions, and arranges for any
+     *           necessary return value conversions
+     * @throws IllegalArgumentException if the conversion cannot be made
+     * @see MethodHandles#convertArguments
+     */
+    public final MethodHandle asType(MethodType newType) {
+        return MethodHandles.convertArguments(this, newType);
+    }
+
+    /**
+     * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
+     * Produce a method handle which adapts, as its <i>target</i>,
+     * the current method handle.  The type of the adapter will be
+     * the same as the type of the target, except that all but the first
+     * {@code keepPosArgs} parameters of the target's type are replaced
+     * by a single array parameter of type {@code Object[]}.
+     * Thus, if {@code keepPosArgs} is zero, the adapter will take all
+     * arguments in a single object array.
+     * <p>
+     * When called, the adapter replaces a trailing array argument
+     * by the array's elements, each as its own argument to the target.
+     * (The order of the arguments is preserved.)
+     * They are converted pairwise by casting and/or unboxing
+     * (as if by {@link MethodHandles#convertArguments})
+     * to the types of the trailing parameters of the target.
+     * Finally the target is called.
+     * What the target eventually returns is returned unchanged by the adapter.
+     * <p>
+     * Before calling the target, the adapter verifies that the array
+     * contains exactly enough elements to provide a correct argument count
+     * to the target method handle.
+     * (The array may also be null when zero elements are required.)
+     * @param keepPosArgs the number of leading positional arguments to preserve
+     * @return a new method handle which spreads its final argument,
+     *         before calling the original method handle
+     * @throws IllegalArgumentException if target does not have at least
+     *         {@code keepPosArgs} parameter types
+     */
+    public final MethodHandle asSpreader(int keepPosArgs) {
+        MethodType oldType = type();
+        int nargs = oldType.parameterCount();
+        MethodType newType = oldType.dropParameterTypes(keepPosArgs, nargs);
+        newType = newType.insertParameterTypes(keepPosArgs, Object[].class);
+        return MethodHandles.spreadArguments(this, newType);
+    }
+
+    /**
+     * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
+     * Produce a method handle which adapts, as its <i>target</i>,
+     * the current method handle.  The type of the adapter will be
+     * the same as the type of the target, except that a single trailing
+     * array parameter of type {@code Object[]} is replaced by
+     * {@code spreadArrayArgs} parameters of type {@code Object}.
+     * <p>
+     * When called, the adapter replaces its trailing {@code spreadArrayArgs}
+     * arguments by a single new {@code Object} array, whose elements
+     * comprise (in order) the replaced arguments.
+     * Finally the target is called.
+     * What the target eventually returns is returned unchanged by the adapter.
+     * <p>
+     * (The array may also be a shared constant when {@code spreadArrayArgs} is zero.)
+     * @param spreadArrayArgs the number of arguments to spread from the trailing array
+     * @return a new method handle which collects some trailing argument
+     *         into an array, before calling the original method handle
+     * @throws IllegalArgumentException if the last argument of the target
+     *         is not {@code Object[]}
+     * @throws IllegalArgumentException if {@code spreadArrayArgs} is not
+     *         a legal array size
+     * @deprecated Provisional and unstable; use {@link MethodHandles#collectArguments}.
+     */
+    public final MethodHandle asCollector(int spreadArrayArgs) {
+        MethodType oldType = type();
+        int nargs = oldType.parameterCount();
+        MethodType newType = oldType.dropParameterTypes(nargs-1, nargs);
+        newType = newType.insertParameterTypes(nargs-1, MethodType.genericMethodType(spreadArrayArgs).parameterArray());
+        return MethodHandles.collectArguments(this, newType);
+    }
+
+    /**
+     * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
+     * Produce a method handle which binds the given argument
+     * to the current method handle as <i>target</i>.
+     * The type of the bound handle will be
+     * the same as the type of the target, except that a single leading
+     * reference parameter will be omitted.
+     * <p>
+     * When called, the bound handle inserts the given value {@code x}
+     * as a new leading argument to the target.  The other arguments are
+     * also passed unchanged.
+     * What the target eventually returns is returned unchanged by the bound handle.
+     * <p>
+     * The reference {@code x} must be convertible to the first parameter
+     * type of the target.
+     * @param x  the value to bind to the first argument of the target
+     * @return a new method handle which collects some trailing argument
+     *         into an array, before calling the original method handle
+     * @throws IllegalArgumentException if the target does not have a
+     *         leading parameter type that is a reference type
+     * @throws ClassCastException if {@code x} cannot be converted
+     *         to the leading parameter type of the target
+     * @deprecated Provisional and unstable; use {@link MethodHandles#insertArguments}.
+     */
+    public final MethodHandle bindTo(Object x) {
+        return MethodHandles.insertArguments(this, 0, x);
+    }
 }
--- a/jdk/src/share/classes/java/dyn/MethodHandles.java	Thu Dec 17 14:10:20 2009 -0800
+++ b/jdk/src/share/classes/java/dyn/MethodHandles.java	Wed Jul 05 17:04:56 2017 +0200
@@ -34,6 +34,7 @@
 import java.lang.reflect.Field;
 import java.lang.reflect.Method;
 import java.lang.reflect.Modifier;
+import java.util.List;
 import java.util.ArrayList;
 import java.util.Arrays;
 import sun.dyn.Invokers;
@@ -44,17 +45,14 @@
 
 /**
  * Fundamental operations and utilities for MethodHandle.
+ * They fall into several categories:
+ * <ul>
+ * <li>Reifying methods and fields.  This is subject to access checks.
+ * <li>Invoking method handles on dynamically typed arguments and/or varargs arrays.
+ * <li>Combining or transforming pre-existing method handles into new ones.
+ * <li>Miscellaneous emulation of common JVM operations or control flow patterns.
+ * </ul>
  * <p>
- * <em>API Note:</em>  The matching of method types in this API cannot
- * be completely checked by Java's generic type system for three reasons:
- * <ol>
- * <li>Method types range over all possible arities,
- * from no arguments to an arbitrary number of arguments.
- * Generics are not variadic, and so cannot represent this.</li>
- * <li>Method types can specify arguments of primitive types,
- * which Java generic types cannot range over.</li>
- * <li>Method types can optionally specify varargs (ellipsis).</li>
- * </ol>
  * @author John Rose, JSR 292 EG
  */
 public class MethodHandles {
@@ -68,12 +66,22 @@
 
     //// Method handle creation from ordinary methods.
 
+    /** Create a {@link Lookup} lookup object on the caller.
+     *
+     */
     public static Lookup lookup() {
         return new Lookup();
     }
 
+    /** Version of lookup which is trusted minimally.
+     *  It can only be used to create method handles to
+     *  publicly accessible members.
+     */
+    public static Lookup publicLookup() {
+        return Lookup.PUBLIC_LOOKUP;
+    }
+
     /**
-     * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
      * A factory object for creating method handles, when the creation
      * requires access checking.  Method handles do not perform
      * access checks when they are called; this is a major difference
@@ -121,7 +129,8 @@
         /** Which class is performing the lookup?  It is this class against
          *  which checks are performed for visibility and access permissions.
          *  <p>
-         *  This value is null if and only if this lookup is {@link #PUBLIC_LOOKUP}.
+         *  This value is null if and only if this lookup was produced
+         *  by {@link MethodHandles#publicLookup}.
          */
         public Class<?> lookupClass() {
             return lookupClass;
@@ -135,23 +144,46 @@
          * an access$N method.
          */
         Lookup() {
-            Class caller = getCallerClassAtEntryPoint();
-            // make sure we haven't accidentally picked up this class:
-            checkUnprivilegedlookupClass(caller);
-            this.lookupClass = caller;
+            this(IMPL_TOKEN, getCallerClassAtEntryPoint());
+        }
+
+        Lookup(Access token, Class<?> lookupClass) {
+            // make sure we haven't accidentally picked up a privileged class:
+            checkUnprivilegedlookupClass(lookupClass);
+            this.lookupClass = lookupClass;
+        }
+
+        /**
+         * Create a lookup on the specified class.
+         * The result is guaranteed to have no more access privileges
+         * than the original.
+         */
+        public Lookup in(Class<?> newLookupClass) {
+            if (this == PUBLIC_LOOKUP)  return PUBLIC_LOOKUP;
+            if (newLookupClass == null)  return PUBLIC_LOOKUP;
+            if (newLookupClass == lookupClass)  return this;
+            if (this != IMPL_LOOKUP) {
+                if (!VerifyAccess.isSamePackage(lookupClass, newLookupClass))
+                    throw newNoAccessException(new MemberName(newLookupClass), this);
+                checkUnprivilegedlookupClass(newLookupClass);
+            }
+            return new Lookup(newLookupClass);
         }
 
         private Lookup(Class<?> lookupClass) {
             this.lookupClass = lookupClass;
         }
 
+        // Make sure outer class is initialized first.
+        static { IMPL_TOKEN.getClass(); }
+
         private static final Class<?> PUBLIC_ONLY = sun.dyn.empty.Empty.class;
 
         /** Version of lookup which is trusted minimally.
          *  It can only be used to create method handles to
          *  publicly accessible members.
          */
-        public static final Lookup PUBLIC_LOOKUP = new Lookup(PUBLIC_ONLY);
+        static final Lookup PUBLIC_LOOKUP = new Lookup(PUBLIC_ONLY);
 
         /** Package-private version of lookup which is trusted. */
         static final Lookup IMPL_LOOKUP = new Lookup(null);
@@ -178,12 +210,16 @@
             // 0: Reflection.getCC, 1: getCallerClassAtEntryPoint,
             // 2: Lookup.<init>, 3: MethodHandles.*, 4: caller
             // Note:  This should be the only use of getCallerClass in this file.
+            assert(Reflection.getCallerClass(CALLER_DEPTH-1) == MethodHandles.class);
             return Reflection.getCallerClass(CALLER_DEPTH);
         }
 
         /**
          * Produce a method handle for a static method.
          * The type of the method handle will be that of the method.
+         * (Since static methods do not take receivers, there is no
+         * additional receiver argument inserted into the method handle type,
+         * as there would be with {@linkplain #findVirtual} or {@linkplain #findSpecial}.)
          * The method and all its argument types must be accessible to the lookup class.
          * If the method's class has not yet been initialized, that is done
          * immediately, before the method handle is returned.
@@ -196,10 +232,11 @@
          */
         public
         MethodHandle findStatic(Class<?> defc, String name, MethodType type) throws NoAccessException {
-            MemberName method = IMPL_NAMES.resolveOrFail(new MemberName(defc, name, type, Modifier.STATIC), true, lookupClass);
-            checkStatic(true, method, lookupClass);
+            MemberName method = IMPL_NAMES.resolveOrFail(new MemberName(defc, name, type, Modifier.STATIC), true, lookupClass());
+            VerifyAccess.checkName(method, this);
+            checkStatic(true, method, this);
             //throw NoSuchMethodException
-            return MethodHandleImpl.findMethod(IMPL_TOKEN, method, false, lookupClass);
+            return MethodHandleImpl.findMethod(IMPL_TOKEN, method, false, lookupClass());
         }
 
         /**
@@ -228,9 +265,10 @@
          * @exception NoAccessException if the method does not exist or access checking fails
          */
         public MethodHandle findVirtual(Class<?> defc, String name, MethodType type) throws NoAccessException {
-            MemberName method = IMPL_NAMES.resolveOrFail(new MemberName(defc, name, type), true, lookupClass);
-            checkStatic(false, method, lookupClass);
-            return MethodHandleImpl.findMethod(IMPL_TOKEN, method, true, lookupClass);
+            MemberName method = IMPL_NAMES.resolveOrFail(new MemberName(defc, name, type), true, lookupClass());
+            VerifyAccess.checkName(method, this);
+            checkStatic(false, method, this);
+            return MethodHandleImpl.findMethod(IMPL_TOKEN, method, true, lookupClass());
         }
 
         /**
@@ -259,15 +297,17 @@
          */
         public MethodHandle findSpecial(Class<?> defc, String name, MethodType type,
                                         Class<?> specialCaller) throws NoAccessException {
-            checkSpecialCaller(specialCaller, lookupClass);
-            MemberName method = IMPL_NAMES.resolveOrFail(new MemberName(defc, name, type), false, specialCaller);
-            checkStatic(false, method, lookupClass);
+            checkSpecialCaller(specialCaller, this);
+            Lookup slookup = this.in(specialCaller);
+            MemberName method = IMPL_NAMES.resolveOrFail(new MemberName(defc, name, type), false, slookup.lookupClass());
+            VerifyAccess.checkName(method, this);
+            checkStatic(false, method, this);
             if (name.equals("<init>")) {
                 throw newNoAccessException("cannot directly invoke a constructor", method, null);
             } else if (defc.isInterface() || !defc.isAssignableFrom(specialCaller)) {
-                throw newNoAccessException("method must be in a superclass of lookup class", method, lookupClass);
+                throw newNoAccessException("method must be in a superclass of lookup class", method, slookup.lookupClass());
             }
-            return MethodHandleImpl.findMethod(IMPL_TOKEN, method, false, specialCaller);
+            return MethodHandleImpl.findMethod(IMPL_TOKEN, method, false, slookup.lookupClass());
         }
 
         /**
@@ -275,13 +315,19 @@
          * The receiver must have a supertype {@code defc} in which a method
          * of the given name and type is accessible to the lookup class.
          * The method and all its argument types must be accessible to the lookup class.
-         * The type of the method handle will be that of the method.
-         * The given receiver will be bound into the method handle.
+         * The type of the method handle will be that of the method,
+         * without any insertion of an additional receiver parameter.
+         * The given receiver will be bound into the method handle,
+         * so that every call to the method handle will invoke the
+         * requested method on the given receiver.
          * <p>
-         * Equivalent to the following expression:
+         * This is equivalent to the following expression:
          * <code>
-         * {@link #insertArgument}({@link #findVirtual}(defc, name, type), receiver)
+         * {@link #insertArguments}({@link #findVirtual}(defc, name, type), receiver)
          * </code>
+         * where {@code defc} is either {@code receiver.getClass()} or a super
+         * type of that class, in which the requested method is accessible
+         * to the lookup class.
          * @param receiver the object from which the method is accessed
          * @param name the name of the method
          * @param type the type of the method, with the receiver argument omitted
@@ -292,16 +338,18 @@
         public MethodHandle bind(Object receiver, String name, MethodType type) throws NoAccessException {
             Class<? extends Object> rcvc = receiver.getClass(); // may get NPE
             MemberName reference = new MemberName(rcvc, name, type);
-            MemberName method = IMPL_NAMES.resolveOrFail(reference, true, lookupClass);
-            checkStatic(false, method, lookupClass);
-            MethodHandle dmh = MethodHandleImpl.findMethod(IMPL_TOKEN, method, true, lookupClass);
+            MemberName method = IMPL_NAMES.resolveOrFail(reference, true, lookupClass());
+            VerifyAccess.checkName(method, this);
+            checkStatic(false, method, this);
+            MethodHandle dmh = MethodHandleImpl.findMethod(IMPL_TOKEN, method, true, lookupClass());
             MethodHandle bmh = MethodHandleImpl.bindReceiver(IMPL_TOKEN, dmh, receiver);
             if (bmh == null)
-                throw newNoAccessException(method, lookupClass);
+                throw newNoAccessException(method, this);
             return bmh;
         }
 
         /**
+         * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
          * Make a direct method handle to <i>m</i>, if the lookup class has permission.
          * If <i>m</i> is non-static, the receiver argument is treated as an initial argument.
          * If <i>m</i> is virtual, overriding is respected on every call.
@@ -316,10 +364,11 @@
          * @exception NoAccessException if access checking fails
          */
         public MethodHandle unreflect(Method m) throws NoAccessException {
-            return unreflectImpl(new MemberName(m), m.isAccessible(), true, lookupClass);
+            return unreflectImpl(new MemberName(m), m.isAccessible(), true, false, this);
         }
 
         /**
+         * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
          * Produce a method handle for a reflected method.
          * It will bypass checks for overriding methods on the receiver,
          * as if by the {@code invokespecial} instruction.
@@ -333,37 +382,41 @@
          * @exception NoAccessException if access checking fails
          */
         public MethodHandle unreflectSpecial(Method m, Class<?> specialCaller) throws NoAccessException {
-            checkSpecialCaller(specialCaller, lookupClass);
+            checkSpecialCaller(specialCaller, this);
+            Lookup slookup = this.in(specialCaller);
             MemberName mname = new MemberName(m);
-            checkStatic(false, mname, lookupClass);
-            return unreflectImpl(mname, m.isAccessible(), false, specialCaller);
+            checkStatic(false, mname, this);
+            return unreflectImpl(mname, m.isAccessible(), false, false, slookup);
         }
 
         /**
+         * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
          * Produce a method handle for a reflected constructor.
-         * The type of the method handle will be that of the constructor.
+         * The type of the method handle will be that of the constructor,
+         * with the return type changed to the declaring class.
          * The method handle will perform a {@code newInstance} operation,
          * creating a new instance of the constructor's class on the
          * arguments passed to the method handle.
          * <p>
          * If the constructor's {@code accessible} flag is not set,
-         * access checking is performed immediately on behalf of the lookup class,
-         * as if {@code invokespecial} instruction were being linked.
+         * access checking is performed immediately on behalf of the lookup class.
          * @param ctor the reflected constructor
          * @return a method handle which can invoke the reflected constructor
          * @exception NoAccessException if access checking fails
          */
         public MethodHandle unreflectConstructor(Constructor ctor) throws NoAccessException {
             MemberName m = new MemberName(ctor);
-            return unreflectImpl(m, ctor.isAccessible(), false, lookupClass);
+            return unreflectImpl(m, ctor.isAccessible(), false, false, this);
         }
 
         /**
          * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
          * Produce a method handle giving read access to a reflected field.
          * The type of the method handle will have a return type of the field's
-         * value type.  Its sole argument will be the field's containing class
-         * (but only if it is non-static).
+         * value type.
+         * If the field is static, the method handle will take no arguments.
+         * Otherwise, its single argument will be the instance containing
+         * the field.
          * If the method's {@code accessible} flag is not set,
          * access checking is performed immediately on behalf of the lookup class.
          * @param f the reflected field
@@ -371,16 +424,18 @@
          * @exception NoAccessException if access checking fails
          */
         public MethodHandle unreflectGetter(Field f) throws NoAccessException {
-            return MethodHandleImpl.accessField(IMPL_TOKEN, new MemberName(f), false, lookupClass);
+            MemberName m = new MemberName(f);
+            return unreflectImpl(m, f.isAccessible(), false, false, this);
         }
 
         /**
          * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
          * Produce a method handle giving write access to a reflected field.
          * The type of the method handle will have a void return type.
-         * Its last argument will be the field's value type.
-         * Its other argument will be the field's containing class
-         * (but only if it is non-static).
+         * If the field is static, the method handle will take a single
+         * argument, of the field's value type, the value to be stored.
+         * Otherwise, the two arguments will be the instance containing
+         * the field, and the value to be stored.
          * If the method's {@code accessible} flag is not set,
          * access checking is performed immediately on behalf of the lookup class.
          * @param f the reflected field
@@ -388,59 +443,75 @@
          * @exception NoAccessException if access checking fails
          */
         public MethodHandle unreflectSetter(Field f) throws NoAccessException {
-            return MethodHandleImpl.accessField(IMPL_TOKEN, new MemberName(f), true, lookupClass);
+            MemberName m = new MemberName(f);
+            return unreflectImpl(m, f.isAccessible(), false, true, this);
         }
 
     }
 
     static /*must not be public*/
-    MethodHandle findStaticFrom(Class<?> lookupClass,
+    MethodHandle findStaticFrom(Lookup lookup,
                                 Class<?> defc, String name, MethodType type) throws NoAccessException {
-        MemberName method = IMPL_NAMES.resolveOrFail(new MemberName(defc, name, type, Modifier.STATIC), true, lookupClass);
-        checkStatic(true, method, lookupClass);
-        return MethodHandleImpl.findMethod(IMPL_TOKEN, method, false, lookupClass);
+        MemberName method = IMPL_NAMES.resolveOrFail(new MemberName(defc, name, type, Modifier.STATIC), true, lookup.lookupClass());
+        VerifyAccess.checkName(method, lookup);
+        checkStatic(true, method, lookup);
+        return MethodHandleImpl.findMethod(IMPL_TOKEN, method, false, lookup.lookupClass());
     }
 
-    static void checkStatic(boolean wantStatic, MemberName m, Class<?> lookupClass) {
+    static void checkStatic(boolean wantStatic, MemberName m, Lookup lookup) {
         if (wantStatic != m.isStatic()) {
             String message = wantStatic ? "expected a static method" : "expected a non-static method";
-            throw newNoAccessException(message, m, lookupClass);
+            throw newNoAccessException(message, m, lookup.lookupClass());
         }
     }
 
-    static void checkSpecialCaller(Class<?> specialCaller, Class<?> lookupClass) {
-        if (lookupClass == Lookup.IMPL_LOOKUP.lookupClass())
+    static void checkSpecialCaller(Class<?> specialCaller, Lookup lookup) {
+        if (lookup == Lookup.IMPL_LOOKUP)
             return;  // privileged action
-        if (lookupClass == null ||  // public-only access
-            !VerifyAccess.isSamePackageMember(specialCaller, lookupClass))
-            throw newNoAccessException("no private access", new MemberName(specialCaller), lookupClass);
+        assert(lookup.lookupClass() != null);
+        if (!VerifyAccess.isSamePackageMember(specialCaller, lookup.lookupClass()))
+            throw newNoAccessException("no private access", new MemberName(specialCaller), lookup.lookupClass());
     }
 
     // Helper for creating handles on reflected methods and constructors.
     static MethodHandle unreflectImpl(MemberName m, boolean isAccessible,
-                                      boolean doDispatch, Class<?> lookupClass) {
-        MethodType mtype = m.getInvocationType();
+                                      boolean doDispatch, boolean isSetter, Lookup lookup) {
+        MethodType narrowMethodType = null;
         Class<?> defc = m.getDeclaringClass();
+        boolean isSpecialInvoke = m.isInvocable() && !doDispatch;
         int mods = m.getModifiers();
         if (m.isStatic()) {
             if (!isAccessible &&
-                    VerifyAccess.isAccessible(defc, mods, false, lookupClass) == null)
-                throw newNoAccessException(m, lookupClass);
+                    VerifyAccess.isAccessible(defc, mods, lookup.lookupClass(), false) == null)
+                throw newNoAccessException(m, lookup);
         } else {
             Class<?> constraint;
             if (isAccessible) {
                 // abbreviated access check for "unlocked" method
-                constraint = doDispatch ? defc : lookupClass;
+                constraint = doDispatch ? defc : lookup.lookupClass();
             } else {
-                constraint = VerifyAccess.isAccessible(defc, mods, doDispatch, lookupClass);
+                constraint = VerifyAccess.isAccessible(defc, mods, lookup.lookupClass(), isSpecialInvoke);
+            }
+            if (constraint == null) {
+                throw newNoAccessException(m, lookup);
             }
             if (constraint != defc && !constraint.isAssignableFrom(defc)) {
                 if (!defc.isAssignableFrom(constraint))
-                    throw newNoAccessException("receiver must be in caller class", m, lookupClass);
-                mtype = mtype.changeParameterType(0, constraint);
+                    throw newNoAccessException("receiver must be in caller class", m, lookup.lookupClass());
+                if (m.isInvocable())
+                    narrowMethodType = m.getInvocationType().changeParameterType(0, constraint);
+                else if (m.isField())
+                    narrowMethodType = (!isSetter
+                                        ? MethodType.methodType(m.getFieldType(), constraint)
+                                        : MethodType.methodType(void.class, constraint, m.getFieldType()));
             }
         }
-        return MethodHandleImpl.findMethod(IMPL_TOKEN, m, doDispatch, lookupClass);
+        if (m.isInvocable())
+            return MethodHandleImpl.findMethod(IMPL_TOKEN, m, doDispatch, lookup.lookupClass());
+        else if (m.isField())
+            return MethodHandleImpl.accessField(IMPL_TOKEN, m, isSetter, lookup.lookupClass());
+        else
+            throw new InternalError();
     }
 
     /**
@@ -472,138 +543,104 @@
         return MethodHandleImpl.accessArrayElement(IMPL_TOKEN, arrayClass, true);
     }
 
-
     /// method handle invocation (reflective style)
 
     /**
-     * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
-     * Call the {@code invoke} method of a given method handle,
-     * with arguments that exactly match the parameter types of the method handle.
-     * The length of the arguments array must equal the parameter count
-     * of the target's type.
-     * The arguments array is spread into separate arguments, and
-     * basic reference and unboxing conversions are applied.
-     * <p>
-     * In order to match the type of the target, the following argument
-     * conversions are applied as necessary:
-     * <ul>
-     * <li>reference casting
-     * <li>unboxing
-     * </ul>
-     * The following conversions are not applied:
-     * <ul>
-     * <li>primitive conversions (e.g., {@code byte} to {@code int}
-     * <li>varargs conversions other than the initial spread
-     * <li>any application-specific conversions (e.g., string to number)
-     * </ul>
-     * The result returned by the call is boxed if it is a primitive,
-     * or forced to null if the return type is void.
-     * <p>
-     * This call is a convenience method for the following code:
-     * <pre>
-     *   MethodHandle invoker = MethodHandles.genericInvoker(target.type(), 0, true);
-     *   Object result = invoker.invoke(arguments);
-     * </pre>
-     * @param target the method handle to invoke
-     * @param arguments the arguments to pass to the target
-     * @return the result returned by the target
+     * @deprecated Alias for MethodHandle.invokeVarargs.
      */
+    @Deprecated
     public static
-    Object invoke(MethodHandle target, Object... arguments) {
-        int argc = arguments == null ? 0 : arguments.length;
-        MethodType type = target.type();
-        if (argc <= 4) {
-            MethodHandle invoker = invokers(type).genericInvoker();
-            switch (argc) {
-                case 0:  return invoker.<Object>invoke(target);
-                case 1:  return invoker.<Object>invoke(target,
-                                    arguments[0]);
-                case 2:  return invoker.<Object>invoke(target,
-                                    arguments[0], arguments[1]);
-                case 3:  return invoker.<Object>invoke(target,
-                                    arguments[0], arguments[1], arguments[2]);
-                case 4:  return invoker.<Object>invoke(target,
-                                    arguments[0], arguments[1], arguments[2], arguments[3]);
-            }
-        }
-        MethodHandle invoker = invokers(type).varargsInvoker();
-        return invoker.<Object>invoke(target, arguments);
+    Object invokeVarargs(MethodHandle target, Object... arguments) throws Throwable {
+        return target.invokeVarargs(arguments);
     }
 
-    public static
-    Object invoke_0(MethodHandle target) {
-        MethodHandle invoker = invokers(target.type()).genericInvoker();
-        return invoker.<Object>invoke(target);
-    }
-    public static
-    Object invoke_1(MethodHandle target, Object a0) {
-        MethodHandle invoker = invokers(target.type()).genericInvoker();
-        return invoker.<Object>invoke(target, a0);
-    }
+    /**
+     * @deprecated Alias for MethodHandle.invokeVarargs.
+     */
+    @Deprecated
     public static
-    Object invoke_2(MethodHandle target, Object a0, Object a1) {
-        MethodHandle invoker = invokers(target.type()).genericInvoker();
-        return invoker.<Object>invoke(target, a0, a1);
-    }
-    public static
-    Object invoke_3(MethodHandle target, Object a0, Object a1, Object a2) {
-        MethodHandle invoker = invokers(target.type()).genericInvoker();
-        return invoker.<Object>invoke(target, a0, a1, a2);
-    }
-    public static
-    Object invoke_4(MethodHandle target, Object a0, Object a1, Object a2, Object a3) {
-        MethodHandle invoker = invokers(target.type()).genericInvoker();
-        return invoker.<Object>invoke(target, a0, a1, a2, a3);
+    Object invoke(MethodHandle target, Object... arguments) throws Throwable {
+        return target.invokeVarargs(arguments);
     }
 
     /**
      * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
-     * Give a method handle which will invoke any method handle of the
+     * Produce a method handle which will invoke any method handle of the
      * given type on a standard set of {@code Object} type arguments.
-     * The the resulting invoker will be a method handle with the following
+     * The resulting invoker will be a method handle with the following
      * arguments:
      * <ul>
      * <li>a single {@code MethodHandle} target
-     * <li>zero or more {@code Object} values
-     * <li>an optional {@code Object[]} array containing more arguments
+     * <li>zero or more {@code Object} values (one for each argument in {@code type})
      * </ul>
-     * The invoker will spread the varargs array (if present), apply
+     * The invoker will apply reference casts as necessary and unbox primitive arguments,
+     * as if by {@link #convertArguments}.
+     * The return value of the invoker will be an {@code Object} reference,
+     * boxing a primitive value if the original type returns a primitive,
+     * and always null if the original type returns void.
+     * <p>
+     * This method is equivalent to the following code (though it may be more efficient):
+     * <p><blockquote><pre>
+     * MethodHandle invoker = exactInvoker(type);
+     * MethodType genericType = type.generic();
+     * genericType = genericType.insertParameterType(0, MethodHandle.class);
+     * return convertArguments(invoker, genericType);
+     * </pre></blockquote>
+     * @param type the type of target methods which the invoker will apply to
+     * @return a method handle suitable for invoking any method handle of the given type
+     */
+    static public
+    MethodHandle genericInvoker(MethodType type) {
+        return invokers(type).genericInvoker();
+    }
+
+    /**
+     * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
+     * Produce a method handle which will invoke any method handle of the
+     * given type on a standard set of {@code Object} type arguments
+     * and a single trailing {@code Object[]} array.
+     * The resulting invoker will be a method handle with the following
+     * arguments:
+     * <ul>
+     * <li>a single {@code MethodHandle} target
+     * <li>zero or more {@code Object} values (counted by {@code objectArgCount})
+     * <li>an {@code Object[]} array containing more arguments
+     * </ul>
+     * The invoker will spread the varargs array, apply
      * reference casts as necessary, and unbox primitive arguments.
      * The return value of the invoker will be an {@code Object} reference,
      * boxing a primitive value if the original type returns a primitive,
      * and always null if the original type returns void.
      * <p>
-     * This is a convenience method equivalent to the following code:
-     * <pre>
+     * This method is equivalent to the following code (though it may be more efficient):
+     * <p><blockquote><pre>
      * MethodHandle invoker = exactInvoker(type);
-     * MethodType genericType = MethodType.makeGeneric(objectArgCount, varargs);
-     * genericType = genericType.insertParameterType(0, MethodHandle.class);
-     * if (!varargs)
-     *     return convertArguments(invoker, genericType);
-     * else
-     *     return spreadArguments(invoker, genericType);
-     * </pre>
+     * MethodType vaType = MethodType.makeGeneric(objectArgCount, true);
+     * vaType = vaType.insertParameterType(0, MethodHandle.class);
+     * return spreadArguments(invoker, vaType);
+     * </pre></blockquote>
      * @param type the desired target type
      * @param objectArgCount number of fixed (non-varargs) {@code Object} arguments
-     * @param varargs if true, the invoker will accept a final {@code Object[]} argument
      * @return a method handle suitable for invoking any method handle of the given type
      */
     static public
-    MethodHandle genericInvoker(MethodType type, int objectArgCount, boolean varargs) {
-        return invokers(type).genericInvoker();
+    MethodHandle varargsInvoker(MethodType type, int objectArgCount) {
+        if (objectArgCount < 0 || objectArgCount > type.parameterCount())
+            throw new IllegalArgumentException("bad argument count "+objectArgCount);
+        return invokers(type).varargsInvoker(objectArgCount);
     }
 
     /**
      * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
-     * Give a method handle which will take a invoke any method handle of the
+     * Produce a method handle which will take a invoke any method handle of the
      * given type.  The resulting invoker will have a type which is
      * exactly equal to the desired type, except that it will accept
      * an additional leading argument of type {@code MethodHandle}.
      * <p>
-     * This is a convenience method equivalent to the following code:
-     * <pre>
-     *     MethodHandles.lookup().findVirtual(MethodHandle.class, "invoke", type);
-     * </pre>
+     * This method is equivalent to the following code (though it may be more efficient):
+     * <p><blockquote><pre>
+     * lookup().findVirtual(MethodHandle.class, "invoke", type);
+     * </pre></blockquote>
      * @param type the desired target type
      * @return a method handle suitable for invoking any method handle of the given type
      */
@@ -612,7 +649,30 @@
         return invokers(type).exactInvoker();
     }
 
-    static private Invokers invokers(MethodType type) {
+    /**
+     * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
+     * Produce a method handle equivalent to an invokedynamic instruction
+     * which has been linked to the given call site.
+     * Along with {@link Lookup#findVirtual}, {@link Lookup#findStatic},
+     * and {@link Lookup#findSpecial}, this completes the emulation
+     * of the JVM's {@code invoke} instructions.
+     * <p>This method is equivalent to the following code:
+     * <p><blockquote><pre>
+     * MethodHandle getTarget, invoker, result;
+     * getTarget = lookup().bind(site, "getTarget", methodType(MethodHandle.class));
+     * invoker = exactInvoker(site.type());
+     * result = foldArguments(invoker, getTarget)
+     * </pre></blockquote>
+     * @return a method handle which always invokes the call site's target
+     */
+    public static
+    MethodHandle dynamicInvoker(CallSite site) {
+        MethodHandle getTarget = MethodHandleImpl.bindReceiver(IMPL_TOKEN, CallSite.GET_TARGET, site);
+        MethodHandle invoker = exactInvoker(site.type());
+        return foldArguments(invoker, getTarget);
+    }
+
+    static Invokers invokers(MethodType type) {
         return MethodTypeImpl.invokers(IMPL_TOKEN, type);
     }
 
@@ -688,14 +748,11 @@
     /// method handle modification (creation from other method handles)
 
     /**
-     * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
      * Produce a method handle which adapts the type of the
-     * given method handle to a new type, by pairwise argument conversion,
-     * and/or varargs conversion.
-     * The original type and new type must have the same number of
-     * arguments, or else one or both them the must be varargs types.
+     * given method handle to a new type by pairwise argument conversion.
+     * The original type and new type must have the same number of arguments.
      * The resulting method handle is guaranteed to confess a type
-     * which is equal to the desired new type, with any varargs property erased.
+     * which is equal to the desired new type.
      * <p>
      * If the original type and new type are equal, returns target.
      * <p>
@@ -703,26 +760,15 @@
      * arguments and return types.  Let T0 and T1 be the differing
      * new and old parameter types (or old and new return types)
      * for corresponding values passed by the new and old method types.
-     * <p>
-     * If an ordinary (non-varargs) parameter of the new type is
-     * to be boxed in a varargs parameter of the old type of type T1[],
-     * then T1 is the element type of the varargs array.
-     * Otherwise, if a varargs parameter of the new type of type T0[]
-     * is to be spread into one or more outgoing old type parameters,
-     * then T0 is the element type of the
-     * If the new type is varargs and the old type is not, the varargs
-     * argument will be checked and must be a non-null array of exactly
-     * the right length.  If there are no parameters in the old type
-     * corresponding to the new varargs parameter, the varargs argument
-     * is also allowed to be null.
-     * <p>
      * Given those types T0, T1, one of the following conversions is applied
      * if possible:
      * <ul>
-     * <li>If T0 and T1 are references, then a cast to T2 is applied,
-     *     where T2 is Object if T1 is an interface, else T1.
-     *     (The types do not need to be related in any particular way.
-     *     The treatment of interfaces follows the usage of the bytecode verifier.)
+     * <li>If T0 and T1 are references, and T1 is not an interface type,
+     *     then a cast to T1 is applied.
+     *     (The types do not need to be related in any particular way.)
+     * <li>If T0 and T1 are references, and T1 is an interface type,
+     *     then the value of type T0 is passed as a T1 without a cast.
+     *     (This treatment of interfaces follows the usage of the bytecode verifier.)
      * <li>If T0 and T1 are primitives, then a Java casting
      *     conversion (JLS 5.5) is applied, if one exists.
      * <li>If T0 and T1 are primitives and one is boolean,
@@ -745,16 +791,17 @@
      *     if necessary to T1 by one of the preceding conversions.
      *     Otherwise, T0 is converted directly to the wrapper type for T1,
      *     which is then unboxed.
-     * <li>If T1 is void, any returned value is discarded
-     * <li>If T0 is void and T1 a reference, a null value is introduced.
-     * <li>If T0 is void and T1 a primitive, a zero value is introduced.
+     * <li>If the return type T1 is void, any returned value is discarded
+     * <li>If the return type T0 is void and T1 a reference, a null value is introduced.
+     * <li>If the return type T0 is void and T1 a primitive, a zero value is introduced.
      * </ul>
      * @param target the method handle to invoke after arguments are retyped
      * @param newType the expected type of the new method handle
      * @return a method handle which delegates to {@code target} after performing
      *           any necessary argument conversions, and arranges for any
      *           necessary return value conversions
-     * @throws WrongMethodTypeException if the conversion cannot be made
+     * @throws IllegalArgumentException if the conversion cannot be made
+     * @see MethodHandle#asType
      */
     public static
     MethodHandle convertArguments(MethodHandle target, MethodType newType) {
@@ -872,23 +919,17 @@
      * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
      * Produce a method handle which adapts the type of the
      * given method handle to a new type, by collecting a series of
-     * trailing arguments into an array.
-     * The resulting method handle is guaranteed to confess a type
-     * which is equal to the desired new type.
+     * trailing arguments as elements to a single argument array.
      * <p>
-     * This method is inverse to {@link #spreadArguments}.
+     * This method may be used as an inverse to {@link #spreadArguments}.
      * The final parameter type of the old type must be an array type T[],
      * which is the type of what is called the <i>spread</i> argument.
      * The trailing arguments of the new type which correspond to
      * the spread argument are all converted to type T and collected
      * into an array before the original method is called.
-     * <p>
-     * ISSUE: Unify this with combineArguments.  CollectArguments
-     * is combineArguments with (a) new Object[]{...} as a combiner,
-     * and (b) the combined arguments dropped, in favor of the combined result.
      * @param target the method handle to invoke after the argument is prepended
      * @param newType the expected type of the new method handle
-     * @return a new method handle which collects some trailings argument
+     * @return a new method handle which collects some trailing argument
      *         into an array, before calling the original method handle
      */
     public static
@@ -900,50 +941,72 @@
         int numCollect = (inargs - collectPos);
         if (collectPos < 0 || numCollect < 0)
             throw newIllegalArgumentException("wrong number of arguments");
-        return MethodHandleImpl.collectArguments(IMPL_TOKEN, target, newType, collectPos);
+        MethodHandle res = MethodHandleImpl.collectArguments(IMPL_TOKEN, target, newType, collectPos, null);
+        if (res == null) {
+            throw newIllegalArgumentException("cannot collect from "+newType+" to " +oldType);
+        }
+        return res;
     }
 
     /**
      * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
-     * Produce a method handle which calls the original method handle,
-     * after inserting the given argument at the given position.
-     * The type of the new method handle will drop the corresponding argument
-     * type from the original handle's type.
+     * Produce a method handle which calls the original method handle {@code target},
+     * after inserting the given argument(s) at the given position.
+     * The formal parameters to {@code target} which will be supplied by those
+     * arguments are called <em>bound parameters</em>, because the new method
+     * will contain bindings for those parameters take from {@code values}.
+     * The type of the new method handle will drop the types for the bound
+     * parameters from the original target type, since the new method handle
+     * will no longer require those arguments to be supplied by its callers.
      * <p>
-     * The given argument object must match the dropped argument type.
-     * If the dropped argument type is a primitive, the argument object
-     * must be a wrapper, and is unboxed to produce the primitive.
+     * Each given argument object must match the corresponding bound parameter type.
+     * If a bound parameter type is a primitive, the argument object
+     * must be a wrapper, and will be unboxed to produce the primitive value.
      * <p>
      * The  <i>pos</i> may range between zero and <i>N</i> (inclusively),
-     * where <i>N</i> is the number of argument types in <i>target</i>,
-     * meaning to insert the new argument as the first or last (respectively),
-     * or somewhere in between.
+     * where <i>N</i> is the number of argument types in resulting method handle
+     * (after bound parameter types are dropped).
      * @param target the method handle to invoke after the argument is inserted
      * @param pos where to insert the argument (zero for the first)
-     * @param value the argument to insert
+     * @param values the series of arguments to insert
      * @return a new method handle which inserts an additional argument,
      *         before calling the original method handle
      */
     public static
-    MethodHandle insertArgument(MethodHandle target, int pos, Object value) {
+    MethodHandle insertArguments(MethodHandle target, int pos, Object... values) {
+        int insCount = values.length;
         MethodType oldType = target.type();
         ArrayList<Class<?>> ptypes =
                 new ArrayList<Class<?>>(oldType.parameterList());
         int outargs = oldType.parameterCount();
-        int inargs  = outargs - 1;
-        if (pos < 0 || pos >= outargs)
+        int inargs  = outargs - insCount;
+        if (inargs < 0)
+            throw newIllegalArgumentException("too many values to insert");
+        if (pos < 0 || pos > inargs)
             throw newIllegalArgumentException("no argument type to append");
-        Class<?> valueType = ptypes.remove(pos);
-        value = checkValue(valueType, value);
-        if (pos == 0 && !valueType.isPrimitive()) {
-            // At least for now, make bound method handles a special case.
-            // This lets us get by with minimal JVM support, at the expense
-            // of generating signature-specific adapters as Java bytecodes.
-            MethodHandle bmh = MethodHandleImpl.bindReceiver(IMPL_TOKEN, target, value);
-            if (bmh != null)  return bmh;
-            // else fall through to general adapter machinery
+        MethodHandle result = target;
+        for (int i = 0; i < insCount; i++) {
+            Object value = values[i];
+            Class<?> valueType = oldType.parameterType(pos+i);
+            value = checkValue(valueType, value);
+            if (pos == 0 && !valueType.isPrimitive()) {
+                // At least for now, make bound method handles a special case.
+                MethodHandle bmh = MethodHandleImpl.bindReceiver(IMPL_TOKEN, result, value);
+                if (bmh != null) {
+                    result = bmh;
+                    continue;
+                }
+                // else fall through to general adapter machinery
+            }
+            result = MethodHandleImpl.bindArgument(IMPL_TOKEN, result, pos, value);
         }
-        return MethodHandleImpl.bindArgument(IMPL_TOKEN, target, pos, value);
+        return result;
+    }
+
+    @Deprecated // "use MethodHandles.insertArguments instead"
+    public static
+    MethodHandle insertArgument(MethodHandle target, int pos, Object value) {
+        return insertArguments(target, pos, value);
     }
 
     /**
@@ -953,10 +1016,25 @@
      * The type of the new method handle will insert the given argument
      * type(s), at that position, into the original handle's type.
      * <p>
-     * The <i>pos</i> may range between zero and <i>N-1</i>,
+     * The <i>pos</i> may range between zero and <i>N</i>,
      * where <i>N</i> is the number of argument types in <i>target</i>,
      * meaning to drop the first or last argument (respectively),
      * or an argument somewhere in between.
+     * <p>
+     * <b>Example:</b>
+     * <p><blockquote><pre>
+     *   MethodHandle cat = MethodHandles.lookup().
+     *     findVirtual(String.class, "concat", String.class, String.class);
+     *   System.out.println(cat.&lt;String&gt;invoke("x", "y")); // xy
+     *   MethodHandle d0 = dropArguments(cat, 0, String.class);
+     *   System.out.println(d0.&lt;String&gt;invoke("x", "y", "z")); // xy
+     *   MethodHandle d1 = dropArguments(cat, 1, String.class);
+     *   System.out.println(d1.&lt;String&gt;invoke("x", "y", "z")); // xz
+     *   MethodHandle d2 = dropArguments(cat, 2, String.class);
+     *   System.out.println(d2.&lt;String&gt;invoke("x", "y", "z")); // yz
+     *   MethodHandle d12 = dropArguments(cat, 1, String.class, String.class);
+     *   System.out.println(d12.&lt;String&gt;invoke("w", "x", "y", "z")); // wz
+     * </pre></blockquote>
      * @param target the method handle to invoke after the argument is dropped
      * @param valueTypes the type(s) of the argument to drop
      * @param pos which argument to drop (zero for the first)
@@ -964,20 +1042,150 @@
      *         before calling the original method handle
      */
     public static
-    MethodHandle dropArguments(MethodHandle target, int pos, Class<?>... valueTypes) {
-        if (valueTypes.length == 0)  return target;
+    MethodHandle dropArguments(MethodHandle target, int pos, List<Class<?>> valueTypes) {
+        if (valueTypes.size() == 0)  return target;
         MethodType oldType = target.type();
         int outargs = oldType.parameterCount();
-        int inargs  = outargs + valueTypes.length;
+        int inargs  = outargs + valueTypes.size();
         if (pos < 0 || pos >= inargs)
             throw newIllegalArgumentException("no argument type to remove");
         ArrayList<Class<?>> ptypes =
                 new ArrayList<Class<?>>(oldType.parameterList());
-        ptypes.addAll(pos, Arrays.asList(valueTypes));
-        MethodType newType = MethodType.make(oldType.returnType(), ptypes);
+        ptypes.addAll(pos, valueTypes);
+        MethodType newType = MethodType.methodType(oldType.returnType(), ptypes);
         return MethodHandleImpl.dropArguments(IMPL_TOKEN, target, newType, pos);
     }
 
+    public static
+    MethodHandle dropArguments(MethodHandle target, int pos, Class<?>... valueTypes) {
+        return dropArguments(target, pos, Arrays.asList(valueTypes));
+    }
+
+    /**
+     * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
+     * Adapt a target method handle {@code target} by pre-processing
+     * one or more of its arguments, each with its own unary filter function,
+     * and then calling the target with each pre-processed argument
+     * replaced by the result of its corresponding filter function.
+     * <p>
+     * The pre-processing is performed by one or more method handles,
+     * specified in the non-null elements of the {@code filters} array.
+     * (If there are no such elements, the original target is returned.)
+     * Each filter (that is, each non-null element of {@code filters})
+     * is applied to the corresponding argument of the adapter.
+     * <p>
+     * If a filter {@code F} applies to the {@code N}th argument of
+     * the method handle, then {@code F} must be a method handle which
+     * takes exactly one argument.  The type of {@code F}'s sole argument
+     * replaces the corresponding argument type of the target
+     * in the resulting adapted method handle.
+     * The return type of {@code F} must be identical to the corresponding
+     * parameter type of the target.
+     * <p>
+     * It is an error if there are non-null elements of {@code filters}
+     * which do not correspond to argument positions in the target.
+     * The actual length of the target array may be any number, it need
+     * not be the same as the parameter count of the target type.
+     * (This provides an easy way to filter just the first argument or two
+     * of a target method handle.)
+     * <p> Here is pseudocode for the resulting adapter:
+     * <blockquote><pre>
+     * // there are N arguments in the A sequence
+     * T target(A[N]...);
+     * [i&lt;N] V[i] filter[i](B[i]) = filters[i] ?: identity;
+     * T adapter(B[N]... b) {
+     *   A[N] a...;
+     *   [i&lt;N] a[i] = filter[i](b[i]);
+     *   return target(a...);
+     * }
+     * </pre></blockquote>
+     * @param target the method handle to invoke after arguments are filtered
+     * @param filters method handles to call initially on filtered arguments
+     * @return method handle which incorporates the specified argument filtering logic
+     * @throws IllegalArgumentException if a non-null element of {@code filters}
+     *          does not match a corresponding argument type of {@code target}
+     */
+    public static
+    MethodHandle filterArguments(MethodHandle target, MethodHandle... filters) {
+        MethodType targetType = target.type();
+        MethodHandle adapter = target;
+        MethodType adapterType = targetType;
+        int pos = -1, maxPos = targetType.parameterCount();
+        for (MethodHandle filter : filters) {
+            pos += 1;
+            if (filter == null)  continue;
+            if (pos >= maxPos)
+                throw newIllegalArgumentException("too many filters");
+            MethodType filterType = filter.type();
+            if (filterType.parameterCount() != 1
+                || filterType.returnType() != targetType.parameterType(pos))
+                throw newIllegalArgumentException("target and filter types do not match");
+            adapterType = adapterType.changeParameterType(pos, filterType.parameterType(0));
+            adapter = MethodHandleImpl.filterArgument(IMPL_TOKEN, adapter, pos, filter);
+        }
+        MethodType midType = adapter.type();
+        if (midType != adapterType)
+            adapter = MethodHandleImpl.convertArguments(IMPL_TOKEN, adapter, adapterType, midType, null);
+        return adapter;
+    }
+
+    /**
+     * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
+     * Adapt a target method handle {@code target} by pre-processing
+     * some of its arguments, and then calling the target with
+     * the result of the pre-processing, plus all original arguments.
+     * <p>
+     * The pre-processing is performed by a second method handle, the {@code combiner}.
+     * The first {@code N} arguments passed to the adapter,
+     * are copied to the combiner, which then produces a result.
+     * (Here, {@code N} is defined as the parameter count of the adapter.)
+     * After this, control passes to the {@code target}, with both the result
+     * of the combiner, and all the original incoming arguments.
+     * <p>
+     * The first argument type of the target must be identical with the
+     * return type of the combiner.
+     * The resulting adapter is the same type as the target, except that the
+     * initial argument type of the target is dropped.
+     * <p>
+     * (Note that {@link #dropArguments} can be used to remove any arguments
+     * that either the {@code combiner} or {@code target} does not wish to receive.
+     * If some of the incoming arguments are destined only for the combiner,
+     * consider using {@link #collectArguments} instead, since those
+     * arguments will not need to be live on the stack on entry to the
+     * target.)
+     * <p>
+     * The first argument of the target must be identical with the
+     * return value of the combiner.
+     * <p> Here is pseudocode for the resulting adapter:
+     * <blockquote><pre>
+     * // there are N arguments in the A sequence
+     * T target(V, A[N]..., B...);
+     * V combiner(A...);
+     * T adapter(A... a, B... b) {
+     *   V v = combiner(a...);
+     *   return target(v, a..., b...);
+     * }
+     * </pre></blockquote>
+     * @param target the method handle to invoke after arguments are combined
+     * @param combiner method handle to call initially on the incoming arguments
+     * @return method handle which incorporates the specified argument folding logic
+     * @throws IllegalArgumentException if the first argument type of
+     *          {@code target} is not the same as {@code combiner}'s return type,
+     *          or if the next {@code foldArgs} argument types of {@code target}
+     *          are not identical with the argument types of {@code combiner}
+     */
+    public static
+    MethodHandle foldArguments(MethodHandle target, MethodHandle combiner) {
+        MethodType targetType = target.type();
+        MethodType combinerType = combiner.type();
+        int foldArgs = combinerType.parameterCount();
+        boolean ok = (targetType.parameterCount() >= 1 + foldArgs);
+        if (!ok)
+            throw misMatchedTypes("target and combiner types", targetType, combinerType);
+        MethodType newType = targetType.dropParameterTypes(0, 1);
+        return MethodHandleImpl.foldArguments(IMPL_TOKEN, target, newType, combiner);
+    }
+
     /**
      * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
      * Make a method handle which adapts a target method handle,
@@ -985,18 +1193,18 @@
      * If the guard fails, a fallback handle is called instead.
      * All three method handles must have the same corresponding
      * argument and return types, except that the return type
-     * of the test must be boolean.
+     * of the test must be boolean, and the test is allowed
+     * to have fewer arguments than the other two method handles.
      * <p> Here is pseudocode for the resulting adapter:
      * <blockquote><pre>
-     * signature T(A...);
      * boolean test(A...);
-     * T target(A...);
-     * T fallback(A...);
-     * T adapter(A... a) {
+     * T target(A...,B...);
+     * T fallback(A...,B...);
+     * T adapter(A... a,B... b) {
      *   if (test(a...))
-     *     return target(a...);
+     *     return target(a..., b...);
      *   else
-     *     return fallback(a...);
+     *     return fallback(a..., b...);
      * }
      * </pre></blockquote>
      * @param test method handle used for test, must return boolean
@@ -1011,10 +1219,23 @@
     MethodHandle guardWithTest(MethodHandle test,
                                MethodHandle target,
                                MethodHandle fallback) {
-        if (target.type() != fallback.type())
-            throw newIllegalArgumentException("target and fallback types do not match");
-        if (target.type().changeReturnType(boolean.class) != test.type())
-            throw newIllegalArgumentException("target and test types do not match");
+        MethodType gtype = test.type();
+        MethodType ttype = target.type();
+        MethodType ftype = fallback.type();
+        if (ttype != ftype)
+            throw misMatchedTypes("target and fallback types", ttype, ftype);
+        MethodType gtype2 = ttype.changeReturnType(boolean.class);
+        if (gtype2 != gtype) {
+            if (gtype.returnType() != boolean.class)
+                throw newIllegalArgumentException("guard type is not a predicate "+gtype);
+            int gpc = gtype.parameterCount(), tpc = ttype.parameterCount();
+            if (gpc < tpc) {
+                test = dropArguments(test, gpc, ttype.parameterList().subList(gpc, tpc));
+                gtype = test.type();
+            }
+            if (gtype2 != gtype)
+                throw misMatchedTypes("target and test types", ttype, gtype);
+        }
         /* {
             MethodHandle invoke = findVirtual(MethodHandle.class, "invoke", target.type());
             static MethodHandle choose(boolean z, MethodHandle t, MethodHandle f) {
@@ -1027,7 +1248,7 @@
             }
             // choose = \z.(z ? target : fallback)
             MethodHandle choose = findVirtual(MethodHandles.class, "choose",
-                    MethodType.make(boolean.class, MethodHandle.class, MethodHandle.class));
+                    MethodType.methodType(boolean.class, MethodHandle.class, MethodHandle.class));
             choose = appendArgument(choose, target);
             choose = appendArgument(choose, fallback);
             MethodHandle dispatch = compose(choose, test);
@@ -1038,67 +1259,88 @@
         return MethodHandleImpl.makeGuardWithTest(IMPL_TOKEN, test, target, fallback);
     }
 
+    static RuntimeException misMatchedTypes(String what, MethodType t1, MethodType t2) {
+        return newIllegalArgumentException(what + " must match: " + t1 + " != " + t2);
+    }
+
     /**
      * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
-     * Adapt a target method handle {@code target} by first processing
-     * its arguments, and then calling the target.
-     * The initial processing is performed by a second method handle, the {@code combiner}.
-     * After this, control passes to the {@code target}, with the same arguments.
+     * Make a method handle which adapts a target method handle,
+     * by running it inside an exception handler.
+     * If the target returns normally, the adapter returns that value.
+     * If an exception matching the specified type is thrown, the fallback
+     * handle is called instead on the exception, plus the original arguments.
      * <p>
-     * The return value of the {@code combiner} is inserted into the argument list
-     * for the {@code target} at the indicated position {@code pos}, if it is non-negative.
-     * Except for this inserted argument (if any), the argument types of
-     * the target {@code target} and the {@code combiner} must be identical.
-     * <p>
-     * (Note that {@link #dropArguments} can be used to remove any arguments
-     * that either the {@code combiner} or {@code target} does not wish to receive.)
-     * <p>
-     * The combiner handle must have the same argument types as the
-     * target handle, but must return {@link MethodHandle} instead of
-     * the ultimate return type.  The returned method handle, in turn,
-     * is required to have exactly the given final method type.
+     * The handler must have leading parameter of {@code exType} or a supertype,
+     * followed by arguments which correspond <em>(how? TBD)</em> to
+     * all the parameters of the target.
+     * The target and handler must return the same type.
      * <p> Here is pseudocode for the resulting adapter:
      * <blockquote><pre>
-     * signature V(A[pos]..., B...);
-     * signature T(A[pos]..., V, B...);
-     * T target(A... a, V v, B... b);
-     * V combiner(A..., B...);
-     * T adapter(A... a, B... b) {
-     *   V v = combiner(a..., b...);
-     *   return target(a..., v, b...);
+     * T target(A...);
+     * T handler(ExType, A...);
+     * T adapter(A... a) {
+     *   try {
+     *     return target(a...);
+     *   } catch (ExType ex) {
+     *     return handler(ex, a...);
+     *   }
      * }
      * </pre></blockquote>
-     * @param target the method handle to invoke after arguments are combined
-     * @param pos where the return value of {@code combiner} is to
-     *          be inserted as an argument to {@code target}
-     * @param combiner method handle to call initially on the incoming arguments
-     * @return method handle which incorporates the specified dispatch logic
-     * @throws IllegalArgumentException if {@code combiner} does not itself
-     *          return either void or the {@code pos}-th argument of {@code target},
-     *          or does not have the same argument types as {@code target}
-     *          (minus the inserted argument)
+     * @param target method handle to call
+     * @param exType the type of exception which the handler will catch
+     * @param handler method handle to call if a matching exception is thrown
+     * @return method handle which incorporates the specified try/catch logic
+     * @throws IllegalArgumentException if {@code handler} does not accept
+     *          the given exception type, or if the method handle types do
+     *          not match in their return types and their
+     *          corresponding parameters
      */
     public static
-    MethodHandle combineArguments(MethodHandle target, int pos, MethodHandle combiner) {
-        MethodType mhType = target.type();
-        Class<?> combineType = combiner.type().returnType();
-        MethodType incomingArgs;
-        if (pos < 0) {
-            // No inserted argument; target & combiner must have same argument types.
-            incomingArgs = mhType;
-            if (!incomingArgs.changeReturnType(combineType).equals(combiner.type()))
-                throw newIllegalArgumentException("target and combiner types do not match");
-        } else {
-            // Inserted argument.
-            if (pos >= mhType.parameterCount()
-                || mhType.parameterType(pos) != combineType)
-                throw newIllegalArgumentException("inserted combiner argument does not match target");
-            incomingArgs = mhType.dropParameterType(pos);
-        }
-        if (!incomingArgs.changeReturnType(combineType).equals(combiner.type())) {
-            throw newIllegalArgumentException("target and combiner types do not match");
-        }
-        return MethodHandleImpl.combineArguments(IMPL_TOKEN, target, combiner, pos);
+    MethodHandle catchException(MethodHandle target,
+                                Class<? extends Throwable> exType,
+                                MethodHandle handler) {
+        MethodType targetType = target.type();
+        MethodType handlerType = handler.type();
+        boolean ok = (targetType.parameterCount() ==
+                      handlerType.parameterCount() - 1);
+//        for (int i = 0; ok && i < numExArgs; i++) {
+//            if (targetType.parameterType(i) != handlerType.parameterType(1+i))
+//                ok = false;
+//        }
+        if (!ok)
+            throw newIllegalArgumentException("target and handler types do not match");
+        return MethodHandleImpl.makeGuardWithCatch(IMPL_TOKEN, target, exType, handler);
     }
 
+    /**
+     * Produce a method handle which will throw exceptions of the given {@code exType}.
+     * The method handle will accept a single argument of {@code exType},
+     * and immediately throw it as an exception.
+     * The method type will nominally specify a return of {@code returnType}.
+     * The return type may be anything convenient:  It doesn't matter to the
+     * method handle's behavior, since it will never return normally.
+     */
+    public static
+    MethodHandle throwException(Class<?> returnType, Class<? extends Throwable> exType) {
+        return MethodHandleImpl.throwException(IMPL_TOKEN, MethodType.methodType(returnType, exType));
+    }
+
+    /** Alias for {@link MethodType#methodType}. */
+    @Deprecated // "use MethodType.methodType instead"
+    public static MethodType methodType(Class<?> rtype) {
+        return MethodType.methodType(rtype);
+    }
+
+    /** Alias for {@link MethodType#methodType}. */
+    @Deprecated // "use MethodType.methodType instead"
+    public static MethodType methodType(Class<?> rtype, Class<?> ptype) {
+        return MethodType.methodType(rtype, ptype);
+    }
+
+    /** Alias for {@link MethodType#methodType}. */
+    @Deprecated // "use MethodType.methodType instead"
+    public static MethodType methodType(Class<?> rtype, Class<?> ptype0, Class<?>... ptypes) {
+        return MethodType.methodType(rtype, ptype0, ptypes);
+    }
 }
--- a/jdk/src/share/classes/java/dyn/MethodType.java	Thu Dec 17 14:10:20 2009 -0800
+++ b/jdk/src/share/classes/java/dyn/MethodType.java	Wed Jul 05 17:04:56 2017 +0200
@@ -32,7 +32,7 @@
 import sun.dyn.Access;
 import sun.dyn.Invokers;
 import sun.dyn.MethodTypeImpl;
-import sun.dyn.util.BytecodeSignature;
+import sun.dyn.util.BytecodeDescriptor;
 import static sun.dyn.MemberName.newIllegalArgumentException;
 
 /**
@@ -63,7 +63,7 @@
 
     static {
         // This hack allows the implementation package special access to
-        // the internals of MethodType.  In particular, the Form has all sorts
+        // the internals of MethodType.  In particular, the MTImpl has all sorts
         // of cached information useful to the implementation code.
         MethodTypeImpl.setMethodTypeFriend(IMPL_TOKEN, new MethodTypeImpl.MethodTypeFriend() {
             public Class<?>[] ptypes(MethodType mt)        { return mt.ptypes; }
@@ -114,50 +114,75 @@
      * @throws IllegalArgumentException if any of the ptypes is void
      */
     public static
+    MethodType methodType(Class<?> rtype, Class<?>[] ptypes) {
+        return makeImpl(rtype, ptypes, false);
+    }
+    @Deprecated public static
     MethodType make(Class<?> rtype, Class<?>[] ptypes) {
-        return makeImpl(rtype, ptypes, false);
+        return methodType(rtype, ptypes);
     }
 
-    /** Convenience method for {@link #make(java.lang.Class, java.lang.Class[])}. */
+    /** Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[])}. */
     public static
+    MethodType methodType(Class<?> rtype, List<? extends Class<?>> ptypes) {
+        boolean notrust = false;  // random List impl. could return evil ptypes array
+        return makeImpl(rtype, ptypes.toArray(NO_PTYPES), notrust);
+    }
+    @Deprecated public static
     MethodType make(Class<?> rtype, List<? extends Class<?>> ptypes) {
-        return makeImpl(rtype, ptypes.toArray(NO_PTYPES), true);
+        return methodType(rtype, ptypes);
     }
 
-    /** Convenience method for {@link #make(java.lang.Class, java.lang.Class[])}.
+    /** Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[])}.
      *  The leading parameter type is prepended to the remaining array.
      */
     public static
-    MethodType make(Class<?> rtype, Class<?> ptype0, Class<?>... ptypes) {
+    MethodType methodType(Class<?> rtype, Class<?> ptype0, Class<?>... ptypes) {
         Class<?>[] ptypes1 = new Class<?>[1+ptypes.length];
         ptypes1[0] = ptype0;
         System.arraycopy(ptypes, 0, ptypes1, 1, ptypes.length);
         return makeImpl(rtype, ptypes1, true);
     }
+    @Deprecated public static
+    MethodType make(Class<?> rtype, Class<?> ptype0, Class<?>... ptypes) {
+        return methodType(rtype, ptype0, ptypes);
+    }
 
-    /** Convenience method for {@link #make(java.lang.Class, java.lang.Class[])}.
+    /** Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[])}.
      *  The resulting method has no parameter types.
      */
     public static
-    MethodType make(Class<?> rtype) {
+    MethodType methodType(Class<?> rtype) {
         return makeImpl(rtype, NO_PTYPES, true);
     }
+    @Deprecated public static
+    MethodType make(Class<?> rtype) {
+        return methodType(rtype);
+    }
 
-    /** Convenience method for {@link #make(java.lang.Class, java.lang.Class[])}.
+    /** Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[])}.
      *  The resulting method has the single given parameter type.
      */
     public static
-    MethodType make(Class<?> rtype, Class<?> ptype0) {
+    MethodType methodType(Class<?> rtype, Class<?> ptype0) {
         return makeImpl(rtype, new Class<?>[]{ ptype0 }, true);
     }
+    @Deprecated public static
+    MethodType make(Class<?> rtype, Class<?> ptype0) {
+        return methodType(rtype, ptype0);
+    }
 
-    /** Convenience method for {@link #make(java.lang.Class, java.lang.Class[])}.
+    /** Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[])}.
      *  The resulting method has the same parameter types as {@code ptypes},
      *  and the specified return type.
      */
     public static
+    MethodType methodType(Class<?> rtype, MethodType ptypes) {
+        return makeImpl(rtype, ptypes.ptypes, true);
+    }
+    @Deprecated public static
     MethodType make(Class<?> rtype, MethodType ptypes) {
-        return makeImpl(rtype, ptypes.ptypes, true);
+        return methodType(rtype, ptypes);
     }
 
     /**
@@ -202,15 +227,16 @@
     private static final MethodType[] objectOnlyTypes = new MethodType[20];
 
     /**
-     * Convenience method for {@link #make(java.lang.Class, java.lang.Class[], boolean)}.
-     * All parameters and the return type will be Object, except the final varargs parameter if any.
+     * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[])}.
+     * All parameters and the return type will be {@code Object},
+     * except the final varargs parameter if any, which will be {@code Object[]}.
      * @param objectArgCount number of parameters (excluding the varargs parameter if any)
-     * @param varargs whether there will be a varargs parameter, of type Object[]
+     * @param varargs whether there will be a varargs parameter, of type {@code Object[]}
      * @return a totally generic method type, given only its count of parameters and varargs
-     * @see #makeGeneric(int)
+     * @see #genericMethodType(int)
      */
     public static
-    MethodType makeGeneric(int objectArgCount, boolean varargs) {
+    MethodType genericMethodType(int objectArgCount, boolean varargs) {
         MethodType mt;
         int ivarargs = (!varargs ? 0 : 1);
         int ootIndex = objectArgCount*2 + ivarargs;
@@ -227,19 +253,27 @@
         }
         return mt;
     }
+    @Deprecated public static
+    MethodType makeGeneric(int objectArgCount, boolean varargs) {
+        return genericMethodType(objectArgCount, varargs);
+    }
 
     /**
      * All parameters and the return type will be Object.
      * @param objectArgCount number of parameters
      * @return a totally generic method type, given only its count of parameters
-     * @see #makeGeneric(int, boolean)
+     * @see #genericMethodType(int, boolean)
      */
     public static
+    MethodType genericMethodType(int objectArgCount) {
+        return genericMethodType(objectArgCount, false);
+    }
+    @Deprecated public static
     MethodType makeGeneric(int objectArgCount) {
-        return makeGeneric(objectArgCount, false);
+        return genericMethodType(objectArgCount);
     }
 
-    /** Convenience method for {@link #make(java.lang.Class, java.lang.Class[], boolean)}.
+    /** Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[])}.
      * @param num    the index (zero-based) of the parameter type to change
      * @param nptype a new parameter type to replace the old one with
      * @return the same type, except with the selected parameter changed
@@ -251,11 +285,10 @@
         return makeImpl(rtype, nptypes, true);
     }
 
-    /** Convenience method for {@link #make(java.lang.Class, java.lang.Class[], boolean)}.
-     * @param num    the position (zero-based) of the inserted parameter type
-     * @param nptype a new parameter type to insert into the parameter list
-     * @return the same type, except with the selected parameter inserted
+    /** Convenience method for {@link #insertParameterTypes}.
+     * @deprecated Use {@link #insertParameterTypes} instead.
      */
+    @Deprecated
     public MethodType insertParameterType(int num, Class<?> nptype) {
         int len = ptypes.length;
         Class<?>[] nptypes = Arrays.copyOfRange(ptypes, 0, len+1);
@@ -264,23 +297,73 @@
         return makeImpl(rtype, nptypes, true);
     }
 
-    /** Convenience method for {@link #make(java.lang.Class, java.lang.Class[], boolean)}.
-     * @param num    the index (zero-based) of the parameter type to remove
-     * @return the same type, except with the selected parameter removed
+    /** Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[])}.
+     * @param num    the position (zero-based) of the inserted parameter type(s)
+     * @param ptypesToInsert zero or more a new parameter types to insert into the parameter list
+     * @return the same type, except with the selected parameter(s) inserted
      */
-    public MethodType dropParameterType(int num) {
+    public MethodType insertParameterTypes(int num, Class<?>... ptypesToInsert) {
         int len = ptypes.length;
+        if (num < 0 || num > len)
+            throw newIllegalArgumentException("num="+num); //SPECME
+        int ilen = ptypesToInsert.length;
+        if (ilen == 0)  return this;
+        Class<?>[] nptypes = Arrays.copyOfRange(ptypes, 0, len+ilen);
+        System.arraycopy(nptypes, num, nptypes, num+ilen, len-num);
+        System.arraycopy(ptypesToInsert, 0, nptypes, num, ilen);
+        return makeImpl(rtype, nptypes, true);
+    }
+
+    /** Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[])}.
+     * @param num    the position (zero-based) of the inserted parameter type(s)
+     * @param ptypesToInsert zero or more a new parameter types to insert into the parameter list
+     * @return the same type, except with the selected parameter(s) inserted
+     */
+    public MethodType insertParameterTypes(int num, List<Class<?>> ptypesToInsert) {
+        return insertParameterTypes(num, ptypesToInsert.toArray(NO_PTYPES));
+    }
+
+    /** Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[])}.
+     * @param start  the index (zero-based) of the first parameter type to remove
+     * @param end    the index (greater than {@code start}) of the first parameter type after not to remove
+     * @return the same type, except with the selected parameter(s) removed
+     */
+    public MethodType dropParameterTypes(int start, int end) {
+        int len = ptypes.length;
+        if (!(0 <= start && start <= end && end <= len))
+            throw newIllegalArgumentException("start="+start+" end="+end); //SPECME
+        if (start == end)  return this;
         Class<?>[] nptypes;
-        if (num == 0) {
-            nptypes = Arrays.copyOfRange(ptypes, 1, len);
+        if (start == 0) {
+            if (end == len) {
+                // drop all parameters
+                nptypes = NO_PTYPES;
+            } else {
+                // drop initial parameter(s)
+                nptypes = Arrays.copyOfRange(ptypes, end, len);
+            }
         } else {
-            nptypes = Arrays.copyOfRange(ptypes, 0, len-1);
-            System.arraycopy(ptypes, num+1, nptypes, num, (len-1)-num);
+            if (end == len) {
+                // drop trailing parameter(s)
+                nptypes = Arrays.copyOfRange(ptypes, 0, start);
+            } else {
+                int tail = len - end;
+                nptypes = Arrays.copyOfRange(ptypes, 0, start + tail);
+                System.arraycopy(ptypes, end, nptypes, start, tail);
+            }
         }
         return makeImpl(rtype, nptypes, true);
     }
 
-    /** Convenience method for {@link #make(java.lang.Class, java.lang.Class[], boolean)}.
+    /** Convenience method for {@link #dropParameterTypes}.
+     * @deprecated Use {@link #dropParameterTypes} instead.
+     */
+    @Deprecated
+    public MethodType dropParameterType(int num) {
+        return dropParameterTypes(num, num+1);
+    }
+
+    /** Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[])}.
      * @param nrtype a return parameter type to replace the old one with
      * @return the same type, except with the return type change
      */
@@ -291,6 +374,7 @@
 
     /** Convenience method.
      * Report if this type contains a primitive argument or return value.
+     * The return type {@code void} counts as a primitive.
      * @return true if any of the types are primitives
      */
     public boolean hasPrimitives() {
@@ -300,39 +384,47 @@
     /** Convenience method.
      * Report if this type contains a wrapper argument or return value.
      * Wrappers are types which box primitive values, such as {@link Integer}.
+     * The reference type {@code java.lang.Void} counts as a wrapper.
      * @return true if any of the types are wrappers
      */
     public boolean hasWrappers() {
         return unwrap() != this;
     }
 
-    /** Convenience method for {@link #make(java.lang.Class, java.lang.Class[])}.
-     * Erase all reference types to Object.
+    /** Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[])}.
+     * Erase all reference types to {@code Object}.
+     * All primitive types (including {@code void}) will remain unchanged.
      * @return a version of the original type with all reference types replaced
      */
     public MethodType erase() {
         return form.erasedType();
     }
 
-    /** Convenience method for {@link #makeGeneric(int)}.
-     * Convert all types, both reference and primitive, to Object.
+    /** Convenience method for {@link #genericMethodType(int)}.
+     * Convert all types, both reference and primitive, to {@code Object}.
+     * The expression {@code type.wrap().erase()} produces the same value
+     * as {@code type.generic()}.
      * @return a version of the original type with all types replaced
      */
     public MethodType generic() {
-        return makeGeneric(parameterCount());
+        return genericMethodType(parameterCount());
     }
 
-    /** Convenience method for {@link #make(java.lang.Class, java.lang.Class[])}.
+    /** Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[])}.
      * Convert all primitive types to their corresponding wrapper types.
+     * All reference types (including wrapper types) will remain unchanged.
      * A {@code void} return type is changed to the type {@code java.lang.Void}.
+     * The expression {@code type.wrap().erase()} produces the same value
+     * as {@code type.generic()}.
      * @return a version of the original type with all primitive types replaced
      */
     public MethodType wrap() {
         return hasPrimitives() ? wrapWithPrims(this) : this;
     }
 
-    /** Convenience method for {@link #make(java.lang.Class, java.lang.Class[])}.
+    /** Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[])}.
      * Convert all wrapper types to their corresponding primitive types.
+     * All primitive types (including {@code void}) will remain unchanged.
      * A return type of {@code java.lang.Void} is changed to {@code void}.
      * @return a version of the original type with all wrapper types replaced
      */
@@ -391,6 +483,7 @@
 
     /**
      * Convenience method to present the arguments as an array.
+     * Changes to the array will not result in changes to the type.
      * @return the parameter types (as a fresh copy if necessary)
      */
     public Class<?>[] parameterArray() {
@@ -491,7 +584,7 @@
         return form.parameterSlotCount();
     }
 
-    /** Number of JVM stack slots which carry all parameters after
+    /** Number of JVM stack slots which carry all parameters including and after
      * the given position, which must be in the range of 0 to
      * {@code parameterCount} inclusive.  Successive parameters are
      * more shallowly stacked, and parameters are indexed in the bytecodes
@@ -532,7 +625,7 @@
         return form.returnSlotCount();
     }
 
-    /** Convenience method for {@link #make(java.lang.Class, java.lang.Class[])}.
+    /** Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[])}.
      * Find or create an instance (interned) of the given method type.
      * Any class or interface name embedded in the signature string
      * will be resolved by calling {@link ClassLoader#loadClass(java.lang.String)}
@@ -544,16 +637,16 @@
      * <p>
      * This method is included for the benfit of applications that must
      * generate bytecodes that process method handles and invokedynamic.
-     * @param bytecodeSignature a bytecode-level signature string "(T...)T"
+     * @param descriptor a bytecode-level signature string "(T...)T"
      * @param loader the class loader in which to look up the types
      * @return a method type matching the bytecode-level signature
      * @throws IllegalArgumentException if the string is not well-formed
      * @throws TypeNotPresentException if a named type cannot be found
      */
-    public static MethodType fromBytecodeString(String bytecodeSignature, ClassLoader loader)
+    public static MethodType fromMethodDescriptorString(String descriptor, ClassLoader loader)
         throws IllegalArgumentException, TypeNotPresentException
     {
-        List<Class<?>> types = BytecodeSignature.parseMethod(bytecodeSignature, loader);
+        List<Class<?>> types = BytecodeDescriptor.parseMethod(descriptor, loader);
         Class<?> rtype = types.remove(types.size() - 1);
         Class<?>[] ptypes = types.toArray(NO_PTYPES);
         return makeImpl(rtype, ptypes, true);
@@ -565,11 +658,21 @@
      * <p>
      * This method is included for the benfit of applications that must
      * generate bytecodes that process method handles and invokedynamic.
-     * {@link #fromBytecodeString(java.lang.String, java.lang.ClassLoader)},
+     * {@link #fromMethodDescriptorString(java.lang.String, java.lang.ClassLoader)},
      * because the latter requires a suitable class loader argument.
      * @return the bytecode signature representation
      */
+    public String toMethodDescriptorString() {
+        return BytecodeDescriptor.unparse(this);
+    }
+
+    /** Temporary alias for toMethodDescriptorString; delete after M3. */
     public String toBytecodeString() {
-        return BytecodeSignature.unparse(this);
+        return toMethodDescriptorString();
+    }
+    /** Temporary alias for fromMethodDescriptorString; delete after M3. */
+    public static MethodType fromBytecodeString(String descriptor, ClassLoader loader)
+        throws IllegalArgumentException, TypeNotPresentException {
+        return fromMethodDescriptorString(descriptor, loader);
     }
 }
--- a/jdk/src/share/classes/java/dyn/package-info.java	Thu Dec 17 14:10:20 2009 -0800
+++ b/jdk/src/share/classes/java/dyn/package-info.java	Wed Jul 05 17:04:56 2017 +0200
@@ -24,6 +24,7 @@
  */
 
 /**
+ * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
  * This package contains dynamic language support provided directly by
  * the Java core class libraries and virtual machine.
  * @author John Rose, JSR 292 EG
--- a/jdk/src/share/classes/java/lang/StrictMath.java	Thu Dec 17 14:10:20 2009 -0800
+++ b/jdk/src/share/classes/java/lang/StrictMath.java	Wed Jul 05 17:04:56 2017 +0200
@@ -26,6 +26,7 @@
 package java.lang;
 import java.util.Random;
 import sun.misc.FpUtils;
+import sun.misc.DoubleConsts;
 
 /**
  * The class {@code StrictMath} contains methods for performing basic
@@ -316,7 +317,9 @@
      *          floating-point value that is greater than or equal to
      *          the argument and is equal to a mathematical integer.
      */
-    public static native double ceil(double a);
+    public static double ceil(double a) {
+        return floorOrCeil(a, -0.0, 1.0, 1.0);
+    }
 
     /**
      * Returns the largest (closest to positive infinity)
@@ -333,7 +336,54 @@
      *          floating-point value that less than or equal to the argument
      *          and is equal to a mathematical integer.
      */
-    public static native double floor(double a);
+    public static double floor(double a) {
+        return floorOrCeil(a, -1.0, 0.0, -1.0);
+    }
+
+    /**
+     * Internal method to share logic between floor and ceil.
+     *
+     * @param a the value to be floored or ceiled
+     * @param negativeBoundary result for values in (-1, 0)
+     * @param positiveBoundary result for values in (0, 1)
+     * @param increment value to add when the argument is non-integral
+     */
+    private static double floorOrCeil(double a,
+                                      double negativeBoundary,
+                                      double positiveBoundary,
+                                      double sign) {
+        int exponent = Math.getExponent(a);
+
+        if (exponent < 0) {
+            /*
+             * Absolute value of argument is less than 1.
+             * floorOrceil(-0.0) => -0.0
+             * floorOrceil(+0.0) => +0.0
+             */
+            return ((a == 0.0) ? a :
+                    ( (a < 0.0) ?  negativeBoundary : positiveBoundary) );
+        } else if (exponent >= 52) {
+            /*
+             * Infinity, NaN, or a value so large it must be integral.
+             */
+            return a;
+        }
+        // Else the argument is either an integral value already XOR it
+        // has to be rounded to one.
+        assert exponent >= 0 && exponent <= 51;
+
+        long doppel = Double.doubleToRawLongBits(a);
+        long mask   = DoubleConsts.SIGNIF_BIT_MASK >> exponent;
+
+        if ( (mask & doppel) == 0L )
+            return a; // integral value
+        else {
+            double result = Double.longBitsToDouble(doppel & (~mask));
+            if (sign*a > 0.0)
+                result = result + sign;
+            return result;
+        }
+    }
 
     /**
      * Returns the {@code double} value that is closest in value
--- a/jdk/src/share/classes/java/lang/management/PlatformManagedObject.java	Thu Dec 17 14:10:20 2009 -0800
+++ b/jdk/src/share/classes/java/lang/management/PlatformManagedObject.java	Wed Jul 05 17:04:56 2017 +0200
@@ -32,7 +32,7 @@
  * for monitoring and managing a component in the Java platform.
  * Each platform managed object has a unique
  * <a href="ManagementFactory.html#MXBean">object name</a>
- * for the {@linkplain ManagementFactory.getPlatformMBeanServer
+ * for the {@linkplain ManagementFactory#getPlatformMBeanServer
  * platform MBeanServer} access.
  * All platform MXBeans will implement this interface.
  *
--- a/jdk/src/share/classes/java/nio/X-Buffer.java.template	Thu Dec 17 14:10:20 2009 -0800
+++ b/jdk/src/share/classes/java/nio/X-Buffer.java.template	Wed Jul 05 17:04:56 2017 +0200
@@ -32,24 +32,24 @@
 #end[char]
 
 /**
- * $A$ $fulltype$ buffer.
+ * $A$ $type$ buffer.
  *
  * <p> This class defines {#if[byte]?six:four} categories of operations upon
- * $fulltype$ buffers:
+ * $type$ buffers:
  *
  * <ul>
  *
  *   <li><p> Absolute and relative {@link #get() </code><i>get</i><code>} and
  *   {@link #put($type$) </code><i>put</i><code>} methods that read and write
- *   single $fulltype$s; </p></li>
+ *   single $type$s; </p></li>
  *
  *   <li><p> Relative {@link #get($type$[]) </code><i>bulk get</i><code>}
- *   methods that transfer contiguous sequences of $fulltype$s from this buffer
+ *   methods that transfer contiguous sequences of $type$s from this buffer
  *   into an array; {#if[!byte]?and}</p></li>
  *
  *   <li><p> Relative {@link #put($type$[]) </code><i>bulk put</i><code>}
- *   methods that transfer contiguous sequences of $fulltype$s from $a$
- *   $fulltype$ array{#if[char]?,&#32;a&#32;string,} or some other $fulltype$
+ *   methods that transfer contiguous sequences of $type$s from $a$
+ *   $type$ array{#if[char]?,&#32;a&#32;string,} or some other $type$
  *   buffer into this buffer;{#if[!byte]?&#32;and} </p></li>
  *
 #if[byte]
@@ -67,22 +67,22 @@
  *
  *   <li><p> Methods for {@link #compact </code>compacting<code>}, {@link
  *   #duplicate </code>duplicating<code>}, and {@link #slice
- *   </code>slicing<code>} $a$ $fulltype$ buffer.  </p></li>
+ *   </code>slicing<code>} $a$ $type$ buffer.  </p></li>
  *
  * </ul>
  *
- * <p> $Fulltype$ buffers can be created either by {@link #allocate
+ * <p> $Type$ buffers can be created either by {@link #allocate
  * </code><i>allocation</i><code>}, which allocates space for the buffer's
  *
 #if[byte]
  *
  * content, or by {@link #wrap($type$[]) </code><i>wrapping</i><code>} an
- * existing $fulltype$ array {#if[char]?or&#32;string} into a buffer.
+ * existing $type$ array {#if[char]?or&#32;string} into a buffer.
  *
 #else[byte]
  *
  * content, by {@link #wrap($type$[]) </code><i>wrapping</i><code>} an existing
- * $fulltype$ array {#if[char]?or&#32;string} into a buffer, or by creating a
+ * $type$ array {#if[char]?or&#32;string} into a buffer, or by creating a
  * <a href="ByteBuffer.html#views"><i>view</i></a> of an existing byte buffer.
  *
 #end[byte]
@@ -189,12 +189,12 @@
 *
 #if[!byte]
  *
- * <p> Like a byte buffer, $a$ $fulltype$ buffer is either <a
+ * <p> Like a byte buffer, $a$ $type$ buffer is either <a
  * href="ByteBuffer.html#direct"><i>direct</i> or <i>non-direct</i></a>.  A
- * $fulltype$ buffer created via the <tt>wrap</tt> methods of this class will
- * be non-direct.  $A$ $fulltype$ buffer created as a view of a byte buffer will
+ * $type$ buffer created via the <tt>wrap</tt> methods of this class will
+ * be non-direct.  $A$ $type$ buffer created as a view of a byte buffer will
  * be direct if, and only if, the byte buffer itself is direct.  Whether or not
- * $a$ $fulltype$ buffer is direct may be determined by invoking the {@link
+ * $a$ $type$ buffer is direct may be determined by invoking the {@link
  * #isDirect isDirect} method.  </p>
  *
 #end[!byte]
@@ -287,7 +287,7 @@
 #if[byte]
 
     /**
-     * Allocates a new direct $fulltype$ buffer.
+     * Allocates a new direct $type$ buffer.
      *
      * <p> The new buffer's position will be zero, its limit will be its
      * capacity, its mark will be undefined, and each of its elements will be
@@ -295,9 +295,9 @@
      * {@link #hasArray </code>backing array<code>} is unspecified.
      *
      * @param  capacity
-     *         The new buffer's capacity, in $fulltype$s
+     *         The new buffer's capacity, in $type$s
      *
-     * @return  The new $fulltype$ buffer
+     * @return  The new $type$ buffer
      *
      * @throws  IllegalArgumentException
      *          If the <tt>capacity</tt> is a negative integer
@@ -309,7 +309,7 @@
 #end[byte]
 
     /**
-     * Allocates a new $fulltype$ buffer.
+     * Allocates a new $type$ buffer.
      *
      * <p> The new buffer's position will be zero, its limit will be its
      * capacity, its mark will be undefined, and each of its elements will be
@@ -318,9 +318,9 @@
      * offset<code>} will be zero.
      *
      * @param  capacity
-     *         The new buffer's capacity, in $fulltype$s
+     *         The new buffer's capacity, in $type$s
      *
-     * @return  The new $fulltype$ buffer
+     * @return  The new $type$ buffer
      *
      * @throws  IllegalArgumentException
      *          If the <tt>capacity</tt> is a negative integer
@@ -332,9 +332,9 @@
     }
 
     /**
-     * Wraps $a$ $fulltype$ array into a buffer.
+     * Wraps $a$ $type$ array into a buffer.
      *
-     * <p> The new buffer will be backed by the given $fulltype$ array;
+     * <p> The new buffer will be backed by the given $type$ array;
      * that is, modifications to the buffer will cause the array to be modified
      * and vice versa.  The new buffer's capacity will be
      * <tt>array.length</tt>, its position will be <tt>offset</tt>, its limit
@@ -356,7 +356,7 @@
      *         <tt>array.length - offset</tt>.
      *         The new buffer's limit will be set to <tt>offset + length</tt>.
      *
-     * @return  The new $fulltype$ buffer
+     * @return  The new $type$ buffer
      *
      * @throws  IndexOutOfBoundsException
      *          If the preconditions on the <tt>offset</tt> and <tt>length</tt>
@@ -373,9 +373,9 @@
     }
 
     /**
-     * Wraps $a$ $fulltype$ array into a buffer.
+     * Wraps $a$ $type$ array into a buffer.
      *
-     * <p> The new buffer will be backed by the given $fulltype$ array;
+     * <p> The new buffer will be backed by the given $type$ array;
      * that is, modifications to the buffer will cause the array to be modified
      * and vice versa.  The new buffer's capacity and limit will be
      * <tt>array.length</tt>, its position will be zero, and its mark will be
@@ -386,7 +386,7 @@
      * @param  array
      *         The array that will back this buffer
      *
-     * @return  The new $fulltype$ buffer
+     * @return  The new $type$ buffer
      */
     public static $Type$Buffer wrap($type$[] array) {
         return wrap(array, 0, array.length);
@@ -486,7 +486,7 @@
 #end[char]
 
     /**
-     * Creates a new $fulltype$ buffer whose content is a shared subsequence of
+     * Creates a new $type$ buffer whose content is a shared subsequence of
      * this buffer's content.
      *
      * <p> The content of the new buffer will start at this buffer's current
@@ -495,17 +495,17 @@
      * values will be independent.
      *
      * <p> The new buffer's position will be zero, its capacity and its limit
-     * will be the number of $fulltype$s remaining in this buffer, and its mark
+     * will be the number of $type$s remaining in this buffer, and its mark
      * will be undefined.  The new buffer will be direct if, and only if, this
      * buffer is direct, and it will be read-only if, and only if, this buffer
      * is read-only.  </p>
      *
-     * @return  The new $fulltype$ buffer
+     * @return  The new $type$ buffer
      */
     public abstract $Type$Buffer slice();
 
     /**
-     * Creates a new $fulltype$ buffer that shares this buffer's content.
+     * Creates a new $type$ buffer that shares this buffer's content.
      *
      * <p> The content of the new buffer will be that of this buffer.  Changes
      * to this buffer's content will be visible in the new buffer, and vice
@@ -517,12 +517,12 @@
      * and only if, this buffer is direct, and it will be read-only if, and
      * only if, this buffer is read-only.  </p>
      *
-     * @return  The new $fulltype$ buffer
+     * @return  The new $type$ buffer
      */
     public abstract $Type$Buffer duplicate();
 
     /**
-     * Creates a new, read-only $fulltype$ buffer that shares this buffer's
+     * Creates a new, read-only $type$ buffer that shares this buffer's
      * content.
      *
      * <p> The content of the new buffer will be that of this buffer.  Changes
@@ -537,7 +537,7 @@
      * <p> If this buffer is itself read-only then this method behaves in
      * exactly the same way as the {@link #duplicate duplicate} method.  </p>
      *
-     * @return  The new, read-only $fulltype$ buffer
+     * @return  The new, read-only $type$ buffer
      */
     public abstract $Type$Buffer asReadOnlyBuffer();
 
@@ -545,10 +545,10 @@
     // -- Singleton get/put methods --
 
     /**
-     * Relative <i>get</i> method.  Reads the $fulltype$ at this buffer's
+     * Relative <i>get</i> method.  Reads the $type$ at this buffer's
      * current position, and then increments the position. </p>
      *
-     * @return  The $fulltype$ at the buffer's current position
+     * @return  The $type$ at the buffer's current position
      *
      * @throws  BufferUnderflowException
      *          If the buffer's current position is not smaller than its limit
@@ -558,11 +558,11 @@
     /**
      * Relative <i>put</i> method&nbsp;&nbsp;<i>(optional operation)</i>.
      *
-     * <p> Writes the given $fulltype$ into this buffer at the current
+     * <p> Writes the given $type$ into this buffer at the current
      * position, and then increments the position. </p>
      *
      * @param  $x$
-     *         The $fulltype$ to be written
+     *         The $type$ to be written
      *
      * @return  This buffer
      *
@@ -575,13 +575,13 @@
     public abstract $Type$Buffer put($type$ $x$);
 
     /**
-     * Absolute <i>get</i> method.  Reads the $fulltype$ at the given
+     * Absolute <i>get</i> method.  Reads the $type$ at the given
      * index. </p>
      *
      * @param  index
-     *         The index from which the $fulltype$ will be read
+     *         The index from which the $type$ will be read
      *
-     * @return  The $fulltype$ at the given index
+     * @return  The $type$ at the given index
      *
      * @throws  IndexOutOfBoundsException
      *          If <tt>index</tt> is negative
@@ -592,14 +592,14 @@
     /**
      * Absolute <i>put</i> method&nbsp;&nbsp;<i>(optional operation)</i>.
      *
-     * <p> Writes the given $fulltype$ into this buffer at the given
+     * <p> Writes the given $type$ into this buffer at the given
      * index. </p>
      *
      * @param  index
-     *         The index at which the $fulltype$ will be written
+     *         The index at which the $type$ will be written
      *
      * @param  $x$
-     *         The $fulltype$ value to be written
+     *         The $type$ value to be written
      *
      * @return  This buffer
      *
@@ -618,14 +618,14 @@
     /**
      * Relative bulk <i>get</i> method.
      *
-     * <p> This method transfers $fulltype$s from this buffer into the given
-     * destination array.  If there are fewer $fulltype$s remaining in the
+     * <p> This method transfers $type$s from this buffer into the given
+     * destination array.  If there are fewer $type$s remaining in the
      * buffer than are required to satisfy the request, that is, if
      * <tt>length</tt>&nbsp;<tt>&gt;</tt>&nbsp;<tt>remaining()</tt>, then no
-     * $fulltype$s are transferred and a {@link BufferUnderflowException} is
+     * $type$s are transferred and a {@link BufferUnderflowException} is
      * thrown.
      *
-     * <p> Otherwise, this method copies <tt>length</tt> $fulltype$s from this
+     * <p> Otherwise, this method copies <tt>length</tt> $type$s from this
      * buffer into the given array, starting at the current position of this
      * buffer and at the given offset in the array.  The position of this
      * buffer is then incremented by <tt>length</tt>.
@@ -638,26 +638,26 @@
      *     for (int i = off; i < off + len; i++)
      *         dst[i] = src.get(); </pre>
      *
-     * except that it first checks that there are sufficient $fulltype$s in
+     * except that it first checks that there are sufficient $type$s in
      * this buffer and it is potentially much more efficient. </p>
      *
      * @param  dst
-     *         The array into which $fulltype$s are to be written
+     *         The array into which $type$s are to be written
      *
      * @param  offset
-     *         The offset within the array of the first $fulltype$ to be
+     *         The offset within the array of the first $type$ to be
      *         written; must be non-negative and no larger than
      *         <tt>dst.length</tt>
      *
      * @param  length
-     *         The maximum number of $fulltype$s to be written to the given
+     *         The maximum number of $type$s to be written to the given
      *         array; must be non-negative and no larger than
      *         <tt>dst.length - offset</tt>
      *
      * @return  This buffer
      *
      * @throws  BufferUnderflowException
-     *          If there are fewer than <tt>length</tt> $fulltype$s
+     *          If there are fewer than <tt>length</tt> $type$s
      *          remaining in this buffer
      *
      * @throws  IndexOutOfBoundsException
@@ -677,7 +677,7 @@
     /**
      * Relative bulk <i>get</i> method.
      *
-     * <p> This method transfers $fulltype$s from this buffer into the given
+     * <p> This method transfers $type$s from this buffer into the given
      * destination array.  An invocation of this method of the form
      * <tt>src.get(a)</tt> behaves in exactly the same way as the invocation
      *
@@ -687,7 +687,7 @@
      * @return  This buffer
      *
      * @throws  BufferUnderflowException
-     *          If there are fewer than <tt>length</tt> $fulltype$s
+     *          If there are fewer than <tt>length</tt> $type$s
      *          remaining in this buffer
      */
     public $Type$Buffer get($type$[] dst) {
@@ -700,15 +700,15 @@
     /**
      * Relative bulk <i>put</i> method&nbsp;&nbsp;<i>(optional operation)</i>.
      *
-     * <p> This method transfers the $fulltype$s remaining in the given source
-     * buffer into this buffer.  If there are more $fulltype$s remaining in the
+     * <p> This method transfers the $type$s remaining in the given source
+     * buffer into this buffer.  If there are more $type$s remaining in the
      * source buffer than in this buffer, that is, if
      * <tt>src.remaining()</tt>&nbsp;<tt>&gt;</tt>&nbsp;<tt>remaining()</tt>,
-     * then no $fulltype$s are transferred and a {@link
+     * then no $type$s are transferred and a {@link
      * BufferOverflowException} is thrown.
      *
      * <p> Otherwise, this method copies
-     * <i>n</i>&nbsp;=&nbsp;<tt>src.remaining()</tt> $fulltype$s from the given
+     * <i>n</i>&nbsp;=&nbsp;<tt>src.remaining()</tt> $type$s from the given
      * buffer into this buffer, starting at each buffer's current position.
      * The positions of both buffers are then incremented by <i>n</i>.
      *
@@ -723,14 +723,14 @@
      * buffer and it is potentially much more efficient. </p>
      *
      * @param  src
-     *         The source buffer from which $fulltype$s are to be read;
+     *         The source buffer from which $type$s are to be read;
      *         must not be this buffer
      *
      * @return  This buffer
      *
      * @throws  BufferOverflowException
      *          If there is insufficient space in this buffer
-     *          for the remaining $fulltype$s in the source buffer
+     *          for the remaining $type$s in the source buffer
      *
      * @throws  IllegalArgumentException
      *          If the source buffer is this buffer
@@ -752,14 +752,14 @@
     /**
      * Relative bulk <i>put</i> method&nbsp;&nbsp;<i>(optional operation)</i>.
      *
-     * <p> This method transfers $fulltype$s into this buffer from the given
-     * source array.  If there are more $fulltype$s to be copied from the array
+     * <p> This method transfers $type$s into this buffer from the given
+     * source array.  If there are more $type$s to be copied from the array
      * than remain in this buffer, that is, if
      * <tt>length</tt>&nbsp;<tt>&gt;</tt>&nbsp;<tt>remaining()</tt>, then no
-     * $fulltype$s are transferred and a {@link BufferOverflowException} is
+     * $type$s are transferred and a {@link BufferOverflowException} is
      * thrown.
      *
-     * <p> Otherwise, this method copies <tt>length</tt> $fulltype$s from the
+     * <p> Otherwise, this method copies <tt>length</tt> $type$s from the
      * given array into this buffer, starting at the given offset in the array
      * and at the current position of this buffer.  The position of this buffer
      * is then incremented by <tt>length</tt>.
@@ -776,14 +776,14 @@
      * buffer and it is potentially much more efficient. </p>
      *
      * @param  src
-     *         The array from which $fulltype$s are to be read
+     *         The array from which $type$s are to be read
      *
      * @param  offset
-     *         The offset within the array of the first $fulltype$ to be read;
+     *         The offset within the array of the first $type$ to be read;
      *         must be non-negative and no larger than <tt>array.length</tt>
      *
      * @param  length
-     *         The number of $fulltype$s to be read from the given array;
+     *         The number of $type$s to be read from the given array;
      *         must be non-negative and no larger than
      *         <tt>array.length - offset</tt>
      *
@@ -813,7 +813,7 @@
      * Relative bulk <i>put</i> method&nbsp;&nbsp;<i>(optional operation)</i>.
      *
      * <p> This method transfers the entire content of the given source
-     * $fulltype$ array into this buffer.  An invocation of this method of the
+     * $type$ array into this buffer.  An invocation of this method of the
      * form <tt>dst.put(a)</tt> behaves in exactly the same way as the
      * invocation
      *
@@ -837,15 +837,15 @@
     /**
      * Relative bulk <i>put</i> method&nbsp;&nbsp;<i>(optional operation)</i>.
      *
-     * <p> This method transfers $fulltype$s from the given string into this
-     * buffer.  If there are more $fulltype$s to be copied from the string than
+     * <p> This method transfers $type$s from the given string into this
+     * buffer.  If there are more $type$s to be copied from the string than
      * remain in this buffer, that is, if
      * <tt>end&nbsp;-&nbsp;start</tt>&nbsp;<tt>&gt;</tt>&nbsp;<tt>remaining()</tt>,
-     * then no $fulltype$s are transferred and a {@link
+     * then no $type$s are transferred and a {@link
      * BufferOverflowException} is thrown.
      *
      * <p> Otherwise, this method copies
-     * <i>n</i>&nbsp;=&nbsp;<tt>end</tt>&nbsp;-&nbsp;<tt>start</tt> $fulltype$s
+     * <i>n</i>&nbsp;=&nbsp;<tt>end</tt>&nbsp;-&nbsp;<tt>start</tt> $type$s
      * from the given string into this buffer, starting at the given
      * <tt>start</tt> index and at the current position of this buffer.  The
      * position of this buffer is then incremented by <i>n</i>.
@@ -862,15 +862,15 @@
      * buffer and it is potentially much more efficient. </p>
      *
      * @param  src
-     *         The string from which $fulltype$s are to be read
+     *         The string from which $type$s are to be read
      *
      * @param  start
-     *         The offset within the string of the first $fulltype$ to be read;
+     *         The offset within the string of the first $type$ to be read;
      *         must be non-negative and no larger than
      *         <tt>string.length()</tt>
      *
      * @param  end
-     *         The offset within the string of the last $fulltype$ to be read,
+     *         The offset within the string of the last $type$ to be read,
      *         plus one; must be non-negative and no larger than
      *         <tt>string.length()</tt>
      *
@@ -921,7 +921,7 @@
     // -- Other stuff --
 
     /**
-     * Tells whether or not this buffer is backed by an accessible $fulltype$
+     * Tells whether or not this buffer is backed by an accessible $type$
      * array.
      *
      * <p> If this method returns <tt>true</tt> then the {@link #array() array}
@@ -936,7 +936,7 @@
     }
 
     /**
-     * Returns the $fulltype$ array that backs this
+     * Returns the $type$ array that backs this
      * buffer&nbsp;&nbsp;<i>(optional operation)</i>.
      *
      * <p> Modifications to this buffer's content will cause the returned
@@ -993,17 +993,17 @@
     /**
      * Compacts this buffer&nbsp;&nbsp;<i>(optional operation)</i>.
      *
-     * <p> The $fulltype$s between the buffer's current position and its limit,
+     * <p> The $type$s between the buffer's current position and its limit,
      * if any, are copied to the beginning of the buffer.  That is, the
-     * $fulltype$ at index <i>p</i>&nbsp;=&nbsp;<tt>position()</tt> is copied
-     * to index zero, the $fulltype$ at index <i>p</i>&nbsp;+&nbsp;1 is copied
-     * to index one, and so forth until the $fulltype$ at index
+     * $type$ at index <i>p</i>&nbsp;=&nbsp;<tt>position()</tt> is copied
+     * to index zero, the $type$ at index <i>p</i>&nbsp;+&nbsp;1 is copied
+     * to index one, and so forth until the $type$ at index
      * <tt>limit()</tt>&nbsp;-&nbsp;1 is copied to index
      * <i>n</i>&nbsp;=&nbsp;<tt>limit()</tt>&nbsp;-&nbsp;<tt>1</tt>&nbsp;-&nbsp;<i>p</i>.
      * The buffer's position is then set to <i>n+1</i> and its limit is set to
      * its capacity.  The mark, if defined, is discarded.
      *
-     * <p> The buffer's position is set to the number of $fulltype$s copied,
+     * <p> The buffer's position is set to the number of $type$s copied,
      * rather than to zero, so that an invocation of this method can be
      * followed immediately by an invocation of another relative <i>put</i>
      * method. </p>
@@ -1032,7 +1032,7 @@
     public abstract $Type$Buffer compact();
 
     /**
-     * Tells whether or not this $fulltype$ buffer is direct. </p>
+     * Tells whether or not this $type$ buffer is direct. </p>
      *
      * @return  <tt>true</tt> if, and only if, this buffer is direct
      */
@@ -1098,6 +1098,13 @@
      *
      *   <li><p> The two sequences of remaining elements, considered
      *   independently of their starting positions, are pointwise equal.
+#if[floatingPointType]
+     *   This method considers two $type$ elements {@code a} and {@code b}
+     *   to be equal if
+     *   {@code (a == b) || ($Fulltype$.isNaN(a) && $Fulltype$.isNaN(b))}.
+     *   The values {@code -0.0} and {@code +0.0} are considered to be
+     *   equal, unlike {@link $Fulltype$#equals(Object)}.
+#end[floatingPointType]
      *   </p></li>
      *
      * </ol>
@@ -1118,24 +1125,37 @@
         if (this.remaining() != that.remaining())
             return false;
         int p = this.position();
-        for (int i = this.limit() - 1, j = that.limit() - 1; i >= p; i--, j--) {
-            $type$ v1 = this.get(i);
-            $type$ v2 = that.get(j);
-            if (v1 != v2) {
-                if ((v1 != v1) && (v2 != v2))   // For float and double
-                    continue;
+        for (int i = this.limit() - 1, j = that.limit() - 1; i >= p; i--, j--)
+            if (!equals(this.get(i), that.get(j)))
                 return false;
-            }
-        }
         return true;
     }
 
+    private static boolean equals($type$ x, $type$ y) {
+#if[floatingPointType]
+        return (x == y) || ($Fulltype$.isNaN(x) && $Fulltype$.isNaN(y));
+#else[floatingPointType]
+        return x == y;
+#end[floatingPointType]
+    }
+
     /**
      * Compares this buffer to another.
      *
      * <p> Two $type$ buffers are compared by comparing their sequences of
      * remaining elements lexicographically, without regard to the starting
      * position of each sequence within its corresponding buffer.
+#if[floatingPointType]
+     * Pairs of {@code $type$} elements are compared as if by invoking
+     * {@link $Fulltype$#compare($type$,$type$)}, except that
+     * {@code -0.0} and {@code 0.0} are considered to be equal.
+     * {@code $Fulltype$.NaN} is considered by this method to be equal
+     * to itself and greater than all other {@code $type$} values
+     * (including {@code $Fulltype$.POSITIVE_INFINITY}).
+#else[floatingPointType]
+     * Pairs of {@code $type$} elements are compared as if by invoking
+     * {@link $Fulltype$#compare($type$,$type$)}.
+#end[floatingPointType]
      *
      * <p> A $type$ buffer is not comparable to any other type of object.
      *
@@ -1145,20 +1165,23 @@
     public int compareTo($Type$Buffer that) {
         int n = this.position() + Math.min(this.remaining(), that.remaining());
         for (int i = this.position(), j = that.position(); i < n; i++, j++) {
-            $type$ v1 = this.get(i);
-            $type$ v2 = that.get(j);
-            if (v1 == v2)
-                continue;
-            if ((v1 != v1) && (v2 != v2))       // For float and double
-                continue;
-            if (v1 < v2)
-                return -1;
-            return +1;
+            int cmp = compare(this.get(i), that.get(j));
+            if (cmp != 0)
+                return cmp;
         }
         return this.remaining() - that.remaining();
     }
 
-
+    private static int compare($type$ x, $type$ y) {
+#if[floatingPointType]
+        return ((x < y)  ? -1 :
+                (x > y)  ? +1 :
+                (x == y) ?  0 :
+                $Fulltype$.isNaN(x) ? ($Fulltype$.isNaN(y) ? 0 : +1) : -1);
+#else[floatingPointType]
+        return $Fulltype$.compare(x, y);
+#end[floatingPointType]
+    }
 
     // -- Other char stuff --
 
@@ -1326,7 +1349,7 @@
     }
 
     /**
-     * Appends the specified $fulltype$  to this
+     * Appends the specified $type$  to this
      * buffer&nbsp;&nbsp;<i>(optional operation)</i>.
      *
      * <p> An invocation of this method of the form <tt>dst.append($x$)</tt>
@@ -1336,7 +1359,7 @@
      *     dst.put($x$) </pre>
      *
      * @param  $x$
-     *         The 16-bit $fulltype$ to append
+     *         The 16-bit $type$ to append
      *
      * @return  This buffer
      *
@@ -1362,10 +1385,10 @@
     /**
      * Retrieves this buffer's byte order.
      *
-     * <p> The byte order of $a$ $fulltype$ buffer created by allocation or by
+     * <p> The byte order of $a$ $type$ buffer created by allocation or by
      * wrapping an existing <tt>$type$</tt> array is the {@link
      * ByteOrder#nativeOrder </code>native order<code>} of the underlying
-     * hardware.  The byte order of $a$ $fulltype$ buffer created as a <a
+     * hardware.  The byte order of $a$ $type$ buffer created as a <a
      * href="ByteBuffer.html#views">view</a> of a byte buffer is that of the
      * byte buffer at the moment that the view is created.  </p>
      *
--- a/jdk/src/share/classes/java/rmi/activation/Activatable.java	Thu Dec 17 14:10:20 2009 -0800
+++ b/jdk/src/share/classes/java/rmi/activation/Activatable.java	Wed Jul 05 17:04:56 2017 +0200
@@ -73,7 +73,7 @@
      * can be handled properly.
      *
      * <p>This method invokes the {@link
-     * exportObject(Remote,String,MarshalledObject,boolean,port)
+     * #exportObject(Remote,String,MarshalledObject,boolean,int)
      * exportObject} method with this object, and the specified location,
      * data, restart mode, and port.  Subsequent calls to {@link #getID}
      * will return the activation identifier returned from the call to
@@ -120,7 +120,7 @@
      * can be handled properly.
      *
      * <p>This method invokes the {@link
-     * exportObject(Remote,String,MarshalledObject,boolean,port,RMIClientSocketFactory,RMIServerSocketFactory)
+     * #exportObject(Remote,String,MarshalledObject,boolean,int,RMIClientSocketFactory,RMIServerSocketFactory)
      * exportObject} method with this object, and the specified location,
      * data, restart mode, port, and client and server socket factories.
      * Subsequent calls to {@link #getID} will return the activation
@@ -312,7 +312,7 @@
      * separately, so that exceptions can be handled properly.
      *
      * <p>This method invokes the {@link
-     * exportObject(Remote,String,MarshalledObject,boolean,port,RMIClientSocketFactory,RMIServerSocketFactory)
+     * #exportObject(Remote,String,MarshalledObject,boolean,int,RMIClientSocketFactory,RMIServerSocketFactory)
      * exportObject} method with the specified object, location, data,
      * restart mode, and port, and <code>null</code> for both client and
      * server socket factories, and then returns the resulting activation
--- a/jdk/src/share/classes/java/rmi/registry/LocateRegistry.java	Thu Dec 17 14:10:20 2009 -0800
+++ b/jdk/src/share/classes/java/rmi/registry/LocateRegistry.java	Wed Jul 05 17:04:56 2017 +0200
@@ -187,7 +187,7 @@
      * host that accepts requests on the specified <code>port</code>.
      *
      * <p>The <code>Registry</code> instance is exported as if the static
-     * {@link UnicastRemoteObject.exportObject(Remote,int)
+     * {@link UnicastRemoteObject#exportObject(Remote,int)
      * UnicastRemoteObject.exportObject} method is invoked, passing the
      * <code>Registry</code> instance and the specified <code>port</code> as
      * arguments, except that the <code>Registry</code> instance is
@@ -213,7 +213,7 @@
      *
      * <p>The <code>Registry</code> instance is exported as if
      * the static {@link
-     * UnicastRemoteObject.exportObject(Remote,int,RMIClientSocketFactory,RMIServerSocketFactory)
+     * UnicastRemoteObject#exportObject(Remote,int,RMIClientSocketFactory,RMIServerSocketFactory)
      * UnicastRemoteObject.exportObject} method is invoked, passing the
      * <code>Registry</code> instance, the specified <code>port</code>, the
      * specified <code>RMIClientSocketFactory</code>, and the specified
--- a/jdk/src/share/classes/java/rmi/server/RemoteObjectInvocationHandler.java	Thu Dec 17 14:10:20 2009 -0800
+++ b/jdk/src/share/classes/java/rmi/server/RemoteObjectInvocationHandler.java	Wed Jul 05 17:04:56 2017 +0200
@@ -138,7 +138,6 @@
      * instance
      * @throws  Throwable the exception to throw from the method invocation
      * on the proxy instance
-     * @see
      **/
     public Object invoke(Object proxy, Method method, Object[] args)
         throws Throwable
--- a/jdk/src/share/classes/java/security/cert/CertPathValidatorException.java	Thu Dec 17 14:10:20 2009 -0800
+++ b/jdk/src/share/classes/java/security/cert/CertPathValidatorException.java	Wed Jul 05 17:04:56 2017 +0200
@@ -216,7 +216,7 @@
     /**
      * Returns the reason that the validation failed. The reason is
      * associated with the index of the certificate returned by
-     * {@link getIndex}.
+     * {@link #getIndex}.
      *
      * @return the reason that the validation failed, or
      *    <code>BasicReason.UNSPECIFIED</code> if a reason has not been
--- a/jdk/src/share/classes/java/text/Bidi.java	Thu Dec 17 14:10:20 2009 -0800
+++ b/jdk/src/share/classes/java/text/Bidi.java	Wed Jul 05 17:04:56 2017 +0200
@@ -121,9 +121,9 @@
      *
      * @param paragraph a paragraph of text with optional character and paragraph attribute information
      *
-     * @see TextAttribute#BIDI_EMBEDDING
-     * @see TextAttribute#NUMERIC_SHAPING
-     * @see TextAttribute#RUN_DIRECTION
+     * @see java.awt.font.TextAttribute#BIDI_EMBEDDING
+     * @see java.awt.font.TextAttribute#NUMERIC_SHAPING
+     * @see java.awt.font.TextAttribute#RUN_DIRECTION
      */
     public Bidi(AttributedCharacterIterator paragraph) {
         if (paragraph == null) {
--- a/jdk/src/share/classes/java/util/Objects.java	Thu Dec 17 14:10:20 2009 -0800
+++ b/jdk/src/share/classes/java/util/Objects.java	Wed Jul 05 17:04:56 2017 +0200
@@ -119,7 +119,7 @@
     *
     * @param values the values to be hashed
     * @return a hash value of the sequence of input values
-    * @see Arrays#hashCode
+    * @see Arrays#hashCode(Object[])
     * @see List#hashCode
     */
     public static int hash(Object... values) {
--- a/jdk/src/share/classes/java/util/logging/PlatformLoggingMXBean.java	Thu Dec 17 14:10:20 2009 -0800
+++ b/jdk/src/share/classes/java/util/logging/PlatformLoggingMXBean.java	Wed Jul 05 17:04:56 2017 +0200
@@ -51,7 +51,7 @@
  * The {@link PlatformManagedObject#getObjectName} method
  * can be used to obtain its {@code ObjectName}.
  *
- * @See java.lang.management.PlatformManagedObject
+ * @see java.lang.management.PlatformManagedObject
  *
  * @author  Mandy Chung
  * @since   1.7
--- a/jdk/src/share/classes/javax/accessibility/AccessibleContext.java	Thu Dec 17 14:10:20 2009 -0800
+++ b/jdk/src/share/classes/javax/accessibility/AccessibleContext.java	Wed Jul 05 17:04:56 2017 +0200
@@ -296,7 +296,7 @@
      *
      * @see #getAccessibleText
      * @see #addPropertyChangeListener
-     * @see #AccessibleText.AccessibleTextSequence
+     * @see AccessibleTextSequence
      */
     public static final String ACCESSIBLE_TEXT_PROPERTY
         = "AccessibleText";
@@ -311,7 +311,7 @@
      *
      * @see #getAccessibleText
      * @see #addPropertyChangeListener
-     * @see #AccessibleText.AccessibleTextSequence
+     * @see AccessibleTextSequence
      *
      * @since 1.5
      */
@@ -334,7 +334,7 @@
      *
      * @see #getAccessibleText
      * @see #addPropertyChangeListener
-     * @see #AccessibleText.AccessibleAttributeSequence
+     * @see AccessibleAttributeSequence
      *
      * @since 1.5
      */
--- a/jdk/src/share/classes/javax/accessibility/AccessibleExtendedText.java	Thu Dec 17 14:10:20 2009 -0800
+++ b/jdk/src/share/classes/javax/accessibility/AccessibleExtendedText.java	Wed Jul 05 17:04:56 2017 +0200
@@ -45,7 +45,6 @@
  * @see Accessible#getAccessibleContext
  * @see AccessibleContext
  * @see AccessibleContext#getAccessibleText
- * @see AccessibleText.AccessibleTextChunk
  *
  * @author       Peter Korn
  * @author       Lynn Monsanto
--- a/jdk/src/share/classes/javax/accessibility/AccessibleKeyBinding.java	Thu Dec 17 14:10:20 2009 -0800
+++ b/jdk/src/share/classes/javax/accessibility/AccessibleKeyBinding.java	Wed Jul 05 17:04:56 2017 +0200
@@ -32,16 +32,11 @@
  * the standard mechanism for an assistive technology to determine the
  * key bindings which exist for this object.
  * Any object that has such key bindings should support this
- * interface.  Applications can determine if an object supports the
- * AccessibleKeyBinding interface by first obtaining its AccessibleContext
- * (see @link Accessible} and then calling the
- * {@link AccessibleContext#getAccessibleKeyBinding} method.  If the return
- * value is not null, the object supports this interface.
+ * interface.
  *
  * @see Accessible
  * @see Accessible#getAccessibleContext
  * @see AccessibleContext
- * @see AccessibleContext#getAccessibleKeyBinding
  *
  * @author      Lynn Monsanto
  * @since 1.4
@@ -58,21 +53,7 @@
     /**
      * Returns a key binding for this object.  The value returned is an
      * java.lang.Object which must be cast to appropriate type depending
-     * on the underlying implementation of the key.  For example, if the
-     * Object returned is a javax.swing.KeyStroke, the user of this
-     * method should do the following:
-     * <nf><code>
-     * Component c = <get the component that has the key bindings>
-     * AccessibleContext ac = c.getAccessibleContext();
-     * AccessibleKeyBinding akb = ac.getAccessibleKeyBinding();
-     * for (int i = 0; i < akb.getAccessibleKeyBindingCount(); i++) {
-     *     Object o = akb.getAccessibleKeyBinding(i);
-     *     if (o instanceof javax.swing.KeyStroke) {
-     *         javax.swing.KeyStroke keyStroke = (javax.swing.KeyStroke)o;
-     *         <do something with the key binding>
-     *     }
-     * }
-     * </code></nf>
+     * on the underlying implementation of the key.
      *
      * @param i zero-based index of the key bindings
      * @return a javax.lang.Object which specifies the key binding
--- a/jdk/src/share/classes/org/ietf/jgss/GSSName.java	Thu Dec 17 14:10:20 2009 -0800
+++ b/jdk/src/share/classes/org/ietf/jgss/GSSName.java	Wed Jul 05 17:04:56 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2000-2010 Sun Microsystems, Inc.  All Rights Reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -103,11 +103,12 @@
      * follows: service@hostname.<p>
      *
      * It represents the following Oid value:<br>
-     * <code>{ 1(iso), 3(org), 6(dod), 1(internet), 5(security),
-     * 6(nametypes), 2(gss-host-based-services) }</code>
+     *  <code>{ iso(1) member-body(2) United
+     * States(840) mit(113554) infosys(1) gssapi(2) generic(1) service_name(4)
+     * }</code>
      */
     public static final Oid NT_HOSTBASED_SERVICE
-        = Oid.getInstance("1.3.6.1.5.6.2");
+        = Oid.getInstance("1.2.840.113554.1.2.1.4");
 
     /**
      * Name type to indicate a named user on a local system.<p>
--- a/jdk/src/share/classes/org/jcp/xml/dsig/internal/dom/DOMXMLSignature.java	Thu Dec 17 14:10:20 2009 -0800
+++ b/jdk/src/share/classes/org/jcp/xml/dsig/internal/dom/DOMXMLSignature.java	Wed Jul 05 17:04:56 2017 +0200
@@ -326,7 +326,7 @@
         }
 
         // generate references and signature value
-        List allReferences = new ArrayList(si.getReferences());
+        List allReferences = new ArrayList();
 
         // traverse the Signature and register all objects with IDs that
         // may contain References
@@ -356,6 +356,9 @@
                 }
             }
         }
+        // always add SignedInfo references after Manifest references so
+        // that Manifest reference are digested first
+        allReferences.addAll(si.getReferences());
 
         // generate/digest each reference
         for (int i = 0, size = allReferences.size(); i < size; i++) {
--- a/jdk/src/share/classes/sun/dyn/AdapterMethodHandle.java	Thu Dec 17 14:10:20 2009 -0800
+++ b/jdk/src/share/classes/sun/dyn/AdapterMethodHandle.java	Wed Jul 05 17:04:56 2017 +0200
@@ -30,7 +30,7 @@
 import java.dyn.*;
 import java.util.Arrays;
 import static sun.dyn.MethodHandleNatives.Constants.*;
-import static sun.dyn.MethodHandleImpl.newIllegalArgumentException;
+import static sun.dyn.MemberName.newIllegalArgumentException;
 
 /**
  * This method handle performs simple conversion or checking of a single argument.
@@ -302,7 +302,22 @@
      */
     private static int type2size(int type) {
         assert(type >= T_BOOLEAN && type <= T_OBJECT);
-        return (type == T_FLOAT || type == T_DOUBLE) ? 2 : 1;
+        return (type == T_LONG || type == T_DOUBLE) ? 2 : 1;
+    }
+    private static int type2size(Class<?> type) {
+        return type2size(basicType(type));
+    }
+
+    /** The given stackMove is the number of slots pushed.
+     * It might be negative.  Scale it (multiply) by the
+     * VM's notion of how an address changes with a push,
+     * to get the raw SP change for stackMove.
+     * Then shift and mask it into the correct field.
+     */
+    private static long insertStackMove(int stackMove) {
+        // following variable must be long to avoid sign extension after '<<'
+        long spChange = stackMove * MethodHandleNatives.JVM_STACK_MOVE_UNIT;
+        return (spChange & CONV_STACK_MOVE_MASK) << CONV_STACK_MOVE_SHIFT;
     }
 
     /** Construct an adapter conversion descriptor for a single-argument conversion. */
@@ -310,16 +325,16 @@
         assert(src  == (src  & 0xF));
         assert(dest == (dest & 0xF));
         assert(convOp >= OP_CHECK_CAST && convOp <= OP_PRIM_TO_REF);
-        long stackMove = type2size(dest) - type2size(src);
+        int stackMove = type2size(dest) - type2size(src);
         return ((long) argnum << 32 |
                 (long) convOp << CONV_OP_SHIFT |
                 (int)  src    << CONV_SRC_TYPE_SHIFT |
                 (int)  dest   << CONV_DEST_TYPE_SHIFT |
-                stackMove     << CONV_STACK_MOVE_SHIFT
+                insertStackMove(stackMove)
                 );
     }
     private static long makeConv(int convOp, int argnum, int stackMove) {
-        assert(convOp >= OP_SWAP_ARGS && convOp <= OP_SPREAD_ARGS);
+        assert(convOp >= OP_DUP_ARGS && convOp <= OP_SPREAD_ARGS);
         byte src = 0, dest = 0;
         if (convOp >= OP_COLLECT_ARGS && convOp <= OP_SPREAD_ARGS)
             src = dest = T_OBJECT;
@@ -327,12 +342,21 @@
                 (long) convOp << CONV_OP_SHIFT |
                 (int)  src    << CONV_SRC_TYPE_SHIFT |
                 (int)  dest   << CONV_DEST_TYPE_SHIFT |
-                stackMove     << CONV_STACK_MOVE_SHIFT
+                insertStackMove(stackMove)
+                );
+    }
+    private static long makeSwapConv(int convOp, int srcArg, byte type, int destSlot) {
+        assert(convOp >= OP_SWAP_ARGS && convOp <= OP_ROT_ARGS);
+        return ((long) srcArg << 32 |
+                (long) convOp << CONV_OP_SHIFT |
+                (int)  type   << CONV_SRC_TYPE_SHIFT |
+                (int)  type   << CONV_DEST_TYPE_SHIFT |
+                (int)  destSlot << CONV_VMINFO_SHIFT
                 );
     }
     private static long makeConv(int convOp) {
-        assert(convOp == OP_RETYPE_ONLY);
-        return (long) convOp << CONV_OP_SHIFT;   // stackMove, src, dst, argnum all zero
+        assert(convOp == OP_RETYPE_ONLY || convOp == OP_RETYPE_RAW);
+        return ((long)-1 << 32) | (convOp << CONV_OP_SHIFT);   // stackMove, src, dst all zero
     }
     private static int convCode(long conv) {
         return (int)conv;
@@ -348,16 +372,6 @@
     /** One of OP_RETYPE_ONLY, etc. */
     int conversionOp() { return (conversion & CONV_OP_MASK) >> CONV_OP_SHIFT; }
 
-    @Override
-    public String toString() {
-        return addTypeString(this, "Adapted[" + basicToString(nonAdapter((MethodHandle)vmtarget)) + "]");
-    }
-
-    private static MethodHandle nonAdapter(MethodHandle mh) {
-        return (MethodHandle)
-            MethodHandleNatives.getTarget(mh, ETF_DIRECT_HANDLE);
-    }
-
     /* Return one plus the position of the first non-trivial difference
      * between the given types.  This is not a symmetric operation;
      * we are considering adapting the targetType to adapterType.
@@ -399,14 +413,14 @@
         //if (false)  return 1;  // never adaptable!
         return -1;  // some significant difference
     }
-    private static int diffParamTypes(MethodType adapterType, int tstart,
-                                      MethodType targetType, int astart,
+    private static int diffParamTypes(MethodType adapterType, int astart,
+                                      MethodType targetType, int tstart,
                                       int nargs, boolean raw) {
         assert(nargs >= 0);
         int res = 0;
         for (int i = 0; i < nargs; i++) {
-            Class<?> src  = adapterType.parameterType(tstart+i);
-            Class<?> dest = targetType.parameterType(astart+i);
+            Class<?> src  = adapterType.parameterType(astart+i);
+            Class<?> dest = targetType.parameterType(tstart+i);
             if ((!raw
                  ? VerifyType.canPassUnchecked(src, dest)
                  : VerifyType.canPassRaw(src, dest)
@@ -422,7 +436,7 @@
 
     /** Can a retyping adapter (alone) validly convert the target to newType? */
     public static boolean canRetypeOnly(MethodType newType, MethodType targetType) {
-        return canRetypeOnly(newType, targetType, false);
+        return canRetype(newType, targetType, false);
     }
     /** Can a retyping adapter (alone) convert the target to newType?
      *  It is allowed to widen subword types and void to int, to make bitwise
@@ -430,14 +444,14 @@
      *  reference conversions on return.  This last feature requires that the
      *  caller be trusted, and perform explicit cast conversions on return values.
      */
-    static boolean canRawRetypeOnly(MethodType newType, MethodType targetType) {
-        return canRetypeOnly(newType, targetType, true);
+    public static boolean canRetypeRaw(MethodType newType, MethodType targetType) {
+        return canRetype(newType, targetType, true);
     }
-    static boolean canRetypeOnly(MethodType newType, MethodType targetType, boolean raw) {
-        if (!convOpSupported(OP_RETYPE_ONLY))  return false;
+    static boolean canRetype(MethodType newType, MethodType targetType, boolean raw) {
+        if (!convOpSupported(raw ? OP_RETYPE_RAW : OP_RETYPE_ONLY))  return false;
         int diff = diffTypes(newType, targetType, raw);
         // %%% This assert is too strong.  Factor diff into VerifyType and reconcile.
-        assert((diff == 0) == VerifyType.isNullConversion(newType, targetType));
+        assert(raw || (diff == 0) == VerifyType.isNullConversion(newType, targetType));
         return diff == 0;
     }
 
@@ -447,19 +461,21 @@
      */
     public static MethodHandle makeRetypeOnly(Access token,
                 MethodType newType, MethodHandle target) {
-        return makeRetypeOnly(token, newType, target, false);
+        return makeRetype(token, newType, target, false);
     }
-    public static MethodHandle makeRawRetypeOnly(Access token,
+    public static MethodHandle makeRetypeRaw(Access token,
                 MethodType newType, MethodHandle target) {
-        return makeRetypeOnly(token, newType, target, true);
+        return makeRetype(token, newType, target, true);
     }
-    static MethodHandle makeRetypeOnly(Access token,
+    static MethodHandle makeRetype(Access token,
                 MethodType newType, MethodHandle target, boolean raw) {
         Access.check(token);
-        if (!canRetypeOnly(newType, target.type(), raw))
+        MethodType oldType = target.type();
+        if (oldType == newType)  return target;
+        if (!canRetype(newType, oldType, raw))
             return null;
         // TO DO:  clone the target guy, whatever he is, with new type.
-        return new AdapterMethodHandle(target, newType, makeConv(OP_RETYPE_ONLY));
+        return new AdapterMethodHandle(target, newType, makeConv(raw ? OP_RETYPE_RAW : OP_RETYPE_ONLY));
     }
 
     /** Can a checkcast adapter validly convert the target to newType?
@@ -492,7 +508,7 @@
         Access.check(token);
         if (!canCheckCast(newType, target.type(), arg, castType))
             return null;
-        long conv = makeConv(OP_CHECK_CAST, arg, 0);
+        long conv = makeConv(OP_CHECK_CAST, arg, T_OBJECT, T_OBJECT);
         return new AdapterMethodHandle(target, newType, conv, castType);
     }
 
@@ -537,10 +553,9 @@
                 int arg, Class<?> convType) {
         Access.check(token);
         MethodType oldType = target.type();
-        Class<?> src = newType.parameterType(arg);
-        Class<?> dst = oldType.parameterType(arg);
         if (!canPrimCast(newType, oldType, arg, convType))
             return null;
+        Class<?> src = newType.parameterType(arg);
         long conv = makeConv(OP_PRIM_TO_PRIM, arg, basicType(src), basicType(convType));
         return new AdapterMethodHandle(target, newType, conv);
     }
@@ -607,8 +622,6 @@
         return null;
     }
 
-    // TO DO: makeSwapArguments, makeRotateArguments, makeDuplicateArguments
-
     /** Can an adapter simply drop arguments to convert the target to newType? */
     public static boolean canDropArguments(MethodType newType, MethodType targetType,
                 int dropArgPos, int dropArgCount) {
@@ -643,26 +656,195 @@
         Access.check(token);
         if (dropArgCount == 0)
             return makeRetypeOnly(IMPL_TOKEN, newType, target);
-        MethodType mt = target.type();
-        int argCount  = mt.parameterCount();
-        if (!canDropArguments(newType, mt, dropArgPos, dropArgCount))
+        if (!canDropArguments(newType, target.type(), dropArgPos, dropArgCount))
+            return null;
+        // in  arglist: [0: ...keep1 | dpos: drop... | dpos+dcount: keep2... ]
+        // out arglist: [0: ...keep1 |                        dpos: keep2... ]
+        int keep2InPos  = dropArgPos + dropArgCount;
+        int dropSlot    = newType.parameterSlotDepth(keep2InPos);
+        int keep1InSlot = newType.parameterSlotDepth(dropArgPos);
+        int slotCount   = keep1InSlot - dropSlot;
+        assert(slotCount >= dropArgCount);
+        assert(target.type().parameterSlotCount() + slotCount == newType.parameterSlotCount());
+        long conv = makeConv(OP_DROP_ARGS, dropArgPos + dropArgCount - 1, -slotCount);
+        return new AdapterMethodHandle(target, newType, conv);
+    }
+
+    /** Can an adapter duplicate an argument to convert the target to newType? */
+    public static boolean canDupArguments(MethodType newType, MethodType targetType,
+                int dupArgPos, int dupArgCount) {
+        if (!convOpSupported(OP_DUP_ARGS))  return false;
+        if (diffReturnTypes(newType, targetType, false) != 0)
+            return false;
+        int nptypes = newType.parameterCount();
+        if (dupArgCount < 0 || dupArgPos + dupArgCount > nptypes)
+            return false;
+        if (targetType.parameterCount() != nptypes + dupArgCount)
+            return false;
+        // parameter types must be the same up to the duplicated arguments
+        if (diffParamTypes(newType, 0, targetType, 0, nptypes, false) != 0)
+            return false;
+        // duplicated types must be, well, duplicates
+        if (diffParamTypes(newType, dupArgPos, targetType, nptypes, dupArgCount, false) != 0)
+            return false;
+        return true;
+    }
+
+    /** Factory method:  Duplicate the selected argument.
+     *  Return null if this is not possible.
+     */
+    public static MethodHandle makeDupArguments(Access token,
+                MethodType newType, MethodHandle target,
+                int dupArgPos, int dupArgCount) {
+        Access.check(token);
+        if (!canDupArguments(newType, target.type(), dupArgPos, dupArgCount))
             return null;
-        int dropSlotCount, dropSlotPos;
-        if (dropArgCount >= argCount) {
-            assert(dropArgPos == argCount-1);
-            dropSlotPos = 0;
-            dropSlotCount = mt.parameterSlotCount();
+        if (dupArgCount == 0)
+            return target;
+        // in  arglist: [0: ...keep1 | dpos: dup... | dpos+dcount: keep2... ]
+        // out arglist: [0: ...keep1 | dpos: dup... | dpos+dcount: keep2... | dup... ]
+        int keep2InPos  = dupArgPos + dupArgCount;
+        int dupSlot     = newType.parameterSlotDepth(keep2InPos);
+        int keep1InSlot = newType.parameterSlotDepth(dupArgPos);
+        int slotCount   = keep1InSlot - dupSlot;
+        assert(target.type().parameterSlotCount() - slotCount == newType.parameterSlotCount());
+        long conv = makeConv(OP_DUP_ARGS, dupArgPos + dupArgCount - 1, slotCount);
+        return new AdapterMethodHandle(target, newType, conv);
+    }
+
+    /** Can an adapter swap two arguments to convert the target to newType? */
+    public static boolean canSwapArguments(MethodType newType, MethodType targetType,
+                int swapArg1, int swapArg2) {
+        if (!convOpSupported(OP_SWAP_ARGS))  return false;
+        if (diffReturnTypes(newType, targetType, false) != 0)
+            return false;
+        if (swapArg1 >= swapArg2)  return false;  // caller resp
+        int nptypes = newType.parameterCount();
+        if (targetType.parameterCount() != nptypes)
+            return false;
+        if (swapArg1 < 0 || swapArg2 >= nptypes)
+            return false;
+        if (diffParamTypes(newType, 0, targetType, 0, swapArg1, false) != 0)
+            return false;
+        if (diffParamTypes(newType, swapArg1, targetType, swapArg2, 1, false) != 0)
+            return false;
+        if (diffParamTypes(newType, swapArg1+1, targetType, swapArg1+1, swapArg2-swapArg1-1, false) != 0)
+            return false;
+        if (diffParamTypes(newType, swapArg2, targetType, swapArg1, 1, false) != 0)
+            return false;
+        if (diffParamTypes(newType, swapArg2+1, targetType, swapArg2+1, nptypes-swapArg2-1, false) != 0)
+            return false;
+        return true;
+    }
+
+    /** Factory method:  Swap the selected arguments.
+     *  Return null if this is not possible.
+     */
+    public static MethodHandle makeSwapArguments(Access token,
+                MethodType newType, MethodHandle target,
+                int swapArg1, int swapArg2) {
+        Access.check(token);
+        if (swapArg1 == swapArg2)
+            return target;
+        if (swapArg1 > swapArg2) { int t = swapArg1; swapArg1 = swapArg2; swapArg2 = t; }
+        if (!canSwapArguments(newType, target.type(), swapArg1, swapArg2))
+            return null;
+        Class<?> swapType = newType.parameterType(swapArg1);
+        // in  arglist: [0: ...keep1 | pos1: a1 | pos1+1: keep2... | pos2: a2 | pos2+1: keep3... ]
+        // out arglist: [0: ...keep1 | pos1: a2 | pos1+1: keep2... | pos2: a1 | pos2+1: keep3... ]
+        int swapSlot2  = newType.parameterSlotDepth(swapArg2 + 1);
+        long conv = makeSwapConv(OP_SWAP_ARGS, swapArg1, basicType(swapType), swapSlot2);
+        return new AdapterMethodHandle(target, newType, conv);
+    }
+
+    static int positiveRotation(int argCount, int rotateBy) {
+        assert(argCount > 0);
+        if (rotateBy >= 0) {
+            if (rotateBy < argCount)
+                return rotateBy;
+            return rotateBy % argCount;
+        } else if (rotateBy >= -argCount) {
+            return rotateBy + argCount;
         } else {
-            // arglist: [0: keep... | dpos: drop... | dpos+dcount: keep... ]
-            int lastDroppedArg = dropArgPos + dropArgCount - 1;
-            int lastKeptArg    = dropArgPos - 1;  // might be -1, which is OK
-            dropSlotPos      = mt.parameterSlotDepth(1+lastDroppedArg);
-            int lastKeptSlot = mt.parameterSlotDepth(1+lastKeptArg);
-            dropSlotCount = lastKeptSlot - dropSlotPos;
-            assert(dropSlotCount >= dropArgCount);
+            return (-1-((-1-rotateBy) % argCount)) + argCount;
         }
-        long conv = makeConv(OP_DROP_ARGS, dropArgPos, +dropSlotCount);
-        return new AdapterMethodHandle(target, newType, dropSlotCount, conv);
+    }
+
+    final static int MAX_ARG_ROTATION = 1;
+
+    /** Can an adapter rotate arguments to convert the target to newType? */
+    public static boolean canRotateArguments(MethodType newType, MethodType targetType,
+                int firstArg, int argCount, int rotateBy) {
+        if (!convOpSupported(OP_ROT_ARGS))  return false;
+        if (argCount <= 2)  return false;  // must be a swap, not a rotate
+        rotateBy = positiveRotation(argCount, rotateBy);
+        if (rotateBy == 0)  return false;  // no rotation
+        if (rotateBy > MAX_ARG_ROTATION && rotateBy < argCount - MAX_ARG_ROTATION)
+            return false;  // too many argument positions
+        // Rotate incoming args right N to the out args, N in 1..(argCouunt-1).
+        if (diffReturnTypes(newType, targetType, false) != 0)
+            return false;
+        int nptypes = newType.parameterCount();
+        if (targetType.parameterCount() != nptypes)
+            return false;
+        if (firstArg < 0 || firstArg >= nptypes)  return false;
+        int argLimit = firstArg + argCount;
+        if (argLimit > nptypes)  return false;
+        if (diffParamTypes(newType, 0, targetType, 0, firstArg, false) != 0)
+            return false;
+        int newChunk1 = argCount - rotateBy, newChunk2 = rotateBy;
+        // swap new chunk1 with target chunk2
+        if (diffParamTypes(newType, firstArg, targetType, argLimit-newChunk1, newChunk1, false) != 0)
+            return false;
+        // swap new chunk2 with target chunk1
+        if (diffParamTypes(newType, firstArg+newChunk1, targetType, firstArg, newChunk2, false) != 0)
+            return false;
+        return true;
+    }
+
+    /** Factory method:  Rotate the selected argument range.
+     *  Return null if this is not possible.
+     */
+    public static MethodHandle makeRotateArguments(Access token,
+                MethodType newType, MethodHandle target,
+                int firstArg, int argCount, int rotateBy) {
+        Access.check(token);
+        rotateBy = positiveRotation(argCount, rotateBy);
+        if (!canRotateArguments(newType, target.type(), firstArg, argCount, rotateBy))
+            return null;
+        // Decide whether it should be done as a right or left rotation,
+        // on the JVM stack.  Return the number of stack slots to rotate by,
+        // positive if right, negative if left.
+        int limit = firstArg + argCount;
+        int depth0 = newType.parameterSlotDepth(firstArg);
+        int depth1 = newType.parameterSlotDepth(limit-rotateBy);
+        int depth2 = newType.parameterSlotDepth(limit);
+        int chunk1Slots = depth0 - depth1; assert(chunk1Slots > 0);
+        int chunk2Slots = depth1 - depth2; assert(chunk2Slots > 0);
+        // From here on out, it assumes a single-argument shift.
+        assert(MAX_ARG_ROTATION == 1);
+        int srcArg, dstArg;
+        byte basicType;
+        if (chunk2Slots <= chunk1Slots) {
+            // Rotate right/down N (rotateBy = +N, N small, c2 small):
+            // in  arglist: [0: ...keep1 | arg1: c1...  | limit-N: c2 | limit: keep2... ]
+            // out arglist: [0: ...keep1 | arg1: c2 | arg1+N: c1...   | limit: keep2... ]
+            srcArg = limit-1;
+            dstArg = firstArg;
+            basicType = basicType(newType.parameterType(srcArg));
+            assert(chunk2Slots == type2size(basicType));
+        } else {
+            // Rotate left/up N (rotateBy = -N, N small, c1 small):
+            // in  arglist: [0: ...keep1 | arg1: c1 | arg1+N: c2...   | limit: keep2... ]
+            // out arglist: [0: ...keep1 | arg1: c2 ... | limit-N: c1 | limit: keep2... ]
+            srcArg = firstArg;
+            dstArg = limit-1;
+            basicType = basicType(newType.parameterType(srcArg));
+            assert(chunk1Slots == type2size(basicType));
+        }
+        int dstSlot = newType.parameterSlotDepth(dstArg + 1);
+        long conv = makeSwapConv(OP_ROT_ARGS, srcArg, basicType, dstSlot);
+        return new AdapterMethodHandle(target, newType, conv);
     }
 
     /** Can an adapter spread an argument to convert the target to newType? */
@@ -676,10 +858,10 @@
         if (spreadArgPos != 0 && diffParamTypes(newType, 0, targetType, 0, spreadArgPos, false) != 0)
             return false;
         int afterPos = spreadArgPos + spreadArgCount;
-        int afterCount = nptypes - afterPos;
+        int afterCount = nptypes - (spreadArgPos + 1);
         if (spreadArgPos < 0 || spreadArgPos >= nptypes ||
             spreadArgCount < 0 ||
-            targetType.parameterCount() != nptypes - 1 + spreadArgCount)
+            targetType.parameterCount() != afterPos + afterCount)
             return false;
         // parameter types after the spread point must also be the same
         if (afterCount != 0 && diffParamTypes(newType, spreadArgPos+1, targetType, afterPos, afterCount, false) != 0)
@@ -697,32 +879,40 @@
         return true;
     }
 
+
     /** Factory method:  Spread selected argument. */
     public static MethodHandle makeSpreadArguments(Access token,
                 MethodType newType, MethodHandle target,
                 Class<?> spreadArgType, int spreadArgPos, int spreadArgCount) {
         Access.check(token);
-        MethodType mt = target.type();
-        int argCount  = mt.parameterCount();
-        if (!canSpreadArguments(newType, mt, spreadArgType, spreadArgPos, spreadArgCount))
+        MethodType targetType = target.type();
+        if (!canSpreadArguments(newType, targetType, spreadArgType, spreadArgPos, spreadArgCount))
             return null;
-        int spreadSlotCount, spreadSlotPos;
-        if (spreadArgCount >= argCount) {
-            assert(spreadArgPos == argCount-1);
-            spreadSlotPos = 0;
-            spreadSlotCount = mt.parameterSlotCount();
-        } else {
-            // arglist: [0: keep... | dpos: spread... | dpos+dcount: keep... ]
-            int lastSpreadArg = spreadArgPos + spreadArgCount - 1;
-            int lastKeptArg   = spreadArgPos - 1;  // might be -1, which is OK
-            spreadSlotPos     = mt.parameterSlotDepth(1+lastSpreadArg);
-            int lastKeptSlot  = mt.parameterSlotDepth(1+lastKeptArg);
-            spreadSlotCount = lastKeptSlot - spreadSlotPos;
-            assert(spreadSlotCount >= spreadArgCount);
-        }
-        long conv = makeConv(OP_SPREAD_ARGS, spreadArgPos, spreadSlotCount);
-        return new AdapterMethodHandle(target, newType, conv, spreadArgType);
+        // in  arglist: [0: ...keep1 | spos: spreadArg | spos+1:      keep2... ]
+        // out arglist: [0: ...keep1 | spos: spread... | spos+scount: keep2... ]
+        int keep2OutPos  = spreadArgPos + spreadArgCount;
+        int spreadSlot   = targetType.parameterSlotDepth(keep2OutPos);
+        int keep1OutSlot = targetType.parameterSlotDepth(spreadArgPos);
+        int slotCount    = keep1OutSlot - spreadSlot;
+        assert(spreadSlot == newType.parameterSlotDepth(spreadArgPos+1));
+        assert(slotCount >= spreadArgCount);
+        long conv = makeConv(OP_SPREAD_ARGS, spreadArgPos, slotCount-1);
+        MethodHandle res = new AdapterMethodHandle(target, newType, conv, spreadArgType);
+        assert(res.type().parameterType(spreadArgPos) == spreadArgType);
+        return res;
     }
 
     // TO DO: makeCollectArguments, makeFlyby, makeRicochet
+
+    @Override
+    public String toString() {
+        return nonAdapter((MethodHandle)vmtarget).toString();
+    }
+
+    private static MethodHandle nonAdapter(MethodHandle mh) {
+        while (mh instanceof AdapterMethodHandle) {
+            mh = (MethodHandle) mh.vmtarget;
+        }
+        return mh;
+    }
 }
--- a/jdk/src/share/classes/sun/dyn/BoundMethodHandle.java	Thu Dec 17 14:10:20 2009 -0800
+++ b/jdk/src/share/classes/sun/dyn/BoundMethodHandle.java	Wed Jul 05 17:04:56 2017 +0200
@@ -28,6 +28,10 @@
 import sun.dyn.util.VerifyType;
 import sun.dyn.util.Wrapper;
 import java.dyn.*;
+import java.util.List;
+import sun.dyn.MethodHandleNatives.Constants;
+import static sun.dyn.MethodHandleImpl.IMPL_LOOKUP;
+import static sun.dyn.MemberName.newIllegalArgumentException;
 
 /**
  * The flavor of method handle which emulates an invoke instruction
@@ -35,18 +39,23 @@
  * when the handle is created, not when it is invoked.
  * @author jrose
  */
-public class BoundMethodHandle extends MethodHandle  {
+public class BoundMethodHandle extends MethodHandle {
     //MethodHandle vmtarget;           // next BMH or final DMH or methodOop
     private final Object argument;     // argument to insert
     private final int    vmargslot;    // position at which it is inserted
 
+    private static final Access IMPL_TOKEN = Access.getToken();
+    private static final MemberName.Factory IMPL_NAMES = MemberName.getFactory(IMPL_TOKEN);
+
     // Constructors in this class *must* be package scoped or private.
+    // Exception:  JavaMethodHandle constructors are protected.
+    // (The link between JMH and BMH is temporary.)
 
     /** Bind a direct MH to its receiver (or first ref. argument).
      *  The JVM will pre-dispatch the MH if it is not already static.
      */
     BoundMethodHandle(DirectMethodHandle mh, Object argument) {
-        super(Access.TOKEN, mh.type().dropParameterType(0));
+        super(Access.TOKEN, mh.type().dropParameterTypes(0, 1));
         // check the type now, once for all:
         this.argument = checkReferenceArgument(argument, mh, 0);
         this.vmargslot = this.type().parameterSlotCount();
@@ -56,32 +65,34 @@
         } else {
             this.vmtarget = mh;
         }
-     }
-
-    private static final int REF_ARG = 0, PRIM_ARG = 1, SELF_ARG = 2;
+    }
 
     /** Insert an argument into an arbitrary method handle.
      *  If argnum is zero, inserts the first argument, etc.
      *  The argument type must be a reference.
      */
     BoundMethodHandle(MethodHandle mh, Object argument, int argnum) {
-        this(mh, argument, argnum, mh.type().parameterType(argnum).isPrimitive() ? PRIM_ARG : REF_ARG);
+        this(mh.type().dropParameterTypes(argnum, argnum+1),
+             mh, argument, argnum);
     }
 
     /** Insert an argument into an arbitrary method handle.
      *  If argnum is zero, inserts the first argument, etc.
      */
-    BoundMethodHandle(MethodHandle mh, Object argument, int argnum, int whichArg) {
-        super(Access.TOKEN, mh.type().dropParameterType(argnum));
-        if (whichArg == PRIM_ARG)
+    BoundMethodHandle(MethodType type, MethodHandle mh, Object argument, int argnum) {
+        super(Access.TOKEN, type);
+        if (mh.type().parameterType(argnum).isPrimitive())
             this.argument = bindPrimitiveArgument(argument, mh, argnum);
         else {
-            if (whichArg == SELF_ARG)  argument = this;
             this.argument = checkReferenceArgument(argument, mh, argnum);
         }
-        this.vmargslot = this.type().parameterSlotDepth(argnum);
+        this.vmargslot = type.parameterSlotDepth(argnum);
+        initTarget(mh, argnum);
+    }
+
+    private void initTarget(MethodHandle mh, int argnum) {
         if (MethodHandleNatives.JVM_SUPPORT) {
-            this.vmtarget = null;  // maybe updated by JVM
+            this.vmtarget = null; // maybe updated by JVM
             MethodHandleNatives.init(this, mh, argnum);
         } else {
             this.vmtarget = mh;
@@ -97,29 +108,65 @@
         assert(this.getClass() == AdapterMethodHandle.class);
     }
 
-    /** Initialize the current object as a method handle, binding it
-     *  as the {@code argnum}th argument of the method handle {@code entryPoint}.
-     *  The invocation type of the resulting method handle will be the
-     *  same as {@code entryPoint},  except that the {@code argnum}th argument
-     *  type will be dropped.
-     */
-    public BoundMethodHandle(MethodHandle entryPoint, int argnum) {
-        this(entryPoint, null, argnum, SELF_ARG);
-
-        // Note:  If the conversion fails, perhaps because of a bad entryPoint,
-        // the MethodHandle.type field will not be filled in, and therefore
-        // no MH.invoke call will ever succeed.  The caller may retain a pointer
-        // to the broken method handle, but no harm can be done with it.
-    }
-
-    /** Initialize the current object as a method handle, binding it
+    /** Initialize the current object as a Java method handle, binding it
      *  as the first argument of the method handle {@code entryPoint}.
      *  The invocation type of the resulting method handle will be the
      *  same as {@code entryPoint},  except that the first argument
      *  type will be dropped.
      */
-    public BoundMethodHandle(MethodHandle entryPoint) {
-        this(entryPoint, null, 0, SELF_ARG);
+    protected BoundMethodHandle(MethodHandle entryPoint) {
+        super(Access.TOKEN, entryPoint.type().dropParameterTypes(0, 1));
+        this.argument = this; // kludge; get rid of
+        this.vmargslot = this.type().parameterSlotDepth(0);
+        initTarget(entryPoint, 0);
+        assert(this instanceof JavaMethodHandle);
+    }
+
+    /** Initialize the current object as a Java method handle.
+     */
+    protected BoundMethodHandle(String entryPointName, MethodType type, boolean matchArity) {
+        super(Access.TOKEN, null);
+        MethodHandle entryPoint
+                = findJavaMethodHandleEntryPoint(this.getClass(),
+                                        entryPointName, type, matchArity);
+        MethodHandleImpl.initType(this, entryPoint.type().dropParameterTypes(0, 1));
+        this.argument = this; // kludge; get rid of
+        this.vmargslot = this.type().parameterSlotDepth(0);
+        initTarget(entryPoint, 0);
+        assert(this instanceof JavaMethodHandle);
+    }
+
+    private static
+    MethodHandle findJavaMethodHandleEntryPoint(Class<?> caller,
+                                                String name,
+                                                MethodType type,
+                                                boolean matchArity) {
+        if (matchArity)  type.getClass();  // elicit NPE
+        List<MemberName> methods = IMPL_NAMES.getMethods(caller, true, name, null, caller);
+        MethodType foundType = null;
+        MemberName foundMethod = null;
+        for (MemberName method : methods) {
+            MethodType mtype = method.getMethodType();
+            if (type != null && type.parameterCount() != mtype.parameterCount())
+                continue;
+            else if (foundType == null)
+                foundType = mtype;
+            else if (foundType != mtype)
+                throw newIllegalArgumentException("more than one method named "+name+" in "+caller.getName());
+            // discard overrides
+            if (foundMethod == null)
+                foundMethod = method;
+            else if (foundMethod.getDeclaringClass().isAssignableFrom(method.getDeclaringClass()))
+                foundMethod = method;
+        }
+        if (foundMethod == null)
+            throw newIllegalArgumentException("no method named "+name+" in "+caller.getName());
+        MethodHandle entryPoint = MethodHandleImpl.findMethod(IMPL_TOKEN, foundMethod, true, caller);
+        if (type != null) {
+            MethodType epType = type.insertParameterTypes(0, entryPoint.type().parameterType(0));
+            entryPoint = MethodHandles.convertArguments(entryPoint, epType);
+        }
+        return entryPoint;
     }
 
     /** Make sure the given {@code argument} can be used as {@code argnum}-th
@@ -175,6 +222,24 @@
 
     @Override
     public String toString() {
-        return "Bound[" + super.toString() + "]";
+        MethodHandle mh = this;
+        while (mh instanceof BoundMethodHandle) {
+            Object info = MethodHandleNatives.getTargetInfo(mh);
+            if (info instanceof MethodHandle) {
+                mh = (MethodHandle) info;
+            } else {
+                String name = null;
+                if (info instanceof MemberName)
+                    name = ((MemberName)info).getName();
+                if (name != null)
+                    return name;
+                else
+                    return super.toString(); // <unknown>, probably
+            }
+            assert(mh != this);
+            if (mh instanceof JavaMethodHandle)
+                break;  // access JMH.toString(), not BMH.toString()
+        }
+        return mh.toString();
     }
 }
--- a/jdk/src/share/classes/sun/dyn/CallSiteImpl.java	Thu Dec 17 14:10:20 2009 -0800
+++ b/jdk/src/share/classes/sun/dyn/CallSiteImpl.java	Wed Jul 05 17:04:56 2017 +0200
@@ -26,34 +26,51 @@
 package sun.dyn;
 
 import java.dyn.*;
+import java.util.logging.Level;
+import java.util.logging.Logger;
 
 /**
- * The CallSite privately created by the JVM at every invokedynamic instruction.
+ * Parts of CallSite known to the JVM.
+ * FIXME: Merge all this into CallSite proper.
  * @author jrose
  */
-class CallSiteImpl extends CallSite {
-    // Fields used only by the JVM.  Do not use or change.
+public class CallSiteImpl {
+    // Field used only by the JVM.  Do not use or change.
     private Object vmmethod;
 
     // Values supplied by the JVM:
-    int callerMID, callerBCI;
+    protected int callerMID, callerBCI;
+
+    private MethodHandle target;
+    protected final Object caller;  // usually a class
+    protected final String name;
+    protected final MethodType type;
 
-    private CallSiteImpl(Class<?> caller, String name, MethodType type) {
-        super(caller, name, type);
+    /** called only directly from CallSite() */
+    protected CallSiteImpl(Access token, Object caller, String name, MethodType type) {
+        Access.check(token);
+        this.caller = caller;
+        this.name = name;
+        this.type = type;
     }
 
-    @Override
-    public void setTarget(MethodHandle mh) {
-        checkTarget(mh);
-        if (MethodHandleNatives.JVM_SUPPORT)
-            MethodHandleNatives.linkCallSite(this, (MethodHandle) mh);
-        else
-            super.setTarget(mh);
+    /** native version of setTarget */
+    protected void setTarget(MethodHandle mh) {
+        //System.out.println("setTarget "+this+" := "+mh);
+        // XXX I don't know how to fix this properly.
+//         if (false && MethodHandleNatives.JVM_SUPPORT) // FIXME: enable this
+//             MethodHandleNatives.linkCallSite(this, mh);
+//         else
+            this.target = mh;
+    }
+
+    protected MethodHandle getTarget() {
+        return target;
     }
 
     private static final MethodHandle PRIVATE_INITIALIZE_CALL_SITE =
             MethodHandleImpl.IMPL_LOOKUP.findStatic(CallSite.class, "privateInitializeCallSite",
-                MethodType.make(void.class, CallSite.class, int.class, int.class));
+                MethodType.methodType(void.class, CallSite.class, int.class, int.class));
 
     // this is the up-call from the JVM:
     static CallSite makeSite(Class<?> caller, String name, MethodType type,
@@ -61,10 +78,25 @@
         MethodHandle bsm = Linkage.getBootstrapMethod(caller);
         if (bsm == null)
             throw new InvokeDynamicBootstrapError("class has no bootstrap method: "+caller);
-        CallSite site = bsm.<CallSite>invoke(caller, name, type);
+        CallSite site;
+        try {
+            site = bsm.<CallSite>invoke(caller, name, type);
+        } catch (Throwable ex) {
+            throw new InvokeDynamicBootstrapError("exception thrown while linking", ex);
+        }
         if (site == null)
             throw new InvokeDynamicBootstrapError("class bootstrap method failed to create a call site: "+caller);
-        PRIVATE_INITIALIZE_CALL_SITE.<void>invoke(site, callerMID, callerBCI);
+        if (site.type() != type)
+            throw new InvokeDynamicBootstrapError("call site type not initialized correctly: "+site);
+        if (site.callerClass() != caller)
+            throw new InvokeDynamicBootstrapError("call site caller not initialized correctly: "+site);
+        if ((Object)site.name() != name)
+            throw new InvokeDynamicBootstrapError("call site name not initialized correctly: "+site);
+        try {
+            PRIVATE_INITIALIZE_CALL_SITE.<void>invoke(site, callerMID, callerBCI);
+        } catch (Throwable ex) {
+            throw new InvokeDynamicBootstrapError("call site initialization exception", ex);
+        }
         return site;
     }
 }
--- a/jdk/src/share/classes/sun/dyn/FilterGeneric.java	Thu Dec 17 14:10:20 2009 -0800
+++ b/jdk/src/share/classes/sun/dyn/FilterGeneric.java	Wed Jul 05 17:04:56 2017 +0200
@@ -31,174 +31,159 @@
 import java.dyn.NoAccessException;
 import java.lang.reflect.Constructor;
 import java.lang.reflect.InvocationTargetException;
+import static sun.dyn.MemberName.newIllegalArgumentException;
 
 /**
- * "Flyby adapters" which apply arbitrary conversions to arguments
+ * These adapters apply arbitrary conversions to arguments
  * on the way to a ultimate target.
  * For simplicity, these are all generically typed.
  * @author jrose
  */
 class FilterGeneric {
-    // type for the outgoing call (will be generic)
-    private final MethodType targetType;
-    // position of (first) argument to participate in filtering
-    private final short argumentPosition;
-    // number of arguments to participate in filtering
-    private final short argumentCount;
-    // how the result interacts with the filtered arguments: Prepend, Append, Replace, Discard
-    private final char replaceMode;
-    // prototype adapter (clone and customize for each new target & conversion!)
-    private final Adapter adapter;
-    // entry point for adapter (Adapter mh, a...) => ...
-    private final MethodHandle entryPoint;
-    // more of them (loosely cached)
-    private FilterGeneric variations;
+    // type for the incoming call (will be generic)
+    private final MethodType entryType;
+    // prototype adapters (clone and customize for each new target & conversion!)
+    private final Adapter[] adapters;
 
-    /** Compute and cache information common to all unboxing adapters
-     *  that can call out to targets of the erasure-family of the given erased type.
+    /** Compute and cache information common to all filtering adapters
+     *  with the given generic type
      */
-    // TO DO: Make this private.
-    FilterGeneric(MethodType targetType, short argumentPosition, short argumentCount, char replaceMode) {
-        if (argumentCount == 0) {
-            if (replaceMode == 'P' || replaceMode == 'A')  replaceMode = 'R';
-            if (replaceMode == 'I')  argumentPosition = 0;
-        }
-        this.targetType = targetType;
-        this.argumentPosition = argumentPosition;
-        this.argumentCount = argumentCount;
-        this.replaceMode = replaceMode;
-        validate(targetType, argumentPosition, argumentCount, replaceMode);
-        Adapter ad = findAdapter(targetType, argumentPosition, argumentCount, replaceMode, filterType());
-        if (ad == null)
-            ad = buildAdapterFromBytecodes(targetType, argumentPosition, argumentCount, replaceMode, filterType());
-        this.adapter = ad;
-        this.entryPoint = ad.prototypeEntryPoint();
+    FilterGeneric(MethodType entryType) {
+        this.entryType = entryType;
+        int tableSize = Kind.LIMIT.invokerIndex(1 + entryType.parameterCount());
+        this.adapters = new Adapter[tableSize];
     }
 
-    Adapter makeInstance(MethodHandle filter, MethodHandle target) {
-        return adapter.makeInstance(entryPoint, filter, target);
+    Adapter getAdapter(Kind kind, int pos) {
+        int index = kind.invokerIndex(pos);
+        Adapter ad = adapters[index];
+        if (ad != null)  return ad;
+        ad = findAdapter(entryType, kind, pos);
+        if (ad == null)
+            ad = buildAdapterFromBytecodes(entryType, kind, pos);
+        adapters[index] = ad;
+        return ad;
+    }
+
+    Adapter makeInstance(Kind kind, int pos, MethodHandle filter, MethodHandle target) {
+        Adapter ad = getAdapter(kind, pos);
+        return ad.makeInstance(ad.prototypeEntryPoint(), filter, target);
+    }
+
+    /** Build an adapter of the given generic type, which invokes filter
+     *  on the selected incoming argument before passing it to the target.
+     * @param pos the argument to filter
+     * @param filter the function to call on the argument
+     * @param target the target to call with the modified argument list
+     * @return an adapter method handle
+     */
+    public static MethodHandle makeArgumentFilter(int pos, MethodHandle filter, MethodHandle target) {
+        return make(Kind.value, pos, filter, target);
     }
 
-    /** Build an adapter of the given generic type, which invokes typedTarget
-     *  on the incoming arguments, after unboxing as necessary.
-     *  The return value is boxed if necessary.
-     * @param genericType  the required type of the result
-     * @param typedTarget the target
+    /** Build an adapter of the given generic type, which invokes a combiner
+     *  on a selected group of leading arguments.
+     *  The result of the combiner is prepended before all those arguments.
+     * @param combiner the function to call on the selected leading arguments
+     * @param target the target to call with the modified argument list
      * @return an adapter method handle
      */
-    public static MethodHandle make(MethodHandle target, int pos, MethodHandle filter) {
-        return FilterGeneric.of(target.type(), (short)pos, (short)1, 'R').makeInstance(filter, target);
+    public static MethodHandle makeArgumentFolder(MethodHandle combiner, MethodHandle target) {
+        int num = combiner.type().parameterCount();
+        return make(Kind.fold, num, combiner, target);
     }
 
-    /** Return the adapter information for this type's erasure. */
-    static FilterGeneric of(MethodType type, short ap, short ac, char mode) {
-        if (type.generic() != type)
-            throw new IllegalArgumentException("must be generic: "+type);
-        validate(type, ap, ac, mode);
-        MethodTypeImpl form = MethodTypeImpl.of(type);
-        FilterGeneric filterGen = form.filterGeneric;
-        if (filterGen == null)
-            form.filterGeneric = filterGen = new FilterGeneric(type, (short)0, (short)1, 'R');
-        return find(filterGen, ap, ac, mode);
+    /** Build an adapter of the given generic type, which invokes a filter
+     *  on the incoming arguments, reified as a group.
+     *  The argument may be modified (by side effects in the filter).
+     *  The arguments, possibly modified, are passed on to the target.
+     * @param filter the function to call on the arguments
+     * @param target the target to call with the possibly-modified argument list
+     * @return an adapter method handle
+     */
+    public static MethodHandle makeFlyby(MethodHandle filter, MethodHandle target) {
+        return make(Kind.flyby, 0, filter, target);
     }
 
-    static FilterGeneric find(FilterGeneric gen, short ap, short ac, char mode) {
-        for (;;) {
-            if (gen.argumentPosition == ap &&
-                gen.argumentCount == ac &&
-                gen.replaceMode == mode) {
-                return gen;
-            }
-            FilterGeneric gen2 = gen.variations;
-            if (gen2 == null)  break;
-            gen = gen2;
-        }
-        FilterGeneric gen2 = new FilterGeneric(gen.targetType, ap, ac, mode);
-        gen.variations = gen2;  // OK if this smashes another cached chain
-        return gen2;
+    /** Build an adapter of the given generic type, which invokes a collector
+     *  on the selected incoming argument and all following arguments.
+     *  The result of the collector replaces all those arguments.
+     * @param collector the function to call on the selected trailing arguments
+     * @param target the target to call with the modified argument list
+     * @return an adapter method handle
+     */
+    public static MethodHandle makeArgumentCollector(MethodHandle collector, MethodHandle target) {
+        int pos = target.type().parameterCount() - 1;
+        return make(Kind.collect, pos, collector, target);
     }
 
-    private static void validate(MethodType type, short ap, short ac, char mode) {
-        int endpos = ap + ac;
-        switch (mode) {
-            case 'P': case 'A': case 'R': case 'D':
-                if (ap >= 0 && ac >= 0 &&
-                        endpos >= 0 && endpos <= type.parameterCount())
-                    return;
-            default:
-                throw new InternalError("configuration "+patternName(ap, ac, mode));
-        }
+    static MethodHandle make(Kind kind, int pos, MethodHandle filter, MethodHandle target) {
+        FilterGeneric fgen = of(kind, pos, filter.type(), target.type());
+        return fgen.makeInstance(kind, pos, filter, target);
+    }
+
+    /** Return the adapter information for this target and filter type. */
+    static FilterGeneric of(Kind kind, int pos, MethodType filterType, MethodType targetType) {
+        MethodType entryType = entryType(kind, pos, filterType, targetType);
+        if (entryType.generic() != entryType)
+            throw newIllegalArgumentException("must be generic: "+entryType);
+        MethodTypeImpl form = MethodTypeImpl.of(entryType);
+        FilterGeneric filterGen = form.filterGeneric;
+        if (filterGen == null)
+            form.filterGeneric = filterGen = new FilterGeneric(entryType);
+        return filterGen;
     }
 
     public String toString() {
-        return "FilterGeneric/"+patternName()+targetType;
-    }
-
-    String patternName() {
-        return patternName(argumentPosition, argumentCount, replaceMode);
-    }
-
-    static String patternName(short ap, short ac, char mode) {
-        return ""+mode+ap+(ac>1?"_"+ac:"");
-    }
-
-    Class<?> filterType() {
-        return Object.class;  // result of filter operation; an uninteresting type
+        return "FilterGeneric/"+entryType;
     }
 
-    static MethodType targetType(MethodType entryType, short ap, short ac, char mode,
-                                 Class<?> arg) {
+    static MethodType targetType(MethodType entryType, Kind kind, int pos, MethodType filterType) {
         MethodType type = entryType;
-        int pos = ap;
-        switch (mode) {
-            case 'A':
-                pos += ac;
-            case 'P':
-                type = type.insertParameterType(pos, arg);
+        switch (kind) {
+            case value:
+            case flyby:
+                break;  // no change
+            case fold:
+                type = type.insertParameterTypes(0, filterType.returnType());
                 break;
-            case 'I':
-                for (int i = 1; i < ac; i++)
-                    type = type.dropParameterType(pos);
-                assert(type.parameterType(pos) == arg);
+            case collect:
+                type = type.dropParameterTypes(pos, type.parameterCount());
+                type = type.insertParameterTypes(pos, filterType.returnType());
                 break;
-            case 'D':
-                break;
+            default:
+                throw new InternalError();
         }
         return type;
     }
 
-    static MethodType entryType(MethodType targetType, short ap, short ac, char mode,
-                                Class<?> arg) {
+    static MethodType entryType(Kind kind, int pos, MethodType filterType, MethodType targetType) {
         MethodType type = targetType;
-        int pos = ap;
-        switch (mode) {
-            case 'A':
-                pos += ac;
-            case 'P':
-                type = type.dropParameterType(pos);
+        switch (kind) {
+            case value:
+            case flyby:
+                break;  // no change
+            case fold:
+                type = type.dropParameterTypes(0, 1);
                 break;
-            case 'I':
-                for (int i = 1; i < ac; i++)
-                    type = type.insertParameterType(pos, arg);
-                assert(type.parameterType(pos) == arg);
+            case collect:
+                type = type.dropParameterTypes(pos, pos+1);
+                type = type.insertParameterTypes(pos, filterType.parameterList());
                 break;
-            case 'D':
-                break;
+            default:
+                throw new InternalError();
         }
         return type;
     }
 
     /* Create an adapter that handles spreading calls for the given type. */
-    static Adapter findAdapter(MethodType targetType, short ap, short ac, char mode, Class<?> arg) {
-        MethodType entryType = entryType(targetType, ap, ac, mode, arg);
-        int argc = targetType.parameterCount();
-        String pname = patternName(ap, ac, mode);
+    static Adapter findAdapter(MethodType entryType, Kind kind, int pos) {
+        int argc = entryType.parameterCount();
         String cname0 = "F"+argc;
-        String cname1 = "F"+argc+mode;
-        String cname2 = "F"+argc+pname;
-        String[] cnames = { cname0, cname1, cname1+"X", cname2 };
-        String iname = "invoke_"+pname;
-        // e.g., F5R; invoke_R3
+        String cname1 = "F"+argc+kind.key;
+        String[] cnames = { cname0, cname1 };
+        String iname = kind.invokerName(pos);
+        // e.g., F5; invoke_C3
         for (String cname : cnames) {
             Class<? extends Adapter> acls = Adapter.findSubClass(cname);
             if (acls == null)  continue;
@@ -220,7 +205,10 @@
                 // Produce an instance configured as a prototype.
                 return ctor.newInstance(entryPoint);
             } catch (IllegalArgumentException ex) {
-            } catch (InvocationTargetException ex) {
+            } catch (InvocationTargetException wex) {
+                Throwable ex = wex.getTargetException();
+                if (ex instanceof Error)  throw (Error)ex;
+                if (ex instanceof RuntimeException)  throw (RuntimeException)ex;
             } catch (InstantiationException ex) {
             } catch (IllegalAccessException ex) {
             }
@@ -228,7 +216,7 @@
         return null;
     }
 
-    static Adapter buildAdapterFromBytecodes(MethodType targetType, short ap, short ac, char mode, Class<?> arg) {
+    static Adapter buildAdapterFromBytecodes(MethodType entryType, Kind kind, int pos) {
         throw new UnsupportedOperationException("NYI");
     }
 
@@ -242,8 +230,13 @@
      * generated once per type erasure family, and reused across adapters.
      */
     static abstract class Adapter extends JavaMethodHandle {
-        protected final MethodHandle filter;
-        protected final MethodHandle target;
+        protected final MethodHandle filter; // transforms one or more arguments
+        protected final MethodHandle target; // ultimate target
+
+        @Override
+        public String toString() {
+            return target.toString();
+        }
 
         protected boolean isPrototype() { return target == null; }
         protected Adapter(MethodHandle entryPoint) {
@@ -287,52 +280,4221 @@
         }
     }
 
-    //* generated classes follow this pattern:
-    static class F1RX extends Adapter {
-        protected F1RX(MethodHandle entryPoint) { super(entryPoint); }  // to build prototype
-        protected F1RX(MethodHandle e, MethodHandle f, MethodHandle t)
-                        { super(e, f, t); }
-        protected F1RX makeInstance(MethodHandle e, MethodHandle f, MethodHandle t)
-                        { return new F1RX(e, f, t); }
-        protected Object filter(Object a0) { return filter.<Object>invoke(a0); }
-        protected Object target(Object a0) { return target.<Object>invoke(a0); }
-        protected Object invoke_R0(Object a0) { return target(filter(a0)); }
-    }
-    static class F2RX extends Adapter {
-        protected F2RX(MethodHandle entryPoint) { super(entryPoint); }  // to build prototype
-        protected F2RX(MethodHandle e, MethodHandle f, MethodHandle t)
-                        { super(e, f, t); }
-        protected F2RX makeInstance(MethodHandle e, MethodHandle f, MethodHandle t)
-                        { return new F2RX(e, f, t); }
-        protected Object filter(Object a0) { return filter.<Object>invoke(a0); }
-        protected Object target(Object a0, Object a1) { return target.<Object>invoke(a0, a1); }
-        protected Object invoke_R0(Object a0, Object a1) { return target(filter(a0), a1); }
-        protected Object invoke_R1(Object a0, Object a1) { return target(a0, filter(a1)); }
+    static enum Kind {
+        value('V'),      // filter and replace Nth argument value
+        fold('F'),       // fold first N arguments, prepend result
+        collect('C'),    // collect last N arguments, replace with result
+        flyby('Y'),      // reify entire argument list, filter, pass to target
+        LIMIT('?');
+        static final int COUNT = LIMIT.ordinal();
+
+        final char key;
+        Kind(char key) { this.key = key; }
+        String invokerName(int pos) { return "invoke_"+key+""+pos; }
+        int invokerIndex(int pos) { return pos * COUNT + ordinal(); }
     }
-    static class F3RX extends Adapter {
-        protected F3RX(MethodHandle entryPoint) { super(entryPoint); }  // to build prototype
-        protected F3RX(MethodHandle e, MethodHandle f, MethodHandle t)
+
+    /* generated classes follow this pattern:
+    static class F1X extends Adapter {
+        protected F1X(MethodHandle entryPoint) { super(entryPoint); }  // to build prototype
+        protected F1X(MethodHandle e, MethodHandle f, MethodHandle t)
                         { super(e, f, t); }
-        protected F3RX makeInstance(MethodHandle e, MethodHandle f, MethodHandle t)
-                        { return new F3RX(e, f, t); }
-        protected Object filter(Object a0) { return filter.<Object>invoke(a0); }
-        protected Object target(Object a0, Object a1, Object a2) { return target.<Object>invoke(a0, a1, a2); }
-        protected Object invoke_R0(Object a0, Object a1, Object a2) { return target(filter(a0), a1, a2); }
-        protected Object invoke_R1(Object a0, Object a1, Object a2) { return target(a0, filter(a1), a2); }
-        protected Object invoke_R2(Object a0, Object a1, Object a2) { return target(a0, a1, filter(a2)); }
+        protected F1X makeInstance(MethodHandle e, MethodHandle f, MethodHandle t)
+                        { return new F1X(e, f, t); }
+        protected Object invoke_V0(Object a0) { return target.invoke(filter.invoke(a0)); }
+        protected Object invoke_F0(Object a0) { return target.invoke(filter.invoke(), a0); }
+        protected Object invoke_F1(Object a0) { return target.invoke(filter.invoke(a0), a0); }
+        protected Object invoke_C0(Object a0) { return target.invoke(filter.invoke(a0)); }
+        protected Object invoke_C1(Object a0) { return target.invoke(a0, filter.invoke()); }
+        protected Object invoke_Y0(Object a0) { Object[] av = { a0 };
+                       filter.<void>invoke(av); return target.invoke(av[0]); }
     }
-    static class F4RX extends Adapter {
-        protected F4RX(MethodHandle entryPoint) { super(entryPoint); }  // to build prototype
-        protected F4RX(MethodHandle e, MethodHandle f, MethodHandle t)
+    static class F2X extends Adapter {
+        protected F2X(MethodHandle entryPoint) { super(entryPoint); }  // to build prototype
+        protected F2X(MethodHandle e, MethodHandle f, MethodHandle t)
                         { super(e, f, t); }
-        protected F4RX makeInstance(MethodHandle e, MethodHandle f, MethodHandle t)
-                        { return new F4RX(e, f, t); }
-        protected Object filter(Object a0) { return filter.<Object>invoke(a0); }
-        protected Object target(Object a0, Object a1, Object a2, Object a3) { return target.<Object>invoke(a0, a1, a2, a3); }
-        protected Object invoke_R0(Object a0, Object a1, Object a2, Object a3) { return target(filter(a0), a1, a2, a3); }
-        protected Object invoke_R1(Object a0, Object a1, Object a2, Object a3) { return target(a0, filter(a1), a2, a3); }
-        protected Object invoke_R2(Object a0, Object a1, Object a2, Object a3) { return target(a0, a1, filter(a2), a3); }
-        protected Object invoke_R3(Object a0, Object a1, Object a2, Object a3) { return target(a0, a1, a2, filter(a3)); }
+        protected F2X makeInstance(MethodHandle e, MethodHandle f, MethodHandle t)
+                        { return new F2X(e, f, t); }
+        protected Object invoke_V0(Object a0, Object a1) { return target.invoke(filter.invoke(a0), a1); }
+        protected Object invoke_V1(Object a0, Object a1) { return target.invoke(a0, filter.invoke(a1)); }
+        protected Object invoke_F0(Object a0, Object a1) { return target.invoke(filter.invoke(), a0, a1); }
+        protected Object invoke_F1(Object a0, Object a1) { return target.invoke(filter.invoke(a0), a0, a1); }
+        protected Object invoke_F2(Object a0, Object a1) { return target.invoke(filter.invoke(a0, a1), a0, a1); }
+        protected Object invoke_C0(Object a0, Object a1) { return target.invoke(filter.invoke(a0, a1)); }
+        protected Object invoke_C1(Object a0, Object a1) { return target.invoke(a0, filter.invoke(a1)); }
+        protected Object invoke_C2(Object a0, Object a1) { return target.invoke(a0, a1, filter.invoke()); }
+        protected Object invoke_Y0(Object a0, Object a1) { Object[] av = { a0, a1 };
+                       filter.<void>invoke(av); return target.invoke(av[0], av[1]); }
     }
     // */
+
+    // This one is written by hand:
+    static class F0 extends Adapter {
+        protected F0(MethodHandle entryPoint) { super(entryPoint); }  // to build prototype
+        protected F0(MethodHandle e, MethodHandle f, MethodHandle t) {
+            super(e, f, t); }
+        protected F0 makeInstance(MethodHandle e, MethodHandle f, MethodHandle t) {
+            return new F0(e, f, t); }
+        protected Object invoke_F0() throws Throwable {
+            return target.invoke(filter.invoke()); }
+        protected Object invoke_C0() throws Throwable {
+            return target.invoke(filter.invoke()); }
+        static final Object[] NO_ARGS = { };
+        protected Object invoke_Y0() throws Throwable {
+            filter.<void>invoke(NO_ARGS); // make the flyby
+            return target.invoke(); }
+    }
+
+/*
+  : SHELL; n=FilterGeneric; cp -p $n.java $n.java-; sed < $n.java- > $n.java+ -e '/{{*{{/,/}}*}}/w /tmp/genclasses.java' -e '/}}*}}/q'; (cd /tmp; javac -d . genclasses.java; java -ea -cp . genclasses | sed 's| *[/]/ *$||') >> $n.java+; echo '}' >> $n.java+; mv $n.java+ $n.java; mv $n.java- $n.java~
+//{{{
+import java.util.*;
+class genclasses {
+    static String[][] TEMPLATES = { {
+        "@for@ N=1..20",
+        "    //@each-cat@",
+        "    static class @cat@ extends Adapter {",
+        "        protected @cat@(MethodHandle entryPoint) { super(entryPoint); }  // to build prototype",
+        "        protected @cat@(MethodHandle e, MethodHandle f, MethodHandle t) {",
+        "            super(e, f, t); }",
+        "        protected @cat@ makeInstance(MethodHandle e, MethodHandle f, MethodHandle t) {",
+        "            return new @cat@(e, f, t); }",
+        "        //@each-P@",
+        "        protected Object invoke_V@P@(@Tvav@) throws Throwable {",
+        "            return target.invoke(@a0_@@Psp@filter.invoke(a@P@)@_aN@); }",
+        "        //@end-P@",
+        "        //@each-P@",
+        "        protected Object invoke_F@P@(@Tvav@) throws Throwable {",
+        "            return target.invoke(filter.invoke(@a0@),",
+        "                                 @av@); }",
+        "        //@end-P@",
+        "        protected Object invoke_F@N@(@Tvav@) throws Throwable {",
+        "            return target.invoke(filter.invoke(@av@),",
+        "                                 @av@); }",
+        "        //@each-P@",
+        "        protected Object invoke_C@P@(@Tvav@) throws Throwable {",
+        "            return target.invoke(@a0_@filter.invoke(a@P@@_aN@)); }",
+        "        //@end-P@",
+        "        protected Object invoke_C@N@(@Tvav@) throws Throwable {",
+        "            return target.invoke(@av@, filter.invoke()); }",
+        "        protected Object invoke_Y0(@Tvav@) throws Throwable {",
+        "            Object[] av = { @av@ };",
+        "            filter.<void>invoke(av); // make the flyby",
+        "            return target.invoke(@av[i]@); }",
+        "    }",
+    } };
+    static final String NEWLINE_INDENT = " //\n                                 ";
+    enum VAR {
+        cat, N, P, Tvav, av, a0, a0_, _aN, Psp, av_i_;
+        public final String pattern = "@"+toString().replace('_','.')+"@";
+        public String binding = toString();
+        static void makeBindings(boolean topLevel, int inargs, int pos) {
+            assert(-1 <= pos && pos < inargs);
+            VAR.cat.binding = "F"+inargs;
+            VAR.N.binding = String.valueOf(inargs); // incoming arg count
+            VAR.P.binding = String.valueOf(pos);  // selected arg position
+            String[] av = new String[inargs];
+            String[] Tvav = new String[inargs];
+            String[] av_i_ = new String[inargs];
+            for (int i = 0; i < inargs; i++) {
+                av[i] = arg(i);
+                av_i_[i] = "av["+i+"]";
+                String spc = "";
+                if (i > 0 && i % 4 == 0) spc = NEWLINE_INDENT+(pos>9?" ":"")+"  ";
+                Tvav[i] = spc+param("Object", av[i]);
+            }
+            VAR.av.binding = comma(av);
+            VAR.av_i_.binding = comma(av_i_);
+            VAR.Tvav.binding = comma(Tvav);
+            if (pos >= 0) {
+                VAR.Psp.binding = (pos > 0 && pos % 10 == 0) ? NEWLINE_INDENT : "";
+                String[] a0 = new String[pos];
+                String[] aN = new String[inargs - (pos+1)];
+                for (int i = 0; i < pos; i++) {
+                    String spc = "";
+                    if (i > 0 && i % 10 == 0) spc = NEWLINE_INDENT;
+                    a0[i] = spc+av[i];
+                }
+                VAR.a0.binding = comma(a0);
+                VAR.a0_.binding = comma(a0, ", ");
+                for (int i = pos+1; i < inargs; i++) {
+                    String spc = "";
+                    if (i > 0 && i % 10 == 0) spc = NEWLINE_INDENT;
+                    aN[i - (pos+1)] = spc+av[i];
+                }
+                VAR._aN.binding = comma(", ", aN);
+            }
+        }
+        static String arg(int i) { return "a"+i; }
+        static String param(String t, String a) { return t+" "+a; }
+        static String comma(String[] v) { return comma(v, ""); }
+        static String comma(String[] v, String sep) { return comma("", v, sep); }
+        static String comma(String sep, String[] v) { return comma(sep, v, ""); }
+        static String comma(String sep1, String[] v, String sep2) {
+            if (v.length == 0)  return "";
+            String res = v[0];
+            for (int i = 1; i < v.length; i++)  res += ", "+v[i];
+            return sep1 + res + sep2;
+        }
+        static String transform(String string) {
+            for (VAR var : values())
+                string = string.replaceAll(var.pattern, var.binding);
+            return string;
+        }
+    }
+    static String[] stringsIn(String[] strings, int beg, int end) {
+        return Arrays.copyOfRange(strings, beg, Math.min(end, strings.length));
+    }
+    static String[] stringsBefore(String[] strings, int pos) {
+        return stringsIn(strings, 0, pos);
+    }
+    static String[] stringsAfter(String[] strings, int pos) {
+        return stringsIn(strings, pos, strings.length);
+    }
+    static int indexAfter(String[] strings, int pos, String tag) {
+        return Math.min(indexBefore(strings, pos, tag) + 1, strings.length);
+    }
+    static int indexBefore(String[] strings, int pos, String tag) {
+        for (int i = pos, end = strings.length; ; i++) {
+            if (i == end || strings[i].endsWith(tag))  return i;
+        }
+    }
+    static int MIN_ARITY, MAX_ARITY;
+    public static void main(String... av) {
+        for (String[] template : TEMPLATES) {
+            int forLinesLimit = indexBefore(template, 0, "@each-cat@");
+            String[] forLines = stringsBefore(template, forLinesLimit);
+            template = stringsAfter(template, forLinesLimit);
+            for (String forLine : forLines)
+                expandTemplate(forLine, template);
+        }
+    }
+    static void expandTemplate(String forLine, String[] template) {
+        String[] params = forLine.split("[^0-9]+");
+        if (params[0].length() == 0)  params = stringsAfter(params, 1);
+        System.out.println("//params="+Arrays.asList(params));
+        int pcur = 0;
+        MIN_ARITY = Integer.valueOf(params[pcur++]);
+        MAX_ARITY = Integer.valueOf(params[pcur++]);
+        if (pcur != params.length)  throw new RuntimeException("bad extra param: "+forLine);
+        for (int inargs = MIN_ARITY; inargs <= MAX_ARITY; inargs++) {
+            expandTemplate(template, true, inargs, -1);
+        }
+    }
+    static void expandTemplate(String[] template, boolean topLevel, int inargs, int pos) {
+        VAR.makeBindings(topLevel, inargs, pos);
+        for (int i = 0; i < template.length; i++) {
+            String line = template[i];
+            if (line.endsWith("@each-cat@")) {
+                // ignore
+            } else if (line.endsWith("@each-P@")) {
+                int blockEnd = indexAfter(template, i, "@end-P@");
+                String[] block = stringsIn(template, i+1, blockEnd-1);
+                for (int pos1 = Math.max(0,pos); pos1 < inargs; pos1++)
+                    expandTemplate(block, false, inargs, pos1);
+                VAR.makeBindings(topLevel, inargs, pos);
+                i = blockEnd-1; continue;
+            } else {
+                System.out.println(VAR.transform(line));
+            }
+        }
+    }
 }
+//}}} */
+//params=[1, 20]
+    static class F1 extends Adapter {
+        protected F1(MethodHandle entryPoint) { super(entryPoint); }  // to build prototype
+        protected F1(MethodHandle e, MethodHandle f, MethodHandle t) {
+            super(e, f, t); }
+        protected F1 makeInstance(MethodHandle e, MethodHandle f, MethodHandle t) {
+            return new F1(e, f, t); }
+        protected Object invoke_V0(Object a0) throws Throwable {
+            return target.invoke(filter.invoke(a0)); }
+        protected Object invoke_F0(Object a0) throws Throwable {
+            return target.invoke(filter.invoke(),
+                                 a0); }
+        protected Object invoke_F1(Object a0) throws Throwable {
+            return target.invoke(filter.invoke(a0),
+                                 a0); }
+        protected Object invoke_C0(Object a0) throws Throwable {
+            return target.invoke(filter.invoke(a0)); }
+        protected Object invoke_C1(Object a0) throws Throwable {
+            return target.invoke(a0, filter.invoke()); }
+        protected Object invoke_Y0(Object a0) throws Throwable {
+            Object[] av = { a0 };
+            filter.<void>invoke(av); // make the flyby
+            return target.invoke(av[0]); }
+    }
+    static class F2 extends Adapter {
+        protected F2(MethodHandle entryPoint) { super(entryPoint); }  // to build prototype
+        protected F2(MethodHandle e, MethodHandle f, MethodHandle t) {
+            super(e, f, t); }
+        protected F2 makeInstance(MethodHandle e, MethodHandle f, MethodHandle t) {
+            return new F2(e, f, t); }
+        protected Object invoke_V0(Object a0, Object a1) throws Throwable {
+            return target.invoke(filter.invoke(a0), a1); }
+        protected Object invoke_V1(Object a0, Object a1) throws Throwable {
+            return target.invoke(a0, filter.invoke(a1)); }
+        protected Object invoke_F0(Object a0, Object a1) throws Throwable {
+            return target.invoke(filter.invoke(),
+                                 a0, a1); }
+        protected Object invoke_F1(Object a0, Object a1) throws Throwable {
+            return target.invoke(filter.invoke(a0),
+                                 a0, a1); }
+        protected Object invoke_F2(Object a0, Object a1) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1),
+                                 a0, a1); }
+        protected Object invoke_C0(Object a0, Object a1) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1)); }
+        protected Object invoke_C1(Object a0, Object a1) throws Throwable {
+            return target.invoke(a0, filter.invoke(a1)); }
+        protected Object invoke_C2(Object a0, Object a1) throws Throwable {
+            return target.invoke(a0, a1, filter.invoke()); }
+        protected Object invoke_Y0(Object a0, Object a1) throws Throwable {
+            Object[] av = { a0, a1 };
+            filter.<void>invoke(av); // make the flyby
+            return target.invoke(av[0], av[1]); }
+    }
+    static class F3 extends Adapter {
+        protected F3(MethodHandle entryPoint) { super(entryPoint); }  // to build prototype
+        protected F3(MethodHandle e, MethodHandle f, MethodHandle t) {
+            super(e, f, t); }
+        protected F3 makeInstance(MethodHandle e, MethodHandle f, MethodHandle t) {
+            return new F3(e, f, t); }
+        protected Object invoke_V0(Object a0, Object a1, Object a2) throws Throwable {
+            return target.invoke(filter.invoke(a0), a1, a2); }
+        protected Object invoke_V1(Object a0, Object a1, Object a2) throws Throwable {
+            return target.invoke(a0, filter.invoke(a1), a2); }
+        protected Object invoke_V2(Object a0, Object a1, Object a2) throws Throwable {
+            return target.invoke(a0, a1, filter.invoke(a2)); }
+        protected Object invoke_F0(Object a0, Object a1, Object a2) throws Throwable {
+            return target.invoke(filter.invoke(),
+                                 a0, a1, a2); }
+        protected Object invoke_F1(Object a0, Object a1, Object a2) throws Throwable {
+            return target.invoke(filter.invoke(a0),
+                                 a0, a1, a2); }
+        protected Object invoke_F2(Object a0, Object a1, Object a2) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1),
+                                 a0, a1, a2); }
+        protected Object invoke_F3(Object a0, Object a1, Object a2) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2),
+                                 a0, a1, a2); }
+        protected Object invoke_C0(Object a0, Object a1, Object a2) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2)); }
+        protected Object invoke_C1(Object a0, Object a1, Object a2) throws Throwable {
+            return target.invoke(a0, filter.invoke(a1, a2)); }
+        protected Object invoke_C2(Object a0, Object a1, Object a2) throws Throwable {
+            return target.invoke(a0, a1, filter.invoke(a2)); }
+        protected Object invoke_C3(Object a0, Object a1, Object a2) throws Throwable {
+            return target.invoke(a0, a1, a2, filter.invoke()); }
+        protected Object invoke_Y0(Object a0, Object a1, Object a2) throws Throwable {
+            Object[] av = { a0, a1, a2 };
+            filter.<void>invoke(av); // make the flyby
+            return target.invoke(av[0], av[1], av[2]); }
+    }
+    static class F4 extends Adapter {
+        protected F4(MethodHandle entryPoint) { super(entryPoint); }  // to build prototype
+        protected F4(MethodHandle e, MethodHandle f, MethodHandle t) {
+            super(e, f, t); }
+        protected F4 makeInstance(MethodHandle e, MethodHandle f, MethodHandle t) {
+            return new F4(e, f, t); }
+        protected Object invoke_V0(Object a0, Object a1, Object a2, Object a3) throws Throwable {
+            return target.invoke(filter.invoke(a0), a1, a2, a3); }
+        protected Object invoke_V1(Object a0, Object a1, Object a2, Object a3) throws Throwable {
+            return target.invoke(a0, filter.invoke(a1), a2, a3); }
+        protected Object invoke_V2(Object a0, Object a1, Object a2, Object a3) throws Throwable {
+            return target.invoke(a0, a1, filter.invoke(a2), a3); }
+        protected Object invoke_V3(Object a0, Object a1, Object a2, Object a3) throws Throwable {
+            return target.invoke(a0, a1, a2, filter.invoke(a3)); }
+        protected Object invoke_F0(Object a0, Object a1, Object a2, Object a3) throws Throwable {
+            return target.invoke(filter.invoke(),
+                                 a0, a1, a2, a3); }
+        protected Object invoke_F1(Object a0, Object a1, Object a2, Object a3) throws Throwable {
+            return target.invoke(filter.invoke(a0),
+                                 a0, a1, a2, a3); }
+        protected Object invoke_F2(Object a0, Object a1, Object a2, Object a3) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1),
+                                 a0, a1, a2, a3); }
+        protected Object invoke_F3(Object a0, Object a1, Object a2, Object a3) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2),
+                                 a0, a1, a2, a3); }
+        protected Object invoke_F4(Object a0, Object a1, Object a2, Object a3) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3),
+                                 a0, a1, a2, a3); }
+        protected Object invoke_C0(Object a0, Object a1, Object a2, Object a3) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3)); }
+        protected Object invoke_C1(Object a0, Object a1, Object a2, Object a3) throws Throwable {
+            return target.invoke(a0, filter.invoke(a1, a2, a3)); }
+        protected Object invoke_C2(Object a0, Object a1, Object a2, Object a3) throws Throwable {
+            return target.invoke(a0, a1, filter.invoke(a2, a3)); }
+        protected Object invoke_C3(Object a0, Object a1, Object a2, Object a3) throws Throwable {
+            return target.invoke(a0, a1, a2, filter.invoke(a3)); }
+        protected Object invoke_C4(Object a0, Object a1, Object a2, Object a3) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, filter.invoke()); }
+        protected Object invoke_Y0(Object a0, Object a1, Object a2, Object a3) throws Throwable {
+            Object[] av = { a0, a1, a2, a3 };
+            filter.<void>invoke(av); // make the flyby
+            return target.invoke(av[0], av[1], av[2], av[3]); }
+    }
+    static class F5 extends Adapter {
+        protected F5(MethodHandle entryPoint) { super(entryPoint); }  // to build prototype
+        protected F5(MethodHandle e, MethodHandle f, MethodHandle t) {
+            super(e, f, t); }
+        protected F5 makeInstance(MethodHandle e, MethodHandle f, MethodHandle t) {
+            return new F5(e, f, t); }
+        protected Object invoke_V0(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4) throws Throwable {
+            return target.invoke(filter.invoke(a0), a1, a2, a3, a4); }
+        protected Object invoke_V1(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4) throws Throwable {
+            return target.invoke(a0, filter.invoke(a1), a2, a3, a4); }
+        protected Object invoke_V2(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4) throws Throwable {
+            return target.invoke(a0, a1, filter.invoke(a2), a3, a4); }
+        protected Object invoke_V3(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4) throws Throwable {
+            return target.invoke(a0, a1, a2, filter.invoke(a3), a4); }
+        protected Object invoke_V4(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, filter.invoke(a4)); }
+        protected Object invoke_F0(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4) throws Throwable {
+            return target.invoke(filter.invoke(),
+                                 a0, a1, a2, a3, a4); }
+        protected Object invoke_F1(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4) throws Throwable {
+            return target.invoke(filter.invoke(a0),
+                                 a0, a1, a2, a3, a4); }
+        protected Object invoke_F2(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1),
+                                 a0, a1, a2, a3, a4); }
+        protected Object invoke_F3(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2),
+                                 a0, a1, a2, a3, a4); }
+        protected Object invoke_F4(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3),
+                                 a0, a1, a2, a3, a4); }
+        protected Object invoke_F5(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3, a4),
+                                 a0, a1, a2, a3, a4); }
+        protected Object invoke_C0(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3, a4)); }
+        protected Object invoke_C1(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4) throws Throwable {
+            return target.invoke(a0, filter.invoke(a1, a2, a3, a4)); }
+        protected Object invoke_C2(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4) throws Throwable {
+            return target.invoke(a0, a1, filter.invoke(a2, a3, a4)); }
+        protected Object invoke_C3(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4) throws Throwable {
+            return target.invoke(a0, a1, a2, filter.invoke(a3, a4)); }
+        protected Object invoke_C4(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, filter.invoke(a4)); }
+        protected Object invoke_C5(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, filter.invoke()); }
+        protected Object invoke_Y0(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4) throws Throwable {
+            Object[] av = { a0, a1, a2, a3, a4 };
+            filter.<void>invoke(av); // make the flyby
+            return target.invoke(av[0], av[1], av[2], av[3], av[4]); }
+    }
+    static class F6 extends Adapter {
+        protected F6(MethodHandle entryPoint) { super(entryPoint); }  // to build prototype
+        protected F6(MethodHandle e, MethodHandle f, MethodHandle t) {
+            super(e, f, t); }
+        protected F6 makeInstance(MethodHandle e, MethodHandle f, MethodHandle t) {
+            return new F6(e, f, t); }
+        protected Object invoke_V0(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5) throws Throwable {
+            return target.invoke(filter.invoke(a0), a1, a2, a3, a4, a5); }
+        protected Object invoke_V1(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5) throws Throwable {
+            return target.invoke(a0, filter.invoke(a1), a2, a3, a4, a5); }
+        protected Object invoke_V2(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5) throws Throwable {
+            return target.invoke(a0, a1, filter.invoke(a2), a3, a4, a5); }
+        protected Object invoke_V3(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5) throws Throwable {
+            return target.invoke(a0, a1, a2, filter.invoke(a3), a4, a5); }
+        protected Object invoke_V4(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, filter.invoke(a4), a5); }
+        protected Object invoke_V5(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, filter.invoke(a5)); }
+        protected Object invoke_F0(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5) throws Throwable {
+            return target.invoke(filter.invoke(),
+                                 a0, a1, a2, a3, a4, a5); }
+        protected Object invoke_F1(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5) throws Throwable {
+            return target.invoke(filter.invoke(a0),
+                                 a0, a1, a2, a3, a4, a5); }
+        protected Object invoke_F2(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1),
+                                 a0, a1, a2, a3, a4, a5); }
+        protected Object invoke_F3(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2),
+                                 a0, a1, a2, a3, a4, a5); }
+        protected Object invoke_F4(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3),
+                                 a0, a1, a2, a3, a4, a5); }
+        protected Object invoke_F5(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3, a4),
+                                 a0, a1, a2, a3, a4, a5); }
+        protected Object invoke_F6(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5),
+                                 a0, a1, a2, a3, a4, a5); }
+        protected Object invoke_C0(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5)); }
+        protected Object invoke_C1(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5) throws Throwable {
+            return target.invoke(a0, filter.invoke(a1, a2, a3, a4, a5)); }
+        protected Object invoke_C2(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5) throws Throwable {
+            return target.invoke(a0, a1, filter.invoke(a2, a3, a4, a5)); }
+        protected Object invoke_C3(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5) throws Throwable {
+            return target.invoke(a0, a1, a2, filter.invoke(a3, a4, a5)); }
+        protected Object invoke_C4(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, filter.invoke(a4, a5)); }
+        protected Object invoke_C5(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, filter.invoke(a5)); }
+        protected Object invoke_C6(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, filter.invoke()); }
+        protected Object invoke_Y0(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5) throws Throwable {
+            Object[] av = { a0, a1, a2, a3, a4, a5 };
+            filter.<void>invoke(av); // make the flyby
+            return target.invoke(av[0], av[1], av[2], av[3], av[4], av[5]); }
+    }
+    static class F7 extends Adapter {
+        protected F7(MethodHandle entryPoint) { super(entryPoint); }  // to build prototype
+        protected F7(MethodHandle e, MethodHandle f, MethodHandle t) {
+            super(e, f, t); }
+        protected F7 makeInstance(MethodHandle e, MethodHandle f, MethodHandle t) {
+            return new F7(e, f, t); }
+        protected Object invoke_V0(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6) throws Throwable {
+            return target.invoke(filter.invoke(a0), a1, a2, a3, a4, a5, a6); }
+        protected Object invoke_V1(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6) throws Throwable {
+            return target.invoke(a0, filter.invoke(a1), a2, a3, a4, a5, a6); }
+        protected Object invoke_V2(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6) throws Throwable {
+            return target.invoke(a0, a1, filter.invoke(a2), a3, a4, a5, a6); }
+        protected Object invoke_V3(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6) throws Throwable {
+            return target.invoke(a0, a1, a2, filter.invoke(a3), a4, a5, a6); }
+        protected Object invoke_V4(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, filter.invoke(a4), a5, a6); }
+        protected Object invoke_V5(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, filter.invoke(a5), a6); }
+        protected Object invoke_V6(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, filter.invoke(a6)); }
+        protected Object invoke_F0(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6) throws Throwable {
+            return target.invoke(filter.invoke(),
+                                 a0, a1, a2, a3, a4, a5, a6); }
+        protected Object invoke_F1(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6) throws Throwable {
+            return target.invoke(filter.invoke(a0),
+                                 a0, a1, a2, a3, a4, a5, a6); }
+        protected Object invoke_F2(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1),
+                                 a0, a1, a2, a3, a4, a5, a6); }
+        protected Object invoke_F3(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2),
+                                 a0, a1, a2, a3, a4, a5, a6); }
+        protected Object invoke_F4(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3),
+                                 a0, a1, a2, a3, a4, a5, a6); }
+        protected Object invoke_F5(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3, a4),
+                                 a0, a1, a2, a3, a4, a5, a6); }
+        protected Object invoke_F6(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5),
+                                 a0, a1, a2, a3, a4, a5, a6); }
+        protected Object invoke_F7(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6),
+                                 a0, a1, a2, a3, a4, a5, a6); }
+        protected Object invoke_C0(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6)); }
+        protected Object invoke_C1(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6) throws Throwable {
+            return target.invoke(a0, filter.invoke(a1, a2, a3, a4, a5, a6)); }
+        protected Object invoke_C2(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6) throws Throwable {
+            return target.invoke(a0, a1, filter.invoke(a2, a3, a4, a5, a6)); }
+        protected Object invoke_C3(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6) throws Throwable {
+            return target.invoke(a0, a1, a2, filter.invoke(a3, a4, a5, a6)); }
+        protected Object invoke_C4(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, filter.invoke(a4, a5, a6)); }
+        protected Object invoke_C5(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, filter.invoke(a5, a6)); }
+        protected Object invoke_C6(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, filter.invoke(a6)); }
+        protected Object invoke_C7(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, filter.invoke()); }
+        protected Object invoke_Y0(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6) throws Throwable {
+            Object[] av = { a0, a1, a2, a3, a4, a5, a6 };
+            filter.<void>invoke(av); // make the flyby
+            return target.invoke(av[0], av[1], av[2], av[3], av[4], av[5], av[6]); }
+    }
+    static class F8 extends Adapter {
+        protected F8(MethodHandle entryPoint) { super(entryPoint); }  // to build prototype
+        protected F8(MethodHandle e, MethodHandle f, MethodHandle t) {
+            super(e, f, t); }
+        protected F8 makeInstance(MethodHandle e, MethodHandle f, MethodHandle t) {
+            return new F8(e, f, t); }
+        protected Object invoke_V0(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7) throws Throwable {
+            return target.invoke(filter.invoke(a0), a1, a2, a3, a4, a5, a6, a7); }
+        protected Object invoke_V1(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7) throws Throwable {
+            return target.invoke(a0, filter.invoke(a1), a2, a3, a4, a5, a6, a7); }
+        protected Object invoke_V2(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7) throws Throwable {
+            return target.invoke(a0, a1, filter.invoke(a2), a3, a4, a5, a6, a7); }
+        protected Object invoke_V3(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7) throws Throwable {
+            return target.invoke(a0, a1, a2, filter.invoke(a3), a4, a5, a6, a7); }
+        protected Object invoke_V4(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, filter.invoke(a4), a5, a6, a7); }
+        protected Object invoke_V5(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, filter.invoke(a5), a6, a7); }
+        protected Object invoke_V6(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, filter.invoke(a6), a7); }
+        protected Object invoke_V7(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, filter.invoke(a7)); }
+        protected Object invoke_F0(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7) throws Throwable {
+            return target.invoke(filter.invoke(),
+                                 a0, a1, a2, a3, a4, a5, a6, a7); }
+        protected Object invoke_F1(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7) throws Throwable {
+            return target.invoke(filter.invoke(a0),
+                                 a0, a1, a2, a3, a4, a5, a6, a7); }
+        protected Object invoke_F2(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1),
+                                 a0, a1, a2, a3, a4, a5, a6, a7); }
+        protected Object invoke_F3(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2),
+                                 a0, a1, a2, a3, a4, a5, a6, a7); }
+        protected Object invoke_F4(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3),
+                                 a0, a1, a2, a3, a4, a5, a6, a7); }
+        protected Object invoke_F5(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3, a4),
+                                 a0, a1, a2, a3, a4, a5, a6, a7); }
+        protected Object invoke_F6(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5),
+                                 a0, a1, a2, a3, a4, a5, a6, a7); }
+        protected Object invoke_F7(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6),
+                                 a0, a1, a2, a3, a4, a5, a6, a7); }
+        protected Object invoke_F8(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7),
+                                 a0, a1, a2, a3, a4, a5, a6, a7); }
+        protected Object invoke_C0(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7)); }
+        protected Object invoke_C1(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7) throws Throwable {
+            return target.invoke(a0, filter.invoke(a1, a2, a3, a4, a5, a6, a7)); }
+        protected Object invoke_C2(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7) throws Throwable {
+            return target.invoke(a0, a1, filter.invoke(a2, a3, a4, a5, a6, a7)); }
+        protected Object invoke_C3(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7) throws Throwable {
+            return target.invoke(a0, a1, a2, filter.invoke(a3, a4, a5, a6, a7)); }
+        protected Object invoke_C4(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, filter.invoke(a4, a5, a6, a7)); }
+        protected Object invoke_C5(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, filter.invoke(a5, a6, a7)); }
+        protected Object invoke_C6(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, filter.invoke(a6, a7)); }
+        protected Object invoke_C7(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, filter.invoke(a7)); }
+        protected Object invoke_C8(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, filter.invoke()); }
+        protected Object invoke_Y0(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7) throws Throwable {
+            Object[] av = { a0, a1, a2, a3, a4, a5, a6, a7 };
+            filter.<void>invoke(av); // make the flyby
+            return target.invoke(av[0], av[1], av[2], av[3], av[4], av[5], av[6], av[7]); }
+    }
+    static class F9 extends Adapter {
+        protected F9(MethodHandle entryPoint) { super(entryPoint); }  // to build prototype
+        protected F9(MethodHandle e, MethodHandle f, MethodHandle t) {
+            super(e, f, t); }
+        protected F9 makeInstance(MethodHandle e, MethodHandle f, MethodHandle t) {
+            return new F9(e, f, t); }
+        protected Object invoke_V0(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8) throws Throwable {
+            return target.invoke(filter.invoke(a0), a1, a2, a3, a4, a5, a6, a7, a8); }
+        protected Object invoke_V1(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8) throws Throwable {
+            return target.invoke(a0, filter.invoke(a1), a2, a3, a4, a5, a6, a7, a8); }
+        protected Object invoke_V2(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8) throws Throwable {
+            return target.invoke(a0, a1, filter.invoke(a2), a3, a4, a5, a6, a7, a8); }
+        protected Object invoke_V3(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8) throws Throwable {
+            return target.invoke(a0, a1, a2, filter.invoke(a3), a4, a5, a6, a7, a8); }
+        protected Object invoke_V4(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, filter.invoke(a4), a5, a6, a7, a8); }
+        protected Object invoke_V5(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, filter.invoke(a5), a6, a7, a8); }
+        protected Object invoke_V6(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, filter.invoke(a6), a7, a8); }
+        protected Object invoke_V7(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, filter.invoke(a7), a8); }
+        protected Object invoke_V8(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, filter.invoke(a8)); }
+        protected Object invoke_F0(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8) throws Throwable {
+            return target.invoke(filter.invoke(),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8); }
+        protected Object invoke_F1(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8) throws Throwable {
+            return target.invoke(filter.invoke(a0),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8); }
+        protected Object invoke_F2(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8); }
+        protected Object invoke_F3(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8); }
+        protected Object invoke_F4(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8); }
+        protected Object invoke_F5(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3, a4),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8); }
+        protected Object invoke_F6(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8); }
+        protected Object invoke_F7(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8); }
+        protected Object invoke_F8(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8); }
+        protected Object invoke_F9(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8); }
+        protected Object invoke_C0(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
+        protected Object invoke_C1(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8) throws Throwable {
+            return target.invoke(a0, filter.invoke(a1, a2, a3, a4, a5, a6, a7, a8)); }
+        protected Object invoke_C2(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8) throws Throwable {
+            return target.invoke(a0, a1, filter.invoke(a2, a3, a4, a5, a6, a7, a8)); }
+        protected Object invoke_C3(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8) throws Throwable {
+            return target.invoke(a0, a1, a2, filter.invoke(a3, a4, a5, a6, a7, a8)); }
+        protected Object invoke_C4(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, filter.invoke(a4, a5, a6, a7, a8)); }
+        protected Object invoke_C5(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, filter.invoke(a5, a6, a7, a8)); }
+        protected Object invoke_C6(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, filter.invoke(a6, a7, a8)); }
+        protected Object invoke_C7(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, filter.invoke(a7, a8)); }
+        protected Object invoke_C8(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, filter.invoke(a8)); }
+        protected Object invoke_C9(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, filter.invoke()); }
+        protected Object invoke_Y0(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8) throws Throwable {
+            Object[] av = { a0, a1, a2, a3, a4, a5, a6, a7, a8 };
+            filter.<void>invoke(av); // make the flyby
+            return target.invoke(av[0], av[1], av[2], av[3], av[4], av[5], av[6], av[7], av[8]); }
+    }
+    static class F10 extends Adapter {
+        protected F10(MethodHandle entryPoint) { super(entryPoint); }  // to build prototype
+        protected F10(MethodHandle e, MethodHandle f, MethodHandle t) {
+            super(e, f, t); }
+        protected F10 makeInstance(MethodHandle e, MethodHandle f, MethodHandle t) {
+            return new F10(e, f, t); }
+        protected Object invoke_V0(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9) throws Throwable {
+            return target.invoke(filter.invoke(a0), a1, a2, a3, a4, a5, a6, a7, a8, a9); }
+        protected Object invoke_V1(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9) throws Throwable {
+            return target.invoke(a0, filter.invoke(a1), a2, a3, a4, a5, a6, a7, a8, a9); }
+        protected Object invoke_V2(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9) throws Throwable {
+            return target.invoke(a0, a1, filter.invoke(a2), a3, a4, a5, a6, a7, a8, a9); }
+        protected Object invoke_V3(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9) throws Throwable {
+            return target.invoke(a0, a1, a2, filter.invoke(a3), a4, a5, a6, a7, a8, a9); }
+        protected Object invoke_V4(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, filter.invoke(a4), a5, a6, a7, a8, a9); }
+        protected Object invoke_V5(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, filter.invoke(a5), a6, a7, a8, a9); }
+        protected Object invoke_V6(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, filter.invoke(a6), a7, a8, a9); }
+        protected Object invoke_V7(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, filter.invoke(a7), a8, a9); }
+        protected Object invoke_V8(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, filter.invoke(a8), a9); }
+        protected Object invoke_V9(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, filter.invoke(a9)); }
+        protected Object invoke_F0(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9) throws Throwable {
+            return target.invoke(filter.invoke(),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
+        protected Object invoke_F1(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9) throws Throwable {
+            return target.invoke(filter.invoke(a0),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
+        protected Object invoke_F2(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
+        protected Object invoke_F3(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
+        protected Object invoke_F4(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
+        protected Object invoke_F5(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3, a4),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
+        protected Object invoke_F6(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
+        protected Object invoke_F7(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
+        protected Object invoke_F8(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
+        protected Object invoke_F9(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
+        protected Object invoke_F10(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
+        protected Object invoke_C0(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
+        protected Object invoke_C1(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9) throws Throwable {
+            return target.invoke(a0, filter.invoke(a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
+        protected Object invoke_C2(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9) throws Throwable {
+            return target.invoke(a0, a1, filter.invoke(a2, a3, a4, a5, a6, a7, a8, a9)); }
+        protected Object invoke_C3(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9) throws Throwable {
+            return target.invoke(a0, a1, a2, filter.invoke(a3, a4, a5, a6, a7, a8, a9)); }
+        protected Object invoke_C4(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, filter.invoke(a4, a5, a6, a7, a8, a9)); }
+        protected Object invoke_C5(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, filter.invoke(a5, a6, a7, a8, a9)); }
+        protected Object invoke_C6(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, filter.invoke(a6, a7, a8, a9)); }
+        protected Object invoke_C7(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, filter.invoke(a7, a8, a9)); }
+        protected Object invoke_C8(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, filter.invoke(a8, a9)); }
+        protected Object invoke_C9(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, filter.invoke(a9)); }
+        protected Object invoke_C10(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, filter.invoke()); }
+        protected Object invoke_Y0(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9) throws Throwable {
+            Object[] av = { a0, a1, a2, a3, a4, a5, a6, a7, a8, a9 };
+            filter.<void>invoke(av); // make the flyby
+            return target.invoke(av[0], av[1], av[2], av[3], av[4], av[5], av[6], av[7], av[8], av[9]); }
+    }
+    static class F11 extends Adapter {
+        protected F11(MethodHandle entryPoint) { super(entryPoint); }  // to build prototype
+        protected F11(MethodHandle e, MethodHandle f, MethodHandle t) {
+            super(e, f, t); }
+        protected F11 makeInstance(MethodHandle e, MethodHandle f, MethodHandle t) {
+            return new F11(e, f, t); }
+        protected Object invoke_V0(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10) throws Throwable {
+            return target.invoke(filter.invoke(a0), a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10); }
+        protected Object invoke_V1(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10) throws Throwable {
+            return target.invoke(a0, filter.invoke(a1), a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10); }
+        protected Object invoke_V2(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10) throws Throwable {
+            return target.invoke(a0, a1, filter.invoke(a2), a3, a4, a5, a6, a7, a8, a9,
+                                 a10); }
+        protected Object invoke_V3(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10) throws Throwable {
+            return target.invoke(a0, a1, a2, filter.invoke(a3), a4, a5, a6, a7, a8, a9,
+                                 a10); }
+        protected Object invoke_V4(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, filter.invoke(a4), a5, a6, a7, a8, a9,
+                                 a10); }
+        protected Object invoke_V5(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, filter.invoke(a5), a6, a7, a8, a9,
+                                 a10); }
+        protected Object invoke_V6(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, filter.invoke(a6), a7, a8, a9,
+                                 a10); }
+        protected Object invoke_V7(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, filter.invoke(a7), a8, a9,
+                                 a10); }
+        protected Object invoke_V8(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, filter.invoke(a8), a9,
+                                 a10); }
+        protected Object invoke_V9(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, filter.invoke(a9),
+                                 a10); }
+        protected Object invoke_V10(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 filter.invoke(a10)); }
+        protected Object invoke_F0(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10) throws Throwable {
+            return target.invoke(filter.invoke(),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10); }
+        protected Object invoke_F1(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10) throws Throwable {
+            return target.invoke(filter.invoke(a0),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10); }
+        protected Object invoke_F2(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10); }
+        protected Object invoke_F3(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10); }
+        protected Object invoke_F4(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10); }
+        protected Object invoke_F5(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3, a4),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10); }
+        protected Object invoke_F6(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10); }
+        protected Object invoke_F7(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10); }
+        protected Object invoke_F8(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10); }
+        protected Object invoke_F9(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10); }
+        protected Object invoke_F10(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10); }
+        protected Object invoke_F11(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10); }
+        protected Object invoke_C0(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10)); }
+        protected Object invoke_C1(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10) throws Throwable {
+            return target.invoke(a0, filter.invoke(a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10)); }
+        protected Object invoke_C2(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10) throws Throwable {
+            return target.invoke(a0, a1, filter.invoke(a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10)); }
+        protected Object invoke_C3(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10) throws Throwable {
+            return target.invoke(a0, a1, a2, filter.invoke(a3, a4, a5, a6, a7, a8, a9,
+                                 a10)); }
+        protected Object invoke_C4(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, filter.invoke(a4, a5, a6, a7, a8, a9,
+                                 a10)); }
+        protected Object invoke_C5(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, filter.invoke(a5, a6, a7, a8, a9,
+                                 a10)); }
+        protected Object invoke_C6(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, filter.invoke(a6, a7, a8, a9,
+                                 a10)); }
+        protected Object invoke_C7(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, filter.invoke(a7, a8, a9,
+                                 a10)); }
+        protected Object invoke_C8(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, filter.invoke(a8, a9,
+                                 a10)); }
+        protected Object invoke_C9(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, filter.invoke(a9,
+                                 a10)); }
+        protected Object invoke_C10(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, filter.invoke(a10)); }
+        protected Object invoke_C11(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, filter.invoke()); }
+        protected Object invoke_Y0(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10) throws Throwable {
+            Object[] av = { a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10 };
+            filter.<void>invoke(av); // make the flyby
+            return target.invoke(av[0], av[1], av[2], av[3], av[4], av[5], av[6], av[7], av[8], av[9], av[10]); }
+    }
+    static class F12 extends Adapter {
+        protected F12(MethodHandle entryPoint) { super(entryPoint); }  // to build prototype
+        protected F12(MethodHandle e, MethodHandle f, MethodHandle t) {
+            super(e, f, t); }
+        protected F12 makeInstance(MethodHandle e, MethodHandle f, MethodHandle t) {
+            return new F12(e, f, t); }
+        protected Object invoke_V0(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11) throws Throwable {
+            return target.invoke(filter.invoke(a0), a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11); }
+        protected Object invoke_V1(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11) throws Throwable {
+            return target.invoke(a0, filter.invoke(a1), a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11); }
+        protected Object invoke_V2(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11) throws Throwable {
+            return target.invoke(a0, a1, filter.invoke(a2), a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11); }
+        protected Object invoke_V3(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11) throws Throwable {
+            return target.invoke(a0, a1, a2, filter.invoke(a3), a4, a5, a6, a7, a8, a9,
+                                 a10, a11); }
+        protected Object invoke_V4(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, filter.invoke(a4), a5, a6, a7, a8, a9,
+                                 a10, a11); }
+        protected Object invoke_V5(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, filter.invoke(a5), a6, a7, a8, a9,
+                                 a10, a11); }
+        protected Object invoke_V6(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, filter.invoke(a6), a7, a8, a9,
+                                 a10, a11); }
+        protected Object invoke_V7(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, filter.invoke(a7), a8, a9,
+                                 a10, a11); }
+        protected Object invoke_V8(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, filter.invoke(a8), a9,
+                                 a10, a11); }
+        protected Object invoke_V9(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, filter.invoke(a9),
+                                 a10, a11); }
+        protected Object invoke_V10(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 filter.invoke(a10), a11); }
+        protected Object invoke_V11(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, filter.invoke(a11)); }
+        protected Object invoke_F0(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11) throws Throwable {
+            return target.invoke(filter.invoke(),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11); }
+        protected Object invoke_F1(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11) throws Throwable {
+            return target.invoke(filter.invoke(a0),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11); }
+        protected Object invoke_F2(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11); }
+        protected Object invoke_F3(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11); }
+        protected Object invoke_F4(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11); }
+        protected Object invoke_F5(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3, a4),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11); }
+        protected Object invoke_F6(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11); }
+        protected Object invoke_F7(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11); }
+        protected Object invoke_F8(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11); }
+        protected Object invoke_F9(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11); }
+        protected Object invoke_F10(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11); }
+        protected Object invoke_F11(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11); }
+        protected Object invoke_F12(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11); }
+        protected Object invoke_C0(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11)); }
+        protected Object invoke_C1(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11) throws Throwable {
+            return target.invoke(a0, filter.invoke(a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11)); }
+        protected Object invoke_C2(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11) throws Throwable {
+            return target.invoke(a0, a1, filter.invoke(a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11)); }
+        protected Object invoke_C3(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11) throws Throwable {
+            return target.invoke(a0, a1, a2, filter.invoke(a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11)); }
+        protected Object invoke_C4(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, filter.invoke(a4, a5, a6, a7, a8, a9,
+                                 a10, a11)); }
+        protected Object invoke_C5(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, filter.invoke(a5, a6, a7, a8, a9,
+                                 a10, a11)); }
+        protected Object invoke_C6(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, filter.invoke(a6, a7, a8, a9,
+                                 a10, a11)); }
+        protected Object invoke_C7(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, filter.invoke(a7, a8, a9,
+                                 a10, a11)); }
+        protected Object invoke_C8(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, filter.invoke(a8, a9,
+                                 a10, a11)); }
+        protected Object invoke_C9(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, filter.invoke(a9,
+                                 a10, a11)); }
+        protected Object invoke_C10(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, filter.invoke(a10, a11)); }
+        protected Object invoke_C11(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, filter.invoke(a11)); }
+        protected Object invoke_C12(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, filter.invoke()); }
+        protected Object invoke_Y0(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11) throws Throwable {
+            Object[] av = { a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11 };
+            filter.<void>invoke(av); // make the flyby
+            return target.invoke(av[0], av[1], av[2], av[3], av[4], av[5], av[6], av[7], av[8], av[9], av[10], av[11]); }
+    }
+    static class F13 extends Adapter {
+        protected F13(MethodHandle entryPoint) { super(entryPoint); }  // to build prototype
+        protected F13(MethodHandle e, MethodHandle f, MethodHandle t) {
+            super(e, f, t); }
+        protected F13 makeInstance(MethodHandle e, MethodHandle f, MethodHandle t) {
+            return new F13(e, f, t); }
+        protected Object invoke_V0(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12) throws Throwable {
+            return target.invoke(filter.invoke(a0), a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12); }
+        protected Object invoke_V1(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12) throws Throwable {
+            return target.invoke(a0, filter.invoke(a1), a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12); }
+        protected Object invoke_V2(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12) throws Throwable {
+            return target.invoke(a0, a1, filter.invoke(a2), a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12); }
+        protected Object invoke_V3(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12) throws Throwable {
+            return target.invoke(a0, a1, a2, filter.invoke(a3), a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12); }
+        protected Object invoke_V4(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, filter.invoke(a4), a5, a6, a7, a8, a9,
+                                 a10, a11, a12); }
+        protected Object invoke_V5(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, filter.invoke(a5), a6, a7, a8, a9,
+                                 a10, a11, a12); }
+        protected Object invoke_V6(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, filter.invoke(a6), a7, a8, a9,
+                                 a10, a11, a12); }
+        protected Object invoke_V7(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, filter.invoke(a7), a8, a9,
+                                 a10, a11, a12); }
+        protected Object invoke_V8(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, filter.invoke(a8), a9,
+                                 a10, a11, a12); }
+        protected Object invoke_V9(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, filter.invoke(a9),
+                                 a10, a11, a12); }
+        protected Object invoke_V10(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 filter.invoke(a10), a11, a12); }
+        protected Object invoke_V11(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, filter.invoke(a11), a12); }
+        protected Object invoke_V12(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, filter.invoke(a12)); }
+        protected Object invoke_F0(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12) throws Throwable {
+            return target.invoke(filter.invoke(),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12); }
+        protected Object invoke_F1(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12) throws Throwable {
+            return target.invoke(filter.invoke(a0),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12); }
+        protected Object invoke_F2(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12); }
+        protected Object invoke_F3(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12); }
+        protected Object invoke_F4(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12); }
+        protected Object invoke_F5(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3, a4),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12); }
+        protected Object invoke_F6(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12); }
+        protected Object invoke_F7(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12); }
+        protected Object invoke_F8(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12); }
+        protected Object invoke_F9(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12); }
+        protected Object invoke_F10(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12); }
+        protected Object invoke_F11(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12); }
+        protected Object invoke_F12(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12); }
+        protected Object invoke_F13(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12); }
+        protected Object invoke_C0(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12)); }
+        protected Object invoke_C1(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12) throws Throwable {
+            return target.invoke(a0, filter.invoke(a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12)); }
+        protected Object invoke_C2(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12) throws Throwable {
+            return target.invoke(a0, a1, filter.invoke(a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12)); }
+        protected Object invoke_C3(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12) throws Throwable {
+            return target.invoke(a0, a1, a2, filter.invoke(a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12)); }
+        protected Object invoke_C4(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, filter.invoke(a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12)); }
+        protected Object invoke_C5(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, filter.invoke(a5, a6, a7, a8, a9,
+                                 a10, a11, a12)); }
+        protected Object invoke_C6(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, filter.invoke(a6, a7, a8, a9,
+                                 a10, a11, a12)); }
+        protected Object invoke_C7(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, filter.invoke(a7, a8, a9,
+                                 a10, a11, a12)); }
+        protected Object invoke_C8(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, filter.invoke(a8, a9,
+                                 a10, a11, a12)); }
+        protected Object invoke_C9(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, filter.invoke(a9,
+                                 a10, a11, a12)); }
+        protected Object invoke_C10(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, filter.invoke(a10, a11, a12)); }
+        protected Object invoke_C11(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, filter.invoke(a11, a12)); }
+        protected Object invoke_C12(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, filter.invoke(a12)); }
+        protected Object invoke_C13(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, filter.invoke()); }
+        protected Object invoke_Y0(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12) throws Throwable {
+            Object[] av = { a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12 };
+            filter.<void>invoke(av); // make the flyby
+            return target.invoke(av[0], av[1], av[2], av[3], av[4], av[5], av[6], av[7], av[8], av[9], av[10], av[11], av[12]); }
+    }
+    static class F14 extends Adapter {
+        protected F14(MethodHandle entryPoint) { super(entryPoint); }  // to build prototype
+        protected F14(MethodHandle e, MethodHandle f, MethodHandle t) {
+            super(e, f, t); }
+        protected F14 makeInstance(MethodHandle e, MethodHandle f, MethodHandle t) {
+            return new F14(e, f, t); }
+        protected Object invoke_V0(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13) throws Throwable {
+            return target.invoke(filter.invoke(a0), a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13); }
+        protected Object invoke_V1(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13) throws Throwable {
+            return target.invoke(a0, filter.invoke(a1), a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13); }
+        protected Object invoke_V2(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13) throws Throwable {
+            return target.invoke(a0, a1, filter.invoke(a2), a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13); }
+        protected Object invoke_V3(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13) throws Throwable {
+            return target.invoke(a0, a1, a2, filter.invoke(a3), a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13); }
+        protected Object invoke_V4(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, filter.invoke(a4), a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13); }
+        protected Object invoke_V5(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, filter.invoke(a5), a6, a7, a8, a9,
+                                 a10, a11, a12, a13); }
+        protected Object invoke_V6(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, filter.invoke(a6), a7, a8, a9,
+                                 a10, a11, a12, a13); }
+        protected Object invoke_V7(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, filter.invoke(a7), a8, a9,
+                                 a10, a11, a12, a13); }
+        protected Object invoke_V8(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, filter.invoke(a8), a9,
+                                 a10, a11, a12, a13); }
+        protected Object invoke_V9(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, filter.invoke(a9),
+                                 a10, a11, a12, a13); }
+        protected Object invoke_V10(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12, Object a13) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 filter.invoke(a10), a11, a12, a13); }
+        protected Object invoke_V11(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12, Object a13) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, filter.invoke(a11), a12, a13); }
+        protected Object invoke_V12(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12, Object a13) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, filter.invoke(a12), a13); }
+        protected Object invoke_V13(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12, Object a13) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, filter.invoke(a13)); }
+        protected Object invoke_F0(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13) throws Throwable {
+            return target.invoke(filter.invoke(),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13); }
+        protected Object invoke_F1(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13) throws Throwable {
+            return target.invoke(filter.invoke(a0),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13); }
+        protected Object invoke_F2(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13); }
+        protected Object invoke_F3(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13); }
+        protected Object invoke_F4(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13); }
+        protected Object invoke_F5(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3, a4),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13); }
+        protected Object invoke_F6(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13); }
+        protected Object invoke_F7(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13); }
+        protected Object invoke_F8(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13); }
+        protected Object invoke_F9(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13); }
+        protected Object invoke_F10(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12, Object a13) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13); }
+        protected Object invoke_F11(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12, Object a13) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13); }
+        protected Object invoke_F12(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12, Object a13) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13); }
+        protected Object invoke_F13(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12, Object a13) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13); }
+        protected Object invoke_F14(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13); }
+        protected Object invoke_C0(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13)); }
+        protected Object invoke_C1(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13) throws Throwable {
+            return target.invoke(a0, filter.invoke(a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13)); }
+        protected Object invoke_C2(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13) throws Throwable {
+            return target.invoke(a0, a1, filter.invoke(a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13)); }
+        protected Object invoke_C3(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13) throws Throwable {
+            return target.invoke(a0, a1, a2, filter.invoke(a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13)); }
+        protected Object invoke_C4(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, filter.invoke(a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13)); }
+        protected Object invoke_C5(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, filter.invoke(a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13)); }
+        protected Object invoke_C6(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, filter.invoke(a6, a7, a8, a9,
+                                 a10, a11, a12, a13)); }
+        protected Object invoke_C7(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, filter.invoke(a7, a8, a9,
+                                 a10, a11, a12, a13)); }
+        protected Object invoke_C8(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, filter.invoke(a8, a9,
+                                 a10, a11, a12, a13)); }
+        protected Object invoke_C9(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, filter.invoke(a9,
+                                 a10, a11, a12, a13)); }
+        protected Object invoke_C10(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12, Object a13) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, filter.invoke(a10, a11, a12, a13)); }
+        protected Object invoke_C11(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12, Object a13) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, filter.invoke(a11, a12, a13)); }
+        protected Object invoke_C12(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12, Object a13) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, filter.invoke(a12, a13)); }
+        protected Object invoke_C13(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12, Object a13) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, filter.invoke(a13)); }
+        protected Object invoke_C14(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, filter.invoke()); }
+        protected Object invoke_Y0(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13) throws Throwable {
+            Object[] av = { a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13 };
+            filter.<void>invoke(av); // make the flyby
+            return target.invoke(av[0], av[1], av[2], av[3], av[4], av[5], av[6], av[7], av[8], av[9], av[10], av[11], av[12], av[13]); }
+    }
+    static class F15 extends Adapter {
+        protected F15(MethodHandle entryPoint) { super(entryPoint); }  // to build prototype
+        protected F15(MethodHandle e, MethodHandle f, MethodHandle t) {
+            super(e, f, t); }
+        protected F15 makeInstance(MethodHandle e, MethodHandle f, MethodHandle t) {
+            return new F15(e, f, t); }
+        protected Object invoke_V0(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14) throws Throwable {
+            return target.invoke(filter.invoke(a0), a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, a14); }
+        protected Object invoke_V1(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14) throws Throwable {
+            return target.invoke(a0, filter.invoke(a1), a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, a14); }
+        protected Object invoke_V2(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14) throws Throwable {
+            return target.invoke(a0, a1, filter.invoke(a2), a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, a14); }
+        protected Object invoke_V3(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14) throws Throwable {
+            return target.invoke(a0, a1, a2, filter.invoke(a3), a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, a14); }
+        protected Object invoke_V4(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, filter.invoke(a4), a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, a14); }
+        protected Object invoke_V5(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, filter.invoke(a5), a6, a7, a8, a9,
+                                 a10, a11, a12, a13, a14); }
+        protected Object invoke_V6(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, filter.invoke(a6), a7, a8, a9,
+                                 a10, a11, a12, a13, a14); }
+        protected Object invoke_V7(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, filter.invoke(a7), a8, a9,
+                                 a10, a11, a12, a13, a14); }
+        protected Object invoke_V8(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, filter.invoke(a8), a9,
+                                 a10, a11, a12, a13, a14); }
+        protected Object invoke_V9(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, filter.invoke(a9),
+                                 a10, a11, a12, a13, a14); }
+        protected Object invoke_V10(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12, Object a13, Object a14) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 filter.invoke(a10), a11, a12, a13, a14); }
+        protected Object invoke_V11(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12, Object a13, Object a14) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, filter.invoke(a11), a12, a13, a14); }
+        protected Object invoke_V12(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12, Object a13, Object a14) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, filter.invoke(a12), a13, a14); }
+        protected Object invoke_V13(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12, Object a13, Object a14) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, filter.invoke(a13), a14); }
+        protected Object invoke_V14(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12, Object a13, Object a14) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, filter.invoke(a14)); }
+        protected Object invoke_F0(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14) throws Throwable {
+            return target.invoke(filter.invoke(),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14); }
+        protected Object invoke_F1(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14) throws Throwable {
+            return target.invoke(filter.invoke(a0),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14); }
+        protected Object invoke_F2(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14); }
+        protected Object invoke_F3(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14); }
+        protected Object invoke_F4(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14); }
+        protected Object invoke_F5(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3, a4),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14); }
+        protected Object invoke_F6(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14); }
+        protected Object invoke_F7(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14); }
+        protected Object invoke_F8(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14); }
+        protected Object invoke_F9(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14); }
+        protected Object invoke_F10(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12, Object a13, Object a14) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14); }
+        protected Object invoke_F11(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12, Object a13, Object a14) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14); }
+        protected Object invoke_F12(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12, Object a13, Object a14) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14); }
+        protected Object invoke_F13(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12, Object a13, Object a14) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14); }
+        protected Object invoke_F14(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12, Object a13, Object a14) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14); }
+        protected Object invoke_F15(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14); }
+        protected Object invoke_C0(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, a14)); }
+        protected Object invoke_C1(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14) throws Throwable {
+            return target.invoke(a0, filter.invoke(a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, a14)); }
+        protected Object invoke_C2(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14) throws Throwable {
+            return target.invoke(a0, a1, filter.invoke(a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, a14)); }
+        protected Object invoke_C3(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14) throws Throwable {
+            return target.invoke(a0, a1, a2, filter.invoke(a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, a14)); }
+        protected Object invoke_C4(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, filter.invoke(a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, a14)); }
+        protected Object invoke_C5(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, filter.invoke(a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, a14)); }
+        protected Object invoke_C6(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, filter.invoke(a6, a7, a8, a9,
+                                 a10, a11, a12, a13, a14)); }
+        protected Object invoke_C7(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, filter.invoke(a7, a8, a9,
+                                 a10, a11, a12, a13, a14)); }
+        protected Object invoke_C8(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, filter.invoke(a8, a9,
+                                 a10, a11, a12, a13, a14)); }
+        protected Object invoke_C9(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, filter.invoke(a9,
+                                 a10, a11, a12, a13, a14)); }
+        protected Object invoke_C10(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12, Object a13, Object a14) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, filter.invoke(a10, a11, a12, a13, a14)); }
+        protected Object invoke_C11(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12, Object a13, Object a14) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, filter.invoke(a11, a12, a13, a14)); }
+        protected Object invoke_C12(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12, Object a13, Object a14) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, filter.invoke(a12, a13, a14)); }
+        protected Object invoke_C13(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12, Object a13, Object a14) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, filter.invoke(a13, a14)); }
+        protected Object invoke_C14(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12, Object a13, Object a14) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, filter.invoke(a14)); }
+        protected Object invoke_C15(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, filter.invoke()); }
+        protected Object invoke_Y0(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14) throws Throwable {
+            Object[] av = { a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14 };
+            filter.<void>invoke(av); // make the flyby
+            return target.invoke(av[0], av[1], av[2], av[3], av[4], av[5], av[6], av[7], av[8], av[9], av[10], av[11], av[12], av[13], av[14]); }
+    }
+    static class F16 extends Adapter {
+        protected F16(MethodHandle entryPoint) { super(entryPoint); }  // to build prototype
+        protected F16(MethodHandle e, MethodHandle f, MethodHandle t) {
+            super(e, f, t); }
+        protected F16 makeInstance(MethodHandle e, MethodHandle f, MethodHandle t) {
+            return new F16(e, f, t); }
+        protected Object invoke_V0(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15) throws Throwable {
+            return target.invoke(filter.invoke(a0), a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, a14, a15); }
+        protected Object invoke_V1(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15) throws Throwable {
+            return target.invoke(a0, filter.invoke(a1), a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, a14, a15); }
+        protected Object invoke_V2(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15) throws Throwable {
+            return target.invoke(a0, a1, filter.invoke(a2), a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, a14, a15); }
+        protected Object invoke_V3(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15) throws Throwable {
+            return target.invoke(a0, a1, a2, filter.invoke(a3), a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, a14, a15); }
+        protected Object invoke_V4(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, filter.invoke(a4), a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, a14, a15); }
+        protected Object invoke_V5(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, filter.invoke(a5), a6, a7, a8, a9,
+                                 a10, a11, a12, a13, a14, a15); }
+        protected Object invoke_V6(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, filter.invoke(a6), a7, a8, a9,
+                                 a10, a11, a12, a13, a14, a15); }
+        protected Object invoke_V7(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, filter.invoke(a7), a8, a9,
+                                 a10, a11, a12, a13, a14, a15); }
+        protected Object invoke_V8(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, filter.invoke(a8), a9,
+                                 a10, a11, a12, a13, a14, a15); }
+        protected Object invoke_V9(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, filter.invoke(a9),
+                                 a10, a11, a12, a13, a14, a15); }
+        protected Object invoke_V10(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12, Object a13, Object a14, Object a15) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 filter.invoke(a10), a11, a12, a13, a14, a15); }
+        protected Object invoke_V11(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12, Object a13, Object a14, Object a15) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, filter.invoke(a11), a12, a13, a14, a15); }
+        protected Object invoke_V12(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12, Object a13, Object a14, Object a15) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, filter.invoke(a12), a13, a14, a15); }
+        protected Object invoke_V13(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12, Object a13, Object a14, Object a15) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, filter.invoke(a13), a14, a15); }
+        protected Object invoke_V14(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12, Object a13, Object a14, Object a15) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, filter.invoke(a14), a15); }
+        protected Object invoke_V15(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12, Object a13, Object a14, Object a15) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, a14, filter.invoke(a15)); }
+        protected Object invoke_F0(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15) throws Throwable {
+            return target.invoke(filter.invoke(),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15); }
+        protected Object invoke_F1(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15) throws Throwable {
+            return target.invoke(filter.invoke(a0),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15); }
+        protected Object invoke_F2(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15); }
+        protected Object invoke_F3(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15); }
+        protected Object invoke_F4(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15); }
+        protected Object invoke_F5(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3, a4),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15); }
+        protected Object invoke_F6(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15); }
+        protected Object invoke_F7(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15); }
+        protected Object invoke_F8(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15); }
+        protected Object invoke_F9(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15); }
+        protected Object invoke_F10(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12, Object a13, Object a14, Object a15) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15); }
+        protected Object invoke_F11(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12, Object a13, Object a14, Object a15) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15); }
+        protected Object invoke_F12(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12, Object a13, Object a14, Object a15) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15); }
+        protected Object invoke_F13(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12, Object a13, Object a14, Object a15) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15); }
+        protected Object invoke_F14(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12, Object a13, Object a14, Object a15) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15); }
+        protected Object invoke_F15(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12, Object a13, Object a14, Object a15) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, a14),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15); }
+        protected Object invoke_F16(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15); }
+        protected Object invoke_C0(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, a14, a15)); }
+        protected Object invoke_C1(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15) throws Throwable {
+            return target.invoke(a0, filter.invoke(a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, a14, a15)); }
+        protected Object invoke_C2(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15) throws Throwable {
+            return target.invoke(a0, a1, filter.invoke(a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, a14, a15)); }
+        protected Object invoke_C3(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15) throws Throwable {
+            return target.invoke(a0, a1, a2, filter.invoke(a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, a14, a15)); }
+        protected Object invoke_C4(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, filter.invoke(a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, a14, a15)); }
+        protected Object invoke_C5(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, filter.invoke(a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, a14, a15)); }
+        protected Object invoke_C6(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, filter.invoke(a6, a7, a8, a9,
+                                 a10, a11, a12, a13, a14, a15)); }
+        protected Object invoke_C7(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, filter.invoke(a7, a8, a9,
+                                 a10, a11, a12, a13, a14, a15)); }
+        protected Object invoke_C8(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, filter.invoke(a8, a9,
+                                 a10, a11, a12, a13, a14, a15)); }
+        protected Object invoke_C9(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, filter.invoke(a9,
+                                 a10, a11, a12, a13, a14, a15)); }
+        protected Object invoke_C10(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12, Object a13, Object a14, Object a15) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, filter.invoke(a10, a11, a12, a13, a14, a15)); }
+        protected Object invoke_C11(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12, Object a13, Object a14, Object a15) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, filter.invoke(a11, a12, a13, a14, a15)); }
+        protected Object invoke_C12(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12, Object a13, Object a14, Object a15) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, filter.invoke(a12, a13, a14, a15)); }
+        protected Object invoke_C13(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12, Object a13, Object a14, Object a15) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, filter.invoke(a13, a14, a15)); }
+        protected Object invoke_C14(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12, Object a13, Object a14, Object a15) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, filter.invoke(a14, a15)); }
+        protected Object invoke_C15(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12, Object a13, Object a14, Object a15) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, a14, filter.invoke(a15)); }
+        protected Object invoke_C16(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, filter.invoke()); }
+        protected Object invoke_Y0(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15) throws Throwable {
+            Object[] av = { a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15 };
+            filter.<void>invoke(av); // make the flyby
+            return target.invoke(av[0], av[1], av[2], av[3], av[4], av[5], av[6], av[7], av[8], av[9], av[10], av[11], av[12], av[13], av[14], av[15]); }
+    }
+    static class F17 extends Adapter {
+        protected F17(MethodHandle entryPoint) { super(entryPoint); }  // to build prototype
+        protected F17(MethodHandle e, MethodHandle f, MethodHandle t) {
+            super(e, f, t); }
+        protected F17 makeInstance(MethodHandle e, MethodHandle f, MethodHandle t) {
+            return new F17(e, f, t); }
+        protected Object invoke_V0(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15,
+                                   Object a16) throws Throwable {
+            return target.invoke(filter.invoke(a0), a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, a14, a15, a16); }
+        protected Object invoke_V1(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15,
+                                   Object a16) throws Throwable {
+            return target.invoke(a0, filter.invoke(a1), a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, a14, a15, a16); }
+        protected Object invoke_V2(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15,
+                                   Object a16) throws Throwable {
+            return target.invoke(a0, a1, filter.invoke(a2), a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, a14, a15, a16); }
+        protected Object invoke_V3(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15,
+                                   Object a16) throws Throwable {
+            return target.invoke(a0, a1, a2, filter.invoke(a3), a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, a14, a15, a16); }
+        protected Object invoke_V4(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15,
+                                   Object a16) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, filter.invoke(a4), a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, a14, a15, a16); }
+        protected Object invoke_V5(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15,
+                                   Object a16) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, filter.invoke(a5), a6, a7, a8, a9,
+                                 a10, a11, a12, a13, a14, a15, a16); }
+        protected Object invoke_V6(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15,
+                                   Object a16) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, filter.invoke(a6), a7, a8, a9,
+                                 a10, a11, a12, a13, a14, a15, a16); }
+        protected Object invoke_V7(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15,
+                                   Object a16) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, filter.invoke(a7), a8, a9,
+                                 a10, a11, a12, a13, a14, a15, a16); }
+        protected Object invoke_V8(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15,
+                                   Object a16) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, filter.invoke(a8), a9,
+                                 a10, a11, a12, a13, a14, a15, a16); }
+        protected Object invoke_V9(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15,
+                                   Object a16) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, filter.invoke(a9),
+                                 a10, a11, a12, a13, a14, a15, a16); }
+        protected Object invoke_V10(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12, Object a13, Object a14, Object a15,
+                                    Object a16) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 filter.invoke(a10), a11, a12, a13, a14, a15, a16); }
+        protected Object invoke_V11(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12, Object a13, Object a14, Object a15,
+                                    Object a16) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, filter.invoke(a11), a12, a13, a14, a15, a16); }
+        protected Object invoke_V12(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12, Object a13, Object a14, Object a15,
+                                    Object a16) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, filter.invoke(a12), a13, a14, a15, a16); }
+        protected Object invoke_V13(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12, Object a13, Object a14, Object a15,
+                                    Object a16) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, filter.invoke(a13), a14, a15, a16); }
+        protected Object invoke_V14(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12, Object a13, Object a14, Object a15,
+                                    Object a16) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, filter.invoke(a14), a15, a16); }
+        protected Object invoke_V15(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12, Object a13, Object a14, Object a15,
+                                    Object a16) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, a14, filter.invoke(a15), a16); }
+        protected Object invoke_V16(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12, Object a13, Object a14, Object a15,
+                                    Object a16) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, a14, a15, filter.invoke(a16)); }
+        protected Object invoke_F0(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15,
+                                   Object a16) throws Throwable {
+            return target.invoke(filter.invoke(),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16); }
+        protected Object invoke_F1(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15,
+                                   Object a16) throws Throwable {
+            return target.invoke(filter.invoke(a0),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16); }
+        protected Object invoke_F2(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15,
+                                   Object a16) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16); }
+        protected Object invoke_F3(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15,
+                                   Object a16) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16); }
+        protected Object invoke_F4(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15,
+                                   Object a16) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16); }
+        protected Object invoke_F5(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15,
+                                   Object a16) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3, a4),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16); }
+        protected Object invoke_F6(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15,
+                                   Object a16) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16); }
+        protected Object invoke_F7(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15,
+                                   Object a16) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16); }
+        protected Object invoke_F8(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15,
+                                   Object a16) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16); }
+        protected Object invoke_F9(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15,
+                                   Object a16) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16); }
+        protected Object invoke_F10(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12, Object a13, Object a14, Object a15,
+                                    Object a16) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16); }
+        protected Object invoke_F11(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12, Object a13, Object a14, Object a15,
+                                    Object a16) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16); }
+        protected Object invoke_F12(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12, Object a13, Object a14, Object a15,
+                                    Object a16) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16); }
+        protected Object invoke_F13(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12, Object a13, Object a14, Object a15,
+                                    Object a16) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16); }
+        protected Object invoke_F14(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12, Object a13, Object a14, Object a15,
+                                    Object a16) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16); }
+        protected Object invoke_F15(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12, Object a13, Object a14, Object a15,
+                                    Object a16) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, a14),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16); }
+        protected Object invoke_F16(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12, Object a13, Object a14, Object a15,
+                                    Object a16) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, a14, a15),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16); }
+        protected Object invoke_F17(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15,
+                                   Object a16) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16); }
+        protected Object invoke_C0(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15,
+                                   Object a16) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, a14, a15, a16)); }
+        protected Object invoke_C1(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15,
+                                   Object a16) throws Throwable {
+            return target.invoke(a0, filter.invoke(a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, a14, a15, a16)); }
+        protected Object invoke_C2(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15,
+                                   Object a16) throws Throwable {
+            return target.invoke(a0, a1, filter.invoke(a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, a14, a15, a16)); }
+        protected Object invoke_C3(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15,
+                                   Object a16) throws Throwable {
+            return target.invoke(a0, a1, a2, filter.invoke(a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, a14, a15, a16)); }
+        protected Object invoke_C4(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15,
+                                   Object a16) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, filter.invoke(a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, a14, a15, a16)); }
+        protected Object invoke_C5(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15,
+                                   Object a16) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, filter.invoke(a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, a14, a15, a16)); }
+        protected Object invoke_C6(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15,
+                                   Object a16) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, filter.invoke(a6, a7, a8, a9,
+                                 a10, a11, a12, a13, a14, a15, a16)); }
+        protected Object invoke_C7(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15,
+                                   Object a16) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, filter.invoke(a7, a8, a9,
+                                 a10, a11, a12, a13, a14, a15, a16)); }
+        protected Object invoke_C8(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15,
+                                   Object a16) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, filter.invoke(a8, a9,
+                                 a10, a11, a12, a13, a14, a15, a16)); }
+        protected Object invoke_C9(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15,
+                                   Object a16) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, filter.invoke(a9,
+                                 a10, a11, a12, a13, a14, a15, a16)); }
+        protected Object invoke_C10(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12, Object a13, Object a14, Object a15,
+                                    Object a16) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, filter.invoke(a10, a11, a12, a13, a14, a15, a16)); }
+        protected Object invoke_C11(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12, Object a13, Object a14, Object a15,
+                                    Object a16) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, filter.invoke(a11, a12, a13, a14, a15, a16)); }
+        protected Object invoke_C12(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12, Object a13, Object a14, Object a15,
+                                    Object a16) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, filter.invoke(a12, a13, a14, a15, a16)); }
+        protected Object invoke_C13(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12, Object a13, Object a14, Object a15,
+                                    Object a16) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, filter.invoke(a13, a14, a15, a16)); }
+        protected Object invoke_C14(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12, Object a13, Object a14, Object a15,
+                                    Object a16) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, filter.invoke(a14, a15, a16)); }
+        protected Object invoke_C15(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12, Object a13, Object a14, Object a15,
+                                    Object a16) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, a14, filter.invoke(a15, a16)); }
+        protected Object invoke_C16(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12, Object a13, Object a14, Object a15,
+                                    Object a16) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, a14, a15, filter.invoke(a16)); }
+        protected Object invoke_C17(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15,
+                                   Object a16) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, filter.invoke()); }
+        protected Object invoke_Y0(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15,
+                                   Object a16) throws Throwable {
+            Object[] av = { a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16 };
+            filter.<void>invoke(av); // make the flyby
+            return target.invoke(av[0], av[1], av[2], av[3], av[4], av[5], av[6], av[7], av[8], av[9], av[10], av[11], av[12], av[13], av[14], av[15], av[16]); }
+    }
+    static class F18 extends Adapter {
+        protected F18(MethodHandle entryPoint) { super(entryPoint); }  // to build prototype
+        protected F18(MethodHandle e, MethodHandle f, MethodHandle t) {
+            super(e, f, t); }
+        protected F18 makeInstance(MethodHandle e, MethodHandle f, MethodHandle t) {
+            return new F18(e, f, t); }
+        protected Object invoke_V0(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15,
+                                   Object a16, Object a17) throws Throwable {
+            return target.invoke(filter.invoke(a0), a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, a14, a15, a16, a17); }
+        protected Object invoke_V1(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15,
+                                   Object a16, Object a17) throws Throwable {
+            return target.invoke(a0, filter.invoke(a1), a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, a14, a15, a16, a17); }
+        protected Object invoke_V2(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15,
+                                   Object a16, Object a17) throws Throwable {
+            return target.invoke(a0, a1, filter.invoke(a2), a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, a14, a15, a16, a17); }
+        protected Object invoke_V3(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15,
+                                   Object a16, Object a17) throws Throwable {
+            return target.invoke(a0, a1, a2, filter.invoke(a3), a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, a14, a15, a16, a17); }
+        protected Object invoke_V4(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15,
+                                   Object a16, Object a17) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, filter.invoke(a4), a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, a14, a15, a16, a17); }
+        protected Object invoke_V5(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15,
+                                   Object a16, Object a17) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, filter.invoke(a5), a6, a7, a8, a9,
+                                 a10, a11, a12, a13, a14, a15, a16, a17); }
+        protected Object invoke_V6(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15,
+                                   Object a16, Object a17) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, filter.invoke(a6), a7, a8, a9,
+                                 a10, a11, a12, a13, a14, a15, a16, a17); }
+        protected Object invoke_V7(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15,
+                                   Object a16, Object a17) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, filter.invoke(a7), a8, a9,
+                                 a10, a11, a12, a13, a14, a15, a16, a17); }
+        protected Object invoke_V8(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15,
+                                   Object a16, Object a17) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, filter.invoke(a8), a9,
+                                 a10, a11, a12, a13, a14, a15, a16, a17); }
+        protected Object invoke_V9(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15,
+                                   Object a16, Object a17) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, filter.invoke(a9),
+                                 a10, a11, a12, a13, a14, a15, a16, a17); }
+        protected Object invoke_V10(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12, Object a13, Object a14, Object a15,
+                                    Object a16, Object a17) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 filter.invoke(a10), a11, a12, a13, a14, a15, a16, a17); }
+        protected Object invoke_V11(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12, Object a13, Object a14, Object a15,
+                                    Object a16, Object a17) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, filter.invoke(a11), a12, a13, a14, a15, a16, a17); }
+        protected Object invoke_V12(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12, Object a13, Object a14, Object a15,
+                                    Object a16, Object a17) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, filter.invoke(a12), a13, a14, a15, a16, a17); }
+        protected Object invoke_V13(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12, Object a13, Object a14, Object a15,
+                                    Object a16, Object a17) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, filter.invoke(a13), a14, a15, a16, a17); }
+        protected Object invoke_V14(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12, Object a13, Object a14, Object a15,
+                                    Object a16, Object a17) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, filter.invoke(a14), a15, a16, a17); }
+        protected Object invoke_V15(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12, Object a13, Object a14, Object a15,
+                                    Object a16, Object a17) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, a14, filter.invoke(a15), a16, a17); }
+        protected Object invoke_V16(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12, Object a13, Object a14, Object a15,
+                                    Object a16, Object a17) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, a14, a15, filter.invoke(a16), a17); }
+        protected Object invoke_V17(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12, Object a13, Object a14, Object a15,
+                                    Object a16, Object a17) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, a14, a15, a16, filter.invoke(a17)); }
+        protected Object invoke_F0(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15,
+                                   Object a16, Object a17) throws Throwable {
+            return target.invoke(filter.invoke(),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17); }
+        protected Object invoke_F1(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15,
+                                   Object a16, Object a17) throws Throwable {
+            return target.invoke(filter.invoke(a0),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17); }
+        protected Object invoke_F2(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15,
+                                   Object a16, Object a17) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17); }
+        protected Object invoke_F3(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15,
+                                   Object a16, Object a17) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17); }
+        protected Object invoke_F4(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15,
+                                   Object a16, Object a17) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17); }
+        protected Object invoke_F5(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15,
+                                   Object a16, Object a17) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3, a4),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17); }
+        protected Object invoke_F6(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15,
+                                   Object a16, Object a17) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17); }
+        protected Object invoke_F7(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15,
+                                   Object a16, Object a17) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17); }
+        protected Object invoke_F8(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15,
+                                   Object a16, Object a17) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17); }
+        protected Object invoke_F9(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15,
+                                   Object a16, Object a17) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17); }
+        protected Object invoke_F10(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12, Object a13, Object a14, Object a15,
+                                    Object a16, Object a17) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17); }
+        protected Object invoke_F11(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12, Object a13, Object a14, Object a15,
+                                    Object a16, Object a17) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17); }
+        protected Object invoke_F12(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12, Object a13, Object a14, Object a15,
+                                    Object a16, Object a17) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17); }
+        protected Object invoke_F13(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12, Object a13, Object a14, Object a15,
+                                    Object a16, Object a17) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17); }
+        protected Object invoke_F14(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12, Object a13, Object a14, Object a15,
+                                    Object a16, Object a17) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17); }
+        protected Object invoke_F15(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12, Object a13, Object a14, Object a15,
+                                    Object a16, Object a17) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, a14),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17); }
+        protected Object invoke_F16(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12, Object a13, Object a14, Object a15,
+                                    Object a16, Object a17) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, a14, a15),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17); }
+        protected Object invoke_F17(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12, Object a13, Object a14, Object a15,
+                                    Object a16, Object a17) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, a14, a15, a16),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17); }
+        protected Object invoke_F18(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15,
+                                   Object a16, Object a17) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17); }
+        protected Object invoke_C0(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15,
+                                   Object a16, Object a17) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, a14, a15, a16, a17)); }
+        protected Object invoke_C1(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15,
+                                   Object a16, Object a17) throws Throwable {
+            return target.invoke(a0, filter.invoke(a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, a14, a15, a16, a17)); }
+        protected Object invoke_C2(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15,
+                                   Object a16, Object a17) throws Throwable {
+            return target.invoke(a0, a1, filter.invoke(a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, a14, a15, a16, a17)); }
+        protected Object invoke_C3(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15,
+                                   Object a16, Object a17) throws Throwable {
+            return target.invoke(a0, a1, a2, filter.invoke(a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, a14, a15, a16, a17)); }
+        protected Object invoke_C4(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15,
+                                   Object a16, Object a17) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, filter.invoke(a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, a14, a15, a16, a17)); }
+        protected Object invoke_C5(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15,
+                                   Object a16, Object a17) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, filter.invoke(a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, a14, a15, a16, a17)); }
+        protected Object invoke_C6(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15,
+                                   Object a16, Object a17) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, filter.invoke(a6, a7, a8, a9,
+                                 a10, a11, a12, a13, a14, a15, a16, a17)); }
+        protected Object invoke_C7(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15,
+                                   Object a16, Object a17) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, filter.invoke(a7, a8, a9,
+                                 a10, a11, a12, a13, a14, a15, a16, a17)); }
+        protected Object invoke_C8(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15,
+                                   Object a16, Object a17) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, filter.invoke(a8, a9,
+                                 a10, a11, a12, a13, a14, a15, a16, a17)); }
+        protected Object invoke_C9(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15,
+                                   Object a16, Object a17) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, filter.invoke(a9,
+                                 a10, a11, a12, a13, a14, a15, a16, a17)); }
+        protected Object invoke_C10(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12, Object a13, Object a14, Object a15,
+                                    Object a16, Object a17) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, filter.invoke(a10, a11, a12, a13, a14, a15, a16, a17)); }
+        protected Object invoke_C11(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12, Object a13, Object a14, Object a15,
+                                    Object a16, Object a17) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, filter.invoke(a11, a12, a13, a14, a15, a16, a17)); }
+        protected Object invoke_C12(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12, Object a13, Object a14, Object a15,
+                                    Object a16, Object a17) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, filter.invoke(a12, a13, a14, a15, a16, a17)); }
+        protected Object invoke_C13(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12, Object a13, Object a14, Object a15,
+                                    Object a16, Object a17) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, filter.invoke(a13, a14, a15, a16, a17)); }
+        protected Object invoke_C14(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12, Object a13, Object a14, Object a15,
+                                    Object a16, Object a17) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, filter.invoke(a14, a15, a16, a17)); }
+        protected Object invoke_C15(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12, Object a13, Object a14, Object a15,
+                                    Object a16, Object a17) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, a14, filter.invoke(a15, a16, a17)); }
+        protected Object invoke_C16(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12, Object a13, Object a14, Object a15,
+                                    Object a16, Object a17) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, a14, a15, filter.invoke(a16, a17)); }
+        protected Object invoke_C17(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12, Object a13, Object a14, Object a15,
+                                    Object a16, Object a17) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, a14, a15, a16, filter.invoke(a17)); }
+        protected Object invoke_C18(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15,
+                                   Object a16, Object a17) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, filter.invoke()); }
+        protected Object invoke_Y0(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15,
+                                   Object a16, Object a17) throws Throwable {
+            Object[] av = { a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17 };
+            filter.<void>invoke(av); // make the flyby
+            return target.invoke(av[0], av[1], av[2], av[3], av[4], av[5], av[6], av[7], av[8], av[9], av[10], av[11], av[12], av[13], av[14], av[15], av[16], av[17]); }
+    }
+    static class F19 extends Adapter {
+        protected F19(MethodHandle entryPoint) { super(entryPoint); }  // to build prototype
+        protected F19(MethodHandle e, MethodHandle f, MethodHandle t) {
+            super(e, f, t); }
+        protected F19 makeInstance(MethodHandle e, MethodHandle f, MethodHandle t) {
+            return new F19(e, f, t); }
+        protected Object invoke_V0(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15,
+                                   Object a16, Object a17, Object a18) throws Throwable {
+            return target.invoke(filter.invoke(a0), a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, a14, a15, a16, a17, a18); }
+        protected Object invoke_V1(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15,
+                                   Object a16, Object a17, Object a18) throws Throwable {
+            return target.invoke(a0, filter.invoke(a1), a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, a14, a15, a16, a17, a18); }
+        protected Object invoke_V2(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15,
+                                   Object a16, Object a17, Object a18) throws Throwable {
+            return target.invoke(a0, a1, filter.invoke(a2), a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, a14, a15, a16, a17, a18); }
+        protected Object invoke_V3(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15,
+                                   Object a16, Object a17, Object a18) throws Throwable {
+            return target.invoke(a0, a1, a2, filter.invoke(a3), a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, a14, a15, a16, a17, a18); }
+        protected Object invoke_V4(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15,
+                                   Object a16, Object a17, Object a18) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, filter.invoke(a4), a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, a14, a15, a16, a17, a18); }
+        protected Object invoke_V5(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15,
+                                   Object a16, Object a17, Object a18) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, filter.invoke(a5), a6, a7, a8, a9,
+                                 a10, a11, a12, a13, a14, a15, a16, a17, a18); }
+        protected Object invoke_V6(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15,
+                                   Object a16, Object a17, Object a18) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, filter.invoke(a6), a7, a8, a9,
+                                 a10, a11, a12, a13, a14, a15, a16, a17, a18); }
+        protected Object invoke_V7(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15,
+                                   Object a16, Object a17, Object a18) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, filter.invoke(a7), a8, a9,
+                                 a10, a11, a12, a13, a14, a15, a16, a17, a18); }
+        protected Object invoke_V8(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15,
+                                   Object a16, Object a17, Object a18) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, filter.invoke(a8), a9,
+                                 a10, a11, a12, a13, a14, a15, a16, a17, a18); }
+        protected Object invoke_V9(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15,
+                                   Object a16, Object a17, Object a18) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, filter.invoke(a9),
+                                 a10, a11, a12, a13, a14, a15, a16, a17, a18); }
+        protected Object invoke_V10(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12, Object a13, Object a14, Object a15,
+                                    Object a16, Object a17, Object a18) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 filter.invoke(a10), a11, a12, a13, a14, a15, a16, a17, a18); }
+        protected Object invoke_V11(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12, Object a13, Object a14, Object a15,
+                                    Object a16, Object a17, Object a18) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, filter.invoke(a11), a12, a13, a14, a15, a16, a17, a18); }
+        protected Object invoke_V12(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12, Object a13, Object a14, Object a15,
+                                    Object a16, Object a17, Object a18) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, filter.invoke(a12), a13, a14, a15, a16, a17, a18); }
+        protected Object invoke_V13(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12, Object a13, Object a14, Object a15,
+                                    Object a16, Object a17, Object a18) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, filter.invoke(a13), a14, a15, a16, a17, a18); }
+        protected Object invoke_V14(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12, Object a13, Object a14, Object a15,
+                                    Object a16, Object a17, Object a18) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, filter.invoke(a14), a15, a16, a17, a18); }
+        protected Object invoke_V15(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12, Object a13, Object a14, Object a15,
+                                    Object a16, Object a17, Object a18) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, a14, filter.invoke(a15), a16, a17, a18); }
+        protected Object invoke_V16(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12, Object a13, Object a14, Object a15,
+                                    Object a16, Object a17, Object a18) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, a14, a15, filter.invoke(a16), a17, a18); }
+        protected Object invoke_V17(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12, Object a13, Object a14, Object a15,
+                                    Object a16, Object a17, Object a18) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, a14, a15, a16, filter.invoke(a17), a18); }
+        protected Object invoke_V18(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12, Object a13, Object a14, Object a15,
+                                    Object a16, Object a17, Object a18) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, a14, a15, a16, a17, filter.invoke(a18)); }
+        protected Object invoke_F0(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15,
+                                   Object a16, Object a17, Object a18) throws Throwable {
+            return target.invoke(filter.invoke(),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18); }
+        protected Object invoke_F1(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15,
+                                   Object a16, Object a17, Object a18) throws Throwable {
+            return target.invoke(filter.invoke(a0),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18); }
+        protected Object invoke_F2(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15,
+                                   Object a16, Object a17, Object a18) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18); }
+        protected Object invoke_F3(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15,
+                                   Object a16, Object a17, Object a18) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18); }
+        protected Object invoke_F4(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15,
+                                   Object a16, Object a17, Object a18) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18); }
+        protected Object invoke_F5(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15,
+                                   Object a16, Object a17, Object a18) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3, a4),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18); }
+        protected Object invoke_F6(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15,
+                                   Object a16, Object a17, Object a18) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18); }
+        protected Object invoke_F7(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15,
+                                   Object a16, Object a17, Object a18) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18); }
+        protected Object invoke_F8(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15,
+                                   Object a16, Object a17, Object a18) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18); }
+        protected Object invoke_F9(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15,
+                                   Object a16, Object a17, Object a18) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18); }
+        protected Object invoke_F10(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12, Object a13, Object a14, Object a15,
+                                    Object a16, Object a17, Object a18) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18); }
+        protected Object invoke_F11(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12, Object a13, Object a14, Object a15,
+                                    Object a16, Object a17, Object a18) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18); }
+        protected Object invoke_F12(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12, Object a13, Object a14, Object a15,
+                                    Object a16, Object a17, Object a18) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18); }
+        protected Object invoke_F13(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12, Object a13, Object a14, Object a15,
+                                    Object a16, Object a17, Object a18) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18); }
+        protected Object invoke_F14(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12, Object a13, Object a14, Object a15,
+                                    Object a16, Object a17, Object a18) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18); }
+        protected Object invoke_F15(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12, Object a13, Object a14, Object a15,
+                                    Object a16, Object a17, Object a18) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, a14),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18); }
+        protected Object invoke_F16(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12, Object a13, Object a14, Object a15,
+                                    Object a16, Object a17, Object a18) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, a14, a15),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18); }
+        protected Object invoke_F17(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12, Object a13, Object a14, Object a15,
+                                    Object a16, Object a17, Object a18) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, a14, a15, a16),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18); }
+        protected Object invoke_F18(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12, Object a13, Object a14, Object a15,
+                                    Object a16, Object a17, Object a18) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, a14, a15, a16, a17),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18); }
+        protected Object invoke_F19(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15,
+                                   Object a16, Object a17, Object a18) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18); }
+        protected Object invoke_C0(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15,
+                                   Object a16, Object a17, Object a18) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, a14, a15, a16, a17, a18)); }
+        protected Object invoke_C1(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15,
+                                   Object a16, Object a17, Object a18) throws Throwable {
+            return target.invoke(a0, filter.invoke(a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, a14, a15, a16, a17, a18)); }
+        protected Object invoke_C2(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15,
+                                   Object a16, Object a17, Object a18) throws Throwable {
+            return target.invoke(a0, a1, filter.invoke(a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, a14, a15, a16, a17, a18)); }
+        protected Object invoke_C3(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15,
+                                   Object a16, Object a17, Object a18) throws Throwable {
+            return target.invoke(a0, a1, a2, filter.invoke(a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, a14, a15, a16, a17, a18)); }
+        protected Object invoke_C4(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15,
+                                   Object a16, Object a17, Object a18) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, filter.invoke(a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, a14, a15, a16, a17, a18)); }
+        protected Object invoke_C5(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15,
+                                   Object a16, Object a17, Object a18) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, filter.invoke(a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, a14, a15, a16, a17, a18)); }
+        protected Object invoke_C6(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15,
+                                   Object a16, Object a17, Object a18) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, filter.invoke(a6, a7, a8, a9,
+                                 a10, a11, a12, a13, a14, a15, a16, a17, a18)); }
+        protected Object invoke_C7(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15,
+                                   Object a16, Object a17, Object a18) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, filter.invoke(a7, a8, a9,
+                                 a10, a11, a12, a13, a14, a15, a16, a17, a18)); }
+        protected Object invoke_C8(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15,
+                                   Object a16, Object a17, Object a18) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, filter.invoke(a8, a9,
+                                 a10, a11, a12, a13, a14, a15, a16, a17, a18)); }
+        protected Object invoke_C9(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15,
+                                   Object a16, Object a17, Object a18) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, filter.invoke(a9,
+                                 a10, a11, a12, a13, a14, a15, a16, a17, a18)); }
+        protected Object invoke_C10(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12, Object a13, Object a14, Object a15,
+                                    Object a16, Object a17, Object a18) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, filter.invoke(a10, a11, a12, a13, a14, a15, a16, a17, a18)); }
+        protected Object invoke_C11(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12, Object a13, Object a14, Object a15,
+                                    Object a16, Object a17, Object a18) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, filter.invoke(a11, a12, a13, a14, a15, a16, a17, a18)); }
+        protected Object invoke_C12(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12, Object a13, Object a14, Object a15,
+                                    Object a16, Object a17, Object a18) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, filter.invoke(a12, a13, a14, a15, a16, a17, a18)); }
+        protected Object invoke_C13(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12, Object a13, Object a14, Object a15,
+                                    Object a16, Object a17, Object a18) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, filter.invoke(a13, a14, a15, a16, a17, a18)); }
+        protected Object invoke_C14(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12, Object a13, Object a14, Object a15,
+                                    Object a16, Object a17, Object a18) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, filter.invoke(a14, a15, a16, a17, a18)); }
+        protected Object invoke_C15(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12, Object a13, Object a14, Object a15,
+                                    Object a16, Object a17, Object a18) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, a14, filter.invoke(a15, a16, a17, a18)); }
+        protected Object invoke_C16(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12, Object a13, Object a14, Object a15,
+                                    Object a16, Object a17, Object a18) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, a14, a15, filter.invoke(a16, a17, a18)); }
+        protected Object invoke_C17(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12, Object a13, Object a14, Object a15,
+                                    Object a16, Object a17, Object a18) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, a14, a15, a16, filter.invoke(a17, a18)); }
+        protected Object invoke_C18(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12, Object a13, Object a14, Object a15,
+                                    Object a16, Object a17, Object a18) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, a14, a15, a16, a17, filter.invoke(a18)); }
+        protected Object invoke_C19(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15,
+                                   Object a16, Object a17, Object a18) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, filter.invoke()); }
+        protected Object invoke_Y0(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15,
+                                   Object a16, Object a17, Object a18) throws Throwable {
+            Object[] av = { a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18 };
+            filter.<void>invoke(av); // make the flyby
+            return target.invoke(av[0], av[1], av[2], av[3], av[4], av[5], av[6], av[7], av[8], av[9], av[10], av[11], av[12], av[13], av[14], av[15], av[16], av[17], av[18]); }
+    }
+    static class F20 extends Adapter {
+        protected F20(MethodHandle entryPoint) { super(entryPoint); }  // to build prototype
+        protected F20(MethodHandle e, MethodHandle f, MethodHandle t) {
+            super(e, f, t); }
+        protected F20 makeInstance(MethodHandle e, MethodHandle f, MethodHandle t) {
+            return new F20(e, f, t); }
+        protected Object invoke_V0(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15,
+                                   Object a16, Object a17, Object a18, Object a19) throws Throwable {
+            return target.invoke(filter.invoke(a0), a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, a14, a15, a16, a17, a18, a19); }
+        protected Object invoke_V1(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15,
+                                   Object a16, Object a17, Object a18, Object a19) throws Throwable {
+            return target.invoke(a0, filter.invoke(a1), a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, a14, a15, a16, a17, a18, a19); }
+        protected Object invoke_V2(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15,
+                                   Object a16, Object a17, Object a18, Object a19) throws Throwable {
+            return target.invoke(a0, a1, filter.invoke(a2), a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, a14, a15, a16, a17, a18, a19); }
+        protected Object invoke_V3(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15,
+                                   Object a16, Object a17, Object a18, Object a19) throws Throwable {
+            return target.invoke(a0, a1, a2, filter.invoke(a3), a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, a14, a15, a16, a17, a18, a19); }
+        protected Object invoke_V4(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15,
+                                   Object a16, Object a17, Object a18, Object a19) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, filter.invoke(a4), a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, a14, a15, a16, a17, a18, a19); }
+        protected Object invoke_V5(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15,
+                                   Object a16, Object a17, Object a18, Object a19) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, filter.invoke(a5), a6, a7, a8, a9,
+                                 a10, a11, a12, a13, a14, a15, a16, a17, a18, a19); }
+        protected Object invoke_V6(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15,
+                                   Object a16, Object a17, Object a18, Object a19) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, filter.invoke(a6), a7, a8, a9,
+                                 a10, a11, a12, a13, a14, a15, a16, a17, a18, a19); }
+        protected Object invoke_V7(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15,
+                                   Object a16, Object a17, Object a18, Object a19) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, filter.invoke(a7), a8, a9,
+                                 a10, a11, a12, a13, a14, a15, a16, a17, a18, a19); }
+        protected Object invoke_V8(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15,
+                                   Object a16, Object a17, Object a18, Object a19) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, filter.invoke(a8), a9,
+                                 a10, a11, a12, a13, a14, a15, a16, a17, a18, a19); }
+        protected Object invoke_V9(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15,
+                                   Object a16, Object a17, Object a18, Object a19) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, filter.invoke(a9),
+                                 a10, a11, a12, a13, a14, a15, a16, a17, a18, a19); }
+        protected Object invoke_V10(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12, Object a13, Object a14, Object a15,
+                                    Object a16, Object a17, Object a18, Object a19) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 filter.invoke(a10), a11, a12, a13, a14, a15, a16, a17, a18, a19); }
+        protected Object invoke_V11(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12, Object a13, Object a14, Object a15,
+                                    Object a16, Object a17, Object a18, Object a19) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, filter.invoke(a11), a12, a13, a14, a15, a16, a17, a18, a19); }
+        protected Object invoke_V12(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12, Object a13, Object a14, Object a15,
+                                    Object a16, Object a17, Object a18, Object a19) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, filter.invoke(a12), a13, a14, a15, a16, a17, a18, a19); }
+        protected Object invoke_V13(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12, Object a13, Object a14, Object a15,
+                                    Object a16, Object a17, Object a18, Object a19) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, filter.invoke(a13), a14, a15, a16, a17, a18, a19); }
+        protected Object invoke_V14(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12, Object a13, Object a14, Object a15,
+                                    Object a16, Object a17, Object a18, Object a19) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, filter.invoke(a14), a15, a16, a17, a18, a19); }
+        protected Object invoke_V15(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12, Object a13, Object a14, Object a15,
+                                    Object a16, Object a17, Object a18, Object a19) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, a14, filter.invoke(a15), a16, a17, a18, a19); }
+        protected Object invoke_V16(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12, Object a13, Object a14, Object a15,
+                                    Object a16, Object a17, Object a18, Object a19) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, a14, a15, filter.invoke(a16), a17, a18, a19); }
+        protected Object invoke_V17(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12, Object a13, Object a14, Object a15,
+                                    Object a16, Object a17, Object a18, Object a19) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, a14, a15, a16, filter.invoke(a17), a18, a19); }
+        protected Object invoke_V18(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12, Object a13, Object a14, Object a15,
+                                    Object a16, Object a17, Object a18, Object a19) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, a14, a15, a16, a17, filter.invoke(a18), a19); }
+        protected Object invoke_V19(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12, Object a13, Object a14, Object a15,
+                                    Object a16, Object a17, Object a18, Object a19) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, a14, a15, a16, a17, a18, filter.invoke(a19)); }
+        protected Object invoke_F0(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15,
+                                   Object a16, Object a17, Object a18, Object a19) throws Throwable {
+            return target.invoke(filter.invoke(),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19); }
+        protected Object invoke_F1(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15,
+                                   Object a16, Object a17, Object a18, Object a19) throws Throwable {
+            return target.invoke(filter.invoke(a0),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19); }
+        protected Object invoke_F2(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15,
+                                   Object a16, Object a17, Object a18, Object a19) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19); }
+        protected Object invoke_F3(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15,
+                                   Object a16, Object a17, Object a18, Object a19) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19); }
+        protected Object invoke_F4(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15,
+                                   Object a16, Object a17, Object a18, Object a19) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19); }
+        protected Object invoke_F5(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15,
+                                   Object a16, Object a17, Object a18, Object a19) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3, a4),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19); }
+        protected Object invoke_F6(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15,
+                                   Object a16, Object a17, Object a18, Object a19) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19); }
+        protected Object invoke_F7(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15,
+                                   Object a16, Object a17, Object a18, Object a19) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19); }
+        protected Object invoke_F8(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15,
+                                   Object a16, Object a17, Object a18, Object a19) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19); }
+        protected Object invoke_F9(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15,
+                                   Object a16, Object a17, Object a18, Object a19) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19); }
+        protected Object invoke_F10(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12, Object a13, Object a14, Object a15,
+                                    Object a16, Object a17, Object a18, Object a19) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19); }
+        protected Object invoke_F11(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12, Object a13, Object a14, Object a15,
+                                    Object a16, Object a17, Object a18, Object a19) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19); }
+        protected Object invoke_F12(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12, Object a13, Object a14, Object a15,
+                                    Object a16, Object a17, Object a18, Object a19) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19); }
+        protected Object invoke_F13(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12, Object a13, Object a14, Object a15,
+                                    Object a16, Object a17, Object a18, Object a19) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19); }
+        protected Object invoke_F14(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12, Object a13, Object a14, Object a15,
+                                    Object a16, Object a17, Object a18, Object a19) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19); }
+        protected Object invoke_F15(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12, Object a13, Object a14, Object a15,
+                                    Object a16, Object a17, Object a18, Object a19) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, a14),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19); }
+        protected Object invoke_F16(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12, Object a13, Object a14, Object a15,
+                                    Object a16, Object a17, Object a18, Object a19) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, a14, a15),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19); }
+        protected Object invoke_F17(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12, Object a13, Object a14, Object a15,
+                                    Object a16, Object a17, Object a18, Object a19) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, a14, a15, a16),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19); }
+        protected Object invoke_F18(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12, Object a13, Object a14, Object a15,
+                                    Object a16, Object a17, Object a18, Object a19) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, a14, a15, a16, a17),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19); }
+        protected Object invoke_F19(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12, Object a13, Object a14, Object a15,
+                                    Object a16, Object a17, Object a18, Object a19) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, a14, a15, a16, a17, a18),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19); }
+        protected Object invoke_F20(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15,
+                                   Object a16, Object a17, Object a18, Object a19) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19),
+                                 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19); }
+        protected Object invoke_C0(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15,
+                                   Object a16, Object a17, Object a18, Object a19) throws Throwable {
+            return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, a14, a15, a16, a17, a18, a19)); }
+        protected Object invoke_C1(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15,
+                                   Object a16, Object a17, Object a18, Object a19) throws Throwable {
+            return target.invoke(a0, filter.invoke(a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, a14, a15, a16, a17, a18, a19)); }
+        protected Object invoke_C2(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15,
+                                   Object a16, Object a17, Object a18, Object a19) throws Throwable {
+            return target.invoke(a0, a1, filter.invoke(a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, a14, a15, a16, a17, a18, a19)); }
+        protected Object invoke_C3(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15,
+                                   Object a16, Object a17, Object a18, Object a19) throws Throwable {
+            return target.invoke(a0, a1, a2, filter.invoke(a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, a14, a15, a16, a17, a18, a19)); }
+        protected Object invoke_C4(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15,
+                                   Object a16, Object a17, Object a18, Object a19) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, filter.invoke(a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, a14, a15, a16, a17, a18, a19)); }
+        protected Object invoke_C5(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15,
+                                   Object a16, Object a17, Object a18, Object a19) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, filter.invoke(a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, a14, a15, a16, a17, a18, a19)); }
+        protected Object invoke_C6(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15,
+                                   Object a16, Object a17, Object a18, Object a19) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, filter.invoke(a6, a7, a8, a9,
+                                 a10, a11, a12, a13, a14, a15, a16, a17, a18, a19)); }
+        protected Object invoke_C7(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15,
+                                   Object a16, Object a17, Object a18, Object a19) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, filter.invoke(a7, a8, a9,
+                                 a10, a11, a12, a13, a14, a15, a16, a17, a18, a19)); }
+        protected Object invoke_C8(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15,
+                                   Object a16, Object a17, Object a18, Object a19) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, filter.invoke(a8, a9,
+                                 a10, a11, a12, a13, a14, a15, a16, a17, a18, a19)); }
+        protected Object invoke_C9(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15,
+                                   Object a16, Object a17, Object a18, Object a19) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, filter.invoke(a9,
+                                 a10, a11, a12, a13, a14, a15, a16, a17, a18, a19)); }
+        protected Object invoke_C10(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12, Object a13, Object a14, Object a15,
+                                    Object a16, Object a17, Object a18, Object a19) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, filter.invoke(a10, a11, a12, a13, a14, a15, a16, a17, a18, a19)); }
+        protected Object invoke_C11(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12, Object a13, Object a14, Object a15,
+                                    Object a16, Object a17, Object a18, Object a19) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, filter.invoke(a11, a12, a13, a14, a15, a16, a17, a18, a19)); }
+        protected Object invoke_C12(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12, Object a13, Object a14, Object a15,
+                                    Object a16, Object a17, Object a18, Object a19) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, filter.invoke(a12, a13, a14, a15, a16, a17, a18, a19)); }
+        protected Object invoke_C13(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12, Object a13, Object a14, Object a15,
+                                    Object a16, Object a17, Object a18, Object a19) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, filter.invoke(a13, a14, a15, a16, a17, a18, a19)); }
+        protected Object invoke_C14(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12, Object a13, Object a14, Object a15,
+                                    Object a16, Object a17, Object a18, Object a19) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, filter.invoke(a14, a15, a16, a17, a18, a19)); }
+        protected Object invoke_C15(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12, Object a13, Object a14, Object a15,
+                                    Object a16, Object a17, Object a18, Object a19) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, a14, filter.invoke(a15, a16, a17, a18, a19)); }
+        protected Object invoke_C16(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12, Object a13, Object a14, Object a15,
+                                    Object a16, Object a17, Object a18, Object a19) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, a14, a15, filter.invoke(a16, a17, a18, a19)); }
+        protected Object invoke_C17(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12, Object a13, Object a14, Object a15,
+                                    Object a16, Object a17, Object a18, Object a19) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, a14, a15, a16, filter.invoke(a17, a18, a19)); }
+        protected Object invoke_C18(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12, Object a13, Object a14, Object a15,
+                                    Object a16, Object a17, Object a18, Object a19) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, a14, a15, a16, a17, filter.invoke(a18, a19)); }
+        protected Object invoke_C19(Object a0, Object a1, Object a2, Object a3,
+                                    Object a4, Object a5, Object a6, Object a7,
+                                    Object a8, Object a9, Object a10, Object a11,
+                                    Object a12, Object a13, Object a14, Object a15,
+                                    Object a16, Object a17, Object a18, Object a19) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, a14, a15, a16, a17, a18, filter.invoke(a19)); }
+        protected Object invoke_C20(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15,
+                                   Object a16, Object a17, Object a18, Object a19) throws Throwable {
+            return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, filter.invoke()); }
+        protected Object invoke_Y0(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6, Object a7,
+                                   Object a8, Object a9, Object a10, Object a11,
+                                   Object a12, Object a13, Object a14, Object a15,
+                                   Object a16, Object a17, Object a18, Object a19) throws Throwable {
+            Object[] av = { a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19 };
+            filter.<void>invoke(av); // make the flyby
+            return target.invoke(av[0], av[1], av[2], av[3], av[4], av[5], av[6], av[7], av[8], av[9], av[10], av[11], av[12], av[13], av[14], av[15], av[16], av[17], av[18], av[19]); }
+    }
+}
--- a/jdk/src/share/classes/sun/dyn/FilterOneArgument.java	Thu Dec 17 14:10:20 2009 -0800
+++ b/jdk/src/share/classes/sun/dyn/FilterOneArgument.java	Wed Jul 05 17:04:56 2017 +0200
@@ -27,7 +27,6 @@
 
 import java.dyn.JavaMethodHandle;
 import java.dyn.MethodHandle;
-import java.dyn.MethodHandles;
 import java.dyn.MethodType;
 
 /**
@@ -42,16 +41,21 @@
     protected final MethodHandle filter;  // Object -> Object
     protected final MethodHandle target;  // Object -> Object
 
-    protected Object entryPoint(Object argument) {
-        Object filteredArgument = filter.<Object>invoke(argument);
-        return target.<Object>invoke(filteredArgument);
+    @Override
+    public String toString() {
+        return target.toString();
     }
 
-    private static final MethodHandle entryPoint =
-        MethodHandleImpl.IMPL_LOOKUP.findVirtual(FilterOneArgument.class, "entryPoint", MethodType.makeGeneric(1));
+    protected Object invoke(Object argument) throws Throwable {
+        Object filteredArgument = filter.invoke(argument);
+        return target.invoke(filteredArgument);
+    }
+
+    private static final MethodHandle INVOKE =
+        MethodHandleImpl.IMPL_LOOKUP.findVirtual(FilterOneArgument.class, "invoke", MethodType.genericMethodType(1));
 
     protected FilterOneArgument(MethodHandle filter, MethodHandle target) {
-        super(entryPoint);
+        super(INVOKE);
         this.filter = filter;
         this.target = target;
     }
@@ -62,10 +66,6 @@
         return new FilterOneArgument(filter, target);
     }
 
-    public String toString() {
-        return filter + "|>" + target;
-    }
-
 //    MethodHandle make(MethodHandle filter1, MethodHandle filter2, MethodHandle target) {
 //        MethodHandle filter = make(filter1, filter2);
 //        return make(filter, target);
--- a/jdk/src/share/classes/sun/dyn/FromGeneric.java	Thu Dec 17 14:10:20 2009 -0800
+++ b/jdk/src/share/classes/sun/dyn/FromGeneric.java	Wed Jul 05 17:04:56 2017 +0200
@@ -36,8 +36,8 @@
 import sun.dyn.util.Wrapper;
 
 /**
- * Adapters which mediate between incoming calls which are not generic
- * and outgoing calls which are.  Any call can be represented generically
+ * Adapters which mediate between incoming calls which are generic
+ * and outgoing calls which are not.  Any call can be represented generically
  * boxing up its arguments, and (on return) unboxing the return value.
  * <p>
  * A call is "generic" (in MethodHandle terms) if its MethodType features
@@ -50,9 +50,6 @@
  * either binds internally or else takes as a leading argument).
  * (To stretch the term, adapter-like method handles may have multiple
  * targets or be polymorphic across multiple call types.)
- * <p>
- * This adapter can sometimes be more directly implemented
- * by the JVM's built-in OP_SPREAD_ARGS adapter.
  * @author jrose
  */
 class FromGeneric {
@@ -99,7 +96,7 @@
         }
         this.internalType = internalType0;
         this.adapter = ad;
-        MethodType tepType = targetType.insertParameterType(0, adapter.getClass());
+        MethodType tepType = targetType.insertParameterTypes(0, adapter.getClass());
         this.entryPoint = ad.prototypeEntryPoint();
         this.returnConversion = computeReturnConversion(targetType, internalType0);
         this.unboxingInvoker = computeUnboxingInvoker(targetType, internalType0);
@@ -146,7 +143,7 @@
         if (fixArgs == null)
             throw new InternalError("bad fixArgs");
         // reinterpret the calling sequence as raw:
-        MethodHandle retyper = AdapterMethodHandle.makeRawRetypeOnly(Access.TOKEN,
+        MethodHandle retyper = AdapterMethodHandle.makeRetypeRaw(Access.TOKEN,
                                         Invokers.invokerType(internalType), fixArgs);
         if (retyper == null)
             throw new InternalError("bad retyper");
@@ -226,7 +223,10 @@
                 // Produce an instance configured as a prototype.
                 return ctor.newInstance(entryPoint);
             } catch (IllegalArgumentException ex) {
-            } catch (InvocationTargetException ex) {
+            } catch (InvocationTargetException wex) {
+                Throwable ex = wex.getTargetException();
+                if (ex instanceof Error)  throw (Error)ex;
+                if (ex instanceof RuntimeException)  throw (RuntimeException)ex;
             } catch (InstantiationException ex) {
             } catch (IllegalAccessException ex) {
             }
@@ -260,6 +260,11 @@
         protected final MethodHandle convert;  // raw(R) => Object
         protected final MethodHandle target;   // (any**N) => R
 
+        @Override
+        public String toString() {
+            return target.toString();
+        }
+
         protected boolean isPrototype() { return target == null; }
         protected Adapter(MethodHandle entryPoint) {
             this(entryPoint, null, entryPoint, null);
@@ -284,11 +289,11 @@
         // { return new ThisType(entryPoint, convert, target); }
 
         /// Conversions on the value returned from the target.
-        protected Object convert_L(Object result) { return convert.<Object>invoke(result); }
-        protected Object convert_I(int    result) { return convert.<Object>invoke(result); }
-        protected Object convert_J(long   result) { return convert.<Object>invoke(result); }
-        protected Object convert_F(float  result) { return convert.<Object>invoke(result); }
-        protected Object convert_D(double result) { return convert.<Object>invoke(result); }
+        protected Object convert_L(Object result) throws Throwable { return convert.<Object>invoke(result); }
+        protected Object convert_I(int    result) throws Throwable { return convert.<Object>invoke(result); }
+        protected Object convert_J(long   result) throws Throwable { return convert.<Object>invoke(result); }
+        protected Object convert_F(float  result) throws Throwable { return convert.<Object>invoke(result); }
+        protected Object convert_D(double result) throws Throwable { return convert.<Object>invoke(result); }
 
         static private final String CLASS_PREFIX; // "sun.dyn.FromGeneric$"
         static {
@@ -317,11 +322,11 @@
                         { super(e, i, c, t); }
         protected xA2 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
                         { return new xA2(e, i, c, t); }
-        protected Object invoke_L2(Object a0, Object a1) { return convert_L(invoker.<Object>invoke(target, a0, a1)); }
-        protected Object invoke_I2(Object a0, Object a1) { return convert_I(invoker.<int   >invoke(target, a0, a1)); }
-        protected Object invoke_J2(Object a0, Object a1) { return convert_J(invoker.<long  >invoke(target, a0, a1)); }
-        protected Object invoke_F2(Object a0, Object a1) { return convert_F(invoker.<float >invoke(target, a0, a1)); }
-        protected Object invoke_D2(Object a0, Object a1) { return convert_D(invoker.<double>invoke(target, a0, a1)); }
+        protected Object invoke_L2(Object a0, Object a1) throws Throwable { return convert_L(invoker.<Object>invoke(target, a0, a1)); }
+        protected Object invoke_I2(Object a0, Object a1) throws Throwable { return convert_I(invoker.<int   >invoke(target, a0, a1)); }
+        protected Object invoke_J2(Object a0, Object a1) throws Throwable { return convert_J(invoker.<long  >invoke(target, a0, a1)); }
+        protected Object invoke_F2(Object a0, Object a1) throws Throwable { return convert_F(invoker.<float >invoke(target, a0, a1)); }
+        protected Object invoke_D2(Object a0, Object a1) throws Throwable { return convert_D(invoker.<double>invoke(target, a0, a1)); }
     }
     // */
 
@@ -342,7 +347,7 @@
         "        protected @cat@ makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)",
         "                        { return new @cat@(e, i, c, t); }",
         "        //@each-R@",
-        "        protected Object invoke_@catN@(@Tvav@) { return convert_@Rc@(invoker.<@R@>invoke(target@av@)); }",
+        "        protected Object invoke_@catN@(@Tvav@) throws Throwable { return convert_@Rc@(invoker.<@R@>invoke(target@av@)); }",
         "        //@end-R@",
         "    }",
     } };
@@ -498,11 +503,11 @@
                         { super(e, i, c, t); }
         protected A0 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
                         { return new A0(e, i, c, t); }
-        protected Object invoke_L0() { return convert_L(invoker.<Object>invoke(target)); }
-        protected Object invoke_I0() { return convert_I(invoker.<int   >invoke(target)); }
-        protected Object invoke_J0() { return convert_J(invoker.<long  >invoke(target)); }
-        protected Object invoke_F0() { return convert_F(invoker.<float >invoke(target)); }
-        protected Object invoke_D0() { return convert_D(invoker.<double>invoke(target)); }
+        protected Object invoke_L0() throws Throwable { return convert_L(invoker.<Object>invoke(target)); }
+        protected Object invoke_I0() throws Throwable { return convert_I(invoker.<int   >invoke(target)); }
+        protected Object invoke_J0() throws Throwable { return convert_J(invoker.<long  >invoke(target)); }
+        protected Object invoke_F0() throws Throwable { return convert_F(invoker.<float >invoke(target)); }
+        protected Object invoke_D0() throws Throwable { return convert_D(invoker.<double>invoke(target)); }
     }
     static class A1 extends Adapter {
         protected A1(MethodHandle entryPoint) { super(entryPoint); }  // to build prototype
@@ -510,11 +515,11 @@
                         { super(e, i, c, t); }
         protected A1 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
                         { return new A1(e, i, c, t); }
-        protected Object invoke_L1(Object a0) { return convert_L(invoker.<Object>invoke(target, a0)); }
-        protected Object invoke_I1(Object a0) { return convert_I(invoker.<int   >invoke(target, a0)); }
-        protected Object invoke_J1(Object a0) { return convert_J(invoker.<long  >invoke(target, a0)); }
-        protected Object invoke_F1(Object a0) { return convert_F(invoker.<float >invoke(target, a0)); }
-        protected Object invoke_D1(Object a0) { return convert_D(invoker.<double>invoke(target, a0)); }
+        protected Object invoke_L1(Object a0) throws Throwable { return convert_L(invoker.<Object>invoke(target, a0)); }
+        protected Object invoke_I1(Object a0) throws Throwable { return convert_I(invoker.<int   >invoke(target, a0)); }
+        protected Object invoke_J1(Object a0) throws Throwable { return convert_J(invoker.<long  >invoke(target, a0)); }
+        protected Object invoke_F1(Object a0) throws Throwable { return convert_F(invoker.<float >invoke(target, a0)); }
+        protected Object invoke_D1(Object a0) throws Throwable { return convert_D(invoker.<double>invoke(target, a0)); }
     }
     static class A2 extends Adapter {
         protected A2(MethodHandle entryPoint) { super(entryPoint); }  // to build prototype
@@ -522,11 +527,11 @@
                         { super(e, i, c, t); }
         protected A2 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
                         { return new A2(e, i, c, t); }
-        protected Object invoke_L2(Object a0, Object a1) { return convert_L(invoker.<Object>invoke(target, a0, a1)); }
-        protected Object invoke_I2(Object a0, Object a1) { return convert_I(invoker.<int   >invoke(target, a0, a1)); }
-        protected Object invoke_J2(Object a0, Object a1) { return convert_J(invoker.<long  >invoke(target, a0, a1)); }
-        protected Object invoke_F2(Object a0, Object a1) { return convert_F(invoker.<float >invoke(target, a0, a1)); }
-        protected Object invoke_D2(Object a0, Object a1) { return convert_D(invoker.<double>invoke(target, a0, a1)); }
+        protected Object invoke_L2(Object a0, Object a1) throws Throwable { return convert_L(invoker.<Object>invoke(target, a0, a1)); }
+        protected Object invoke_I2(Object a0, Object a1) throws Throwable { return convert_I(invoker.<int   >invoke(target, a0, a1)); }
+        protected Object invoke_J2(Object a0, Object a1) throws Throwable { return convert_J(invoker.<long  >invoke(target, a0, a1)); }
+        protected Object invoke_F2(Object a0, Object a1) throws Throwable { return convert_F(invoker.<float >invoke(target, a0, a1)); }
+        protected Object invoke_D2(Object a0, Object a1) throws Throwable { return convert_D(invoker.<double>invoke(target, a0, a1)); }
     }
     static class A3 extends Adapter {
         protected A3(MethodHandle entryPoint) { super(entryPoint); }  // to build prototype
@@ -534,11 +539,11 @@
                         { super(e, i, c, t); }
         protected A3 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
                         { return new A3(e, i, c, t); }
-        protected Object invoke_L3(Object a0, Object a1, Object a2) { return convert_L(invoker.<Object>invoke(target, a0, a1, a2)); }
-        protected Object invoke_I3(Object a0, Object a1, Object a2) { return convert_I(invoker.<int   >invoke(target, a0, a1, a2)); }
-        protected Object invoke_J3(Object a0, Object a1, Object a2) { return convert_J(invoker.<long  >invoke(target, a0, a1, a2)); }
-        protected Object invoke_F3(Object a0, Object a1, Object a2) { return convert_F(invoker.<float >invoke(target, a0, a1, a2)); }
-        protected Object invoke_D3(Object a0, Object a1, Object a2) { return convert_D(invoker.<double>invoke(target, a0, a1, a2)); }
+        protected Object invoke_L3(Object a0, Object a1, Object a2) throws Throwable { return convert_L(invoker.<Object>invoke(target, a0, a1, a2)); }
+        protected Object invoke_I3(Object a0, Object a1, Object a2) throws Throwable { return convert_I(invoker.<int   >invoke(target, a0, a1, a2)); }
+        protected Object invoke_J3(Object a0, Object a1, Object a2) throws Throwable { return convert_J(invoker.<long  >invoke(target, a0, a1, a2)); }
+        protected Object invoke_F3(Object a0, Object a1, Object a2) throws Throwable { return convert_F(invoker.<float >invoke(target, a0, a1, a2)); }
+        protected Object invoke_D3(Object a0, Object a1, Object a2) throws Throwable { return convert_D(invoker.<double>invoke(target, a0, a1, a2)); }
     }
     static class A4 extends Adapter {
         protected A4(MethodHandle entryPoint) { super(entryPoint); }  // to build prototype
@@ -546,11 +551,11 @@
                         { super(e, i, c, t); }
         protected A4 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
                         { return new A4(e, i, c, t); }
-        protected Object invoke_L4(Object a0, Object a1, Object a2, Object a3) { return convert_L(invoker.<Object>invoke(target, a0, a1, a2, a3)); }
-        protected Object invoke_I4(Object a0, Object a1, Object a2, Object a3) { return convert_I(invoker.<int   >invoke(target, a0, a1, a2, a3)); }
-        protected Object invoke_J4(Object a0, Object a1, Object a2, Object a3) { return convert_J(invoker.<long  >invoke(target, a0, a1, a2, a3)); }
-        protected Object invoke_F4(Object a0, Object a1, Object a2, Object a3) { return convert_F(invoker.<float >invoke(target, a0, a1, a2, a3)); }
-        protected Object invoke_D4(Object a0, Object a1, Object a2, Object a3) { return convert_D(invoker.<double>invoke(target, a0, a1, a2, a3)); }
+        protected Object invoke_L4(Object a0, Object a1, Object a2, Object a3) throws Throwable { return convert_L(invoker.<Object>invoke(target, a0, a1, a2, a3)); }
+        protected Object invoke_I4(Object a0, Object a1, Object a2, Object a3) throws Throwable { return convert_I(invoker.<int   >invoke(target, a0, a1, a2, a3)); }
+        protected Object invoke_J4(Object a0, Object a1, Object a2, Object a3) throws Throwable { return convert_J(invoker.<long  >invoke(target, a0, a1, a2, a3)); }
+        protected Object invoke_F4(Object a0, Object a1, Object a2, Object a3) throws Throwable { return convert_F(invoker.<float >invoke(target, a0, a1, a2, a3)); }
+        protected Object invoke_D4(Object a0, Object a1, Object a2, Object a3) throws Throwable { return convert_D(invoker.<double>invoke(target, a0, a1, a2, a3)); }
     }
     static class A5 extends Adapter {
         protected A5(MethodHandle entryPoint) { super(entryPoint); }  // to build prototype
@@ -558,11 +563,11 @@
                         { super(e, i, c, t); }
         protected A5 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
                         { return new A5(e, i, c, t); }
-        protected Object invoke_L5(Object a0, Object a1, Object a2, Object a3, Object a4) { return convert_L(invoker.<Object>invoke(target, a0, a1, a2, a3, a4)); }
-        protected Object invoke_I5(Object a0, Object a1, Object a2, Object a3, Object a4) { return convert_I(invoker.<int   >invoke(target, a0, a1, a2, a3, a4)); }
-        protected Object invoke_J5(Object a0, Object a1, Object a2, Object a3, Object a4) { return convert_J(invoker.<long  >invoke(target, a0, a1, a2, a3, a4)); }
-        protected Object invoke_F5(Object a0, Object a1, Object a2, Object a3, Object a4) { return convert_F(invoker.<float >invoke(target, a0, a1, a2, a3, a4)); }
-        protected Object invoke_D5(Object a0, Object a1, Object a2, Object a3, Object a4) { return convert_D(invoker.<double>invoke(target, a0, a1, a2, a3, a4)); }
+        protected Object invoke_L5(Object a0, Object a1, Object a2, Object a3, Object a4) throws Throwable { return convert_L(invoker.<Object>invoke(target, a0, a1, a2, a3, a4)); }
+        protected Object invoke_I5(Object a0, Object a1, Object a2, Object a3, Object a4) throws Throwable { return convert_I(invoker.<int   >invoke(target, a0, a1, a2, a3, a4)); }
+        protected Object invoke_J5(Object a0, Object a1, Object a2, Object a3, Object a4) throws Throwable { return convert_J(invoker.<long  >invoke(target, a0, a1, a2, a3, a4)); }
+        protected Object invoke_F5(Object a0, Object a1, Object a2, Object a3, Object a4) throws Throwable { return convert_F(invoker.<float >invoke(target, a0, a1, a2, a3, a4)); }
+        protected Object invoke_D5(Object a0, Object a1, Object a2, Object a3, Object a4) throws Throwable { return convert_D(invoker.<double>invoke(target, a0, a1, a2, a3, a4)); }
     }
     static class A6 extends Adapter {
         protected A6(MethodHandle entryPoint) { super(entryPoint); }  // to build prototype
@@ -570,11 +575,11 @@
                         { super(e, i, c, t); }
         protected A6 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
                         { return new A6(e, i, c, t); }
-        protected Object invoke_L6(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) { return convert_L(invoker.<Object>invoke(target, a0, a1, a2, a3, a4, a5)); }
-        protected Object invoke_I6(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) { return convert_I(invoker.<int   >invoke(target, a0, a1, a2, a3, a4, a5)); }
-        protected Object invoke_J6(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) { return convert_J(invoker.<long  >invoke(target, a0, a1, a2, a3, a4, a5)); }
-        protected Object invoke_F6(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) { return convert_F(invoker.<float >invoke(target, a0, a1, a2, a3, a4, a5)); }
-        protected Object invoke_D6(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) { return convert_D(invoker.<double>invoke(target, a0, a1, a2, a3, a4, a5)); }
+        protected Object invoke_L6(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) throws Throwable { return convert_L(invoker.<Object>invoke(target, a0, a1, a2, a3, a4, a5)); }
+        protected Object invoke_I6(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) throws Throwable { return convert_I(invoker.<int   >invoke(target, a0, a1, a2, a3, a4, a5)); }
+        protected Object invoke_J6(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) throws Throwable { return convert_J(invoker.<long  >invoke(target, a0, a1, a2, a3, a4, a5)); }
+        protected Object invoke_F6(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) throws Throwable { return convert_F(invoker.<float >invoke(target, a0, a1, a2, a3, a4, a5)); }
+        protected Object invoke_D6(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) throws Throwable { return convert_D(invoker.<double>invoke(target, a0, a1, a2, a3, a4, a5)); }
     }
     static class A7 extends Adapter {
         protected A7(MethodHandle entryPoint) { super(entryPoint); }  // to build prototype
@@ -582,11 +587,11 @@
                         { super(e, i, c, t); }
         protected A7 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
                         { return new A7(e, i, c, t); }
-        protected Object invoke_L7(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) { return convert_L(invoker.<Object>invoke(target, a0, a1, a2, a3, a4, a5, a6)); }
-        protected Object invoke_I7(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) { return convert_I(invoker.<int   >invoke(target, a0, a1, a2, a3, a4, a5, a6)); }
-        protected Object invoke_J7(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) { return convert_J(invoker.<long  >invoke(target, a0, a1, a2, a3, a4, a5, a6)); }
-        protected Object invoke_F7(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) { return convert_F(invoker.<float >invoke(target, a0, a1, a2, a3, a4, a5, a6)); }
-        protected Object invoke_D7(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) { return convert_D(invoker.<double>invoke(target, a0, a1, a2, a3, a4, a5, a6)); }
+        protected Object invoke_L7(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) throws Throwable { return convert_L(invoker.<Object>invoke(target, a0, a1, a2, a3, a4, a5, a6)); }
+        protected Object invoke_I7(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) throws Throwable { return convert_I(invoker.<int   >invoke(target, a0, a1, a2, a3, a4, a5, a6)); }
+        protected Object invoke_J7(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) throws Throwable { return convert_J(invoker.<long  >invoke(target, a0, a1, a2, a3, a4, a5, a6)); }
+        protected Object invoke_F7(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) throws Throwable { return convert_F(invoker.<float >invoke(target, a0, a1, a2, a3, a4, a5, a6)); }
+        protected Object invoke_D7(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) throws Throwable { return convert_D(invoker.<double>invoke(target, a0, a1, a2, a3, a4, a5, a6)); }
     }
     static class A8 extends Adapter {
         protected A8(MethodHandle entryPoint) { super(entryPoint); }  // to build prototype
@@ -594,11 +599,11 @@
                         { super(e, i, c, t); }
         protected A8 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
                         { return new A8(e, i, c, t); }
-        protected Object invoke_L8(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) { return convert_L(invoker.<Object>invoke(target, a0, a1, a2, a3, a4, a5, a6, a7)); }
-        protected Object invoke_I8(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) { return convert_I(invoker.<int   >invoke(target, a0, a1, a2, a3, a4, a5, a6, a7)); }
-        protected Object invoke_J8(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) { return convert_J(invoker.<long  >invoke(target, a0, a1, a2, a3, a4, a5, a6, a7)); }
-        protected Object invoke_F8(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) { return convert_F(invoker.<float >invoke(target, a0, a1, a2, a3, a4, a5, a6, a7)); }
-        protected Object invoke_D8(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) { return convert_D(invoker.<double>invoke(target, a0, a1, a2, a3, a4, a5, a6, a7)); }
+        protected Object invoke_L8(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) throws Throwable { return convert_L(invoker.<Object>invoke(target, a0, a1, a2, a3, a4, a5, a6, a7)); }
+        protected Object invoke_I8(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) throws Throwable { return convert_I(invoker.<int   >invoke(target, a0, a1, a2, a3, a4, a5, a6, a7)); }
+        protected Object invoke_J8(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) throws Throwable { return convert_J(invoker.<long  >invoke(target, a0, a1, a2, a3, a4, a5, a6, a7)); }
+        protected Object invoke_F8(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) throws Throwable { return convert_F(invoker.<float >invoke(target, a0, a1, a2, a3, a4, a5, a6, a7)); }
+        protected Object invoke_D8(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) throws Throwable { return convert_D(invoker.<double>invoke(target, a0, a1, a2, a3, a4, a5, a6, a7)); }
     }
     static class A9 extends Adapter {
         protected A9(MethodHandle entryPoint) { super(entryPoint); }  // to build prototype
@@ -606,11 +611,11 @@
                         { super(e, i, c, t); }
         protected A9 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
                         { return new A9(e, i, c, t); }
-        protected Object invoke_L9(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8) { return convert_L(invoker.<Object>invoke(target, a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
-        protected Object invoke_I9(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8) { return convert_I(invoker.<int   >invoke(target, a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
-        protected Object invoke_J9(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8) { return convert_J(invoker.<long  >invoke(target, a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
-        protected Object invoke_F9(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8) { return convert_F(invoker.<float >invoke(target, a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
-        protected Object invoke_D9(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8) { return convert_D(invoker.<double>invoke(target, a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
+        protected Object invoke_L9(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8) throws Throwable { return convert_L(invoker.<Object>invoke(target, a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
+        protected Object invoke_I9(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8) throws Throwable { return convert_I(invoker.<int   >invoke(target, a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
+        protected Object invoke_J9(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8) throws Throwable { return convert_J(invoker.<long  >invoke(target, a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
+        protected Object invoke_F9(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8) throws Throwable { return convert_F(invoker.<float >invoke(target, a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
+        protected Object invoke_D9(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8) throws Throwable { return convert_D(invoker.<double>invoke(target, a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
     }
     static class A10 extends Adapter {
         protected A10(MethodHandle entryPoint) { super(entryPoint); }  // to build prototype
@@ -618,10 +623,10 @@
                         { super(e, i, c, t); }
         protected A10 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
                         { return new A10(e, i, c, t); }
-        protected Object invoke_L10(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object a9) { return convert_L(invoker.<Object>invoke(target, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
-        protected Object invoke_I10(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object a9) { return convert_I(invoker.<int   >invoke(target, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
-        protected Object invoke_J10(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object a9) { return convert_J(invoker.<long  >invoke(target, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
-        protected Object invoke_F10(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object a9) { return convert_F(invoker.<float >invoke(target, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
-        protected Object invoke_D10(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object a9) { return convert_D(invoker.<double>invoke(target, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
+        protected Object invoke_L10(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object a9) throws Throwable { return convert_L(invoker.<Object>invoke(target, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
+        protected Object invoke_I10(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object a9) throws Throwable { return convert_I(invoker.<int   >invoke(target, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
+        protected Object invoke_J10(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object a9) throws Throwable { return convert_J(invoker.<long  >invoke(target, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
+        protected Object invoke_F10(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object a9) throws Throwable { return convert_F(invoker.<float >invoke(target, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
+        protected Object invoke_D10(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object a9) throws Throwable { return convert_D(invoker.<double>invoke(target, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
     }
 }
--- a/jdk/src/share/classes/sun/dyn/Invokers.java	Thu Dec 17 14:10:20 2009 -0800
+++ b/jdk/src/share/classes/sun/dyn/Invokers.java	Wed Jul 05 17:04:56 2017 +0200
@@ -44,16 +44,20 @@
     // generic (untyped) invoker for the outgoing call
     private /*lazy*/ MethodHandle genericInvoker;
 
+    // generic (untyped) invoker for the outgoing call; accepts a single Object[]
+    private final /*lazy*/ MethodHandle[] varargsInvokers;
+
     /** Compute and cache information common to all collecting adapters
      *  that implement members of the erasure-family of the given erased type.
      */
     public Invokers(Access token, MethodType targetType) {
         Access.check(token);
         this.targetType = targetType;
+        this.varargsInvokers = new MethodHandle[targetType.parameterCount()+1];
     }
 
     public static MethodType invokerType(MethodType targetType) {
-        return targetType.insertParameterType(0, MethodHandle.class);
+        return targetType.insertParameterTypes(0, MethodHandle.class);
     }
 
     public MethodHandle exactInvoker() {
@@ -76,8 +80,14 @@
         return invoker;
     }
 
-    public MethodHandle varargsInvoker() {
-        throw new UnsupportedOperationException("NYI");
+    public MethodHandle varargsInvoker(int objectArgCount) {
+        MethodHandle vaInvoker = varargsInvokers[objectArgCount];
+        if (vaInvoker != null)  return vaInvoker;
+        MethodHandle gInvoker = genericInvoker();
+        MethodType vaType = MethodType.genericMethodType(objectArgCount, true);
+        vaInvoker = MethodHandles.spreadArguments(gInvoker, invokerType(vaType));
+        varargsInvokers[objectArgCount] = vaInvoker;
+        return vaInvoker;
     }
 
     public String toString() {
--- a/jdk/src/share/classes/sun/dyn/MemberName.java	Thu Dec 17 14:10:20 2009 -0800
+++ b/jdk/src/share/classes/sun/dyn/MemberName.java	Wed Jul 05 17:04:56 2017 +0200
@@ -25,7 +25,7 @@
 
 package sun.dyn;
 
-import sun.dyn.util.BytecodeSignature;
+import sun.dyn.util.BytecodeDescriptor;
 import java.dyn.*;
 import java.lang.reflect.Constructor;
 import java.lang.reflect.Field;
@@ -33,6 +33,7 @@
 import java.lang.reflect.Member;
 import java.lang.reflect.Modifier;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collections;
 import java.util.Iterator;
 import java.util.List;
@@ -93,7 +94,7 @@
         }
         if (type instanceof String) {
             String sig = (String) type;
-            MethodType res = MethodType.fromBytecodeString(sig, getClassLoader());
+            MethodType res = MethodType.fromMethodDescriptorString(sig, getClassLoader());
             this.type = res;
             return res;
         }
@@ -101,7 +102,7 @@
             Object[] typeInfo = (Object[]) type;
             Class<?>[] ptypes = (Class<?>[]) typeInfo[1];
             Class<?> rtype = (Class<?>) typeInfo[0];
-            MethodType res = MethodType.make(rtype, ptypes);
+            MethodType res = MethodType.methodType(rtype, ptypes);
             this.type = res;
             return res;
         }
@@ -111,7 +112,7 @@
     public MethodType getInvocationType() {
         MethodType itype = getMethodType();
         if (!isStatic())
-            itype = itype.insertParameterType(0, clazz);
+            itype = itype.insertParameterTypes(0, clazz);
         return itype;
     }
 
@@ -135,7 +136,7 @@
         }
         if (type instanceof String) {
             String sig = (String) type;
-            MethodType mtype = MethodType.fromBytecodeString("()"+sig, getClassLoader());
+            MethodType mtype = MethodType.fromMethodDescriptorString("()"+sig, getClassLoader());
             Class<?> res = mtype.returnType();
             this.type = res;
             return res;
@@ -155,9 +156,9 @@
         if (type instanceof String)
             return (String) type;
         if (isInvocable())
-            return BytecodeSignature.unparse(getMethodType());
+            return BytecodeDescriptor.unparse(getMethodType());
         else
-            return BytecodeSignature.unparse(getFieldType());
+            return BytecodeDescriptor.unparse(getFieldType());
     }
 
     public int getModifiers() {
@@ -353,6 +354,8 @@
             return type.toString();  // class java.lang.String
         // else it is a field, method, or constructor
         StringBuilder buf = new StringBuilder();
+        if (!isResolved())
+            buf.append("*.");
         if (getDeclaringClass() != null) {
             buf.append(getName(clazz));
             buf.append('.');
@@ -381,7 +384,7 @@
     private static String getName(Object obj) {
         if (obj instanceof Class<?>)
             return ((Class<?>)obj).getName();
-        return obj.toString();
+        return String.valueOf(obj);
     }
 
     // Queries to the JVM:
@@ -408,6 +411,9 @@
     public static NoAccessException newNoAccessException(MemberName name, Class<?> lookupClass) {
         return newNoAccessException("cannot access", name, lookupClass);
     }
+    public static NoAccessException newNoAccessException(MemberName name, MethodHandles.Lookup lookup) {
+        return newNoAccessException(name, lookup.lookupClass());
+    }
     public static NoAccessException newNoAccessException(String message,
             MemberName name, Class<?> lookupClass) {
         message += ": " + name;
@@ -436,7 +442,7 @@
             matchFlags &= ALLOWED_FLAGS;
             String matchSig = null;
             if (matchType != null) {
-                matchSig = BytecodeSignature.unparse(matchType);
+                matchSig = BytecodeDescriptor.unparse(matchType);
                 if (matchSig.startsWith("("))
                     matchFlags &= ~(ALL_KINDS & ~IS_INVOCABLE);
                 else
@@ -447,17 +453,18 @@
             MemberName[] buf = newMemberBuffer(len1);
             int totalCount = 0;
             ArrayList<MemberName[]> bufs = null;
+            int bufCount = 0;
             for (;;) {
-                int bufCount = MethodHandleNatives.getMembers(defc,
+                bufCount = MethodHandleNatives.getMembers(defc,
                         matchName, matchSig, matchFlags,
                         lookupClass,
                         totalCount, buf);
                 if (bufCount <= buf.length) {
-                    if (bufCount >= 0)
-                        totalCount += bufCount;
+                    if (bufCount < 0)  bufCount = 0;
+                    totalCount += bufCount;
                     break;
                 }
-                // JVM returned tp us with an intentional overflow!
+                // JVM returned to us with an intentional overflow!
                 totalCount += buf.length;
                 int excess = bufCount - buf.length;
                 if (bufs == null)  bufs = new ArrayList<MemberName[]>(1);
@@ -473,7 +480,7 @@
                     Collections.addAll(result, buf0);
                 }
             }
-            Collections.addAll(result, buf);
+            result.addAll(Arrays.asList(buf).subList(0, bufCount));
             // Signature matching is not the same as type matching, since
             // one signature might correspond to several types.
             // So if matchType is a Class or MethodType, refilter the results.
--- a/jdk/src/share/classes/sun/dyn/MethodHandleImpl.java	Thu Dec 17 14:10:20 2009 -0800
+++ b/jdk/src/share/classes/sun/dyn/MethodHandleImpl.java	Wed Jul 05 17:04:56 2017 +0200
@@ -25,12 +25,25 @@
 
 package sun.dyn;
 
+import java.dyn.JavaMethodHandle;
 import java.dyn.MethodHandle;
 import java.dyn.MethodHandles;
 import java.dyn.MethodHandles.Lookup;
 import java.dyn.MethodType;
+import java.util.logging.Level;
+import java.util.logging.Logger;
 import sun.dyn.util.VerifyType;
 import java.dyn.NoAccessException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import sun.dyn.empty.Empty;
+import sun.dyn.util.ValueConversions;
+import sun.dyn.util.Wrapper;
+import sun.misc.Unsafe;
 import static sun.dyn.MemberName.newIllegalArgumentException;
 import static sun.dyn.MemberName.newNoAccessException;
 
@@ -57,6 +70,25 @@
     static final int  INT_FIELD = 0;
     static final long LONG_FIELD = 0;
 
+    /** Access methods for the internals of MethodHandle, supplied to
+     *  MethodHandleImpl as a trusted agent.
+     */
+    static public interface MethodHandleFriend {
+        void initType(MethodHandle mh, MethodType type);
+    }
+    public static void setMethodHandleFriend(Access token, MethodHandleFriend am) {
+        Access.check(token);
+        if (METHOD_HANDLE_FRIEND != null)
+            throw new InternalError();  // just once
+        METHOD_HANDLE_FRIEND = am;
+    }
+    static private MethodHandleFriend METHOD_HANDLE_FRIEND;
+
+    // NOT public
+    static void initType(MethodHandle mh, MethodType type) {
+        METHOD_HANDLE_FRIEND.initType(mh, type);
+    }
+
     // type is defined in java.dyn.MethodHandle, which is platform-independent
 
     // vmentry (a void* field) is used *only* by by the JVM.
@@ -106,8 +138,8 @@
     }
 
     static {
-        // Force initialization:
-        Lookup.PUBLIC_LOOKUP.lookupClass();
+        // Force initialization of Lookup, so it calls us back as initLookup:
+        MethodHandles.publicLookup();
         if (IMPL_LOOKUP_INIT == null)
             throw new InternalError();
     }
@@ -151,7 +183,7 @@
             // adjust the advertised receiver type to be exactly the one requested
             // (in the case of invokespecial, this will be the calling class)
             Class<?> recvType = method.getDeclaringClass();
-            mtype = mtype.insertParameterType(0, recvType);
+            mtype = mtype.insertParameterTypes(0, recvType);
             if (method.isConstructor())
                 doDispatch = true;
             // FIXME: JVM has trouble building MH.invoke sites for
@@ -170,21 +202,223 @@
 
     public static
     MethodHandle accessField(Access token,
-                           MemberName member, boolean isSetter,
-                           Class<?> lookupClass) {
+                             MemberName member, boolean isSetter,
+                             Class<?> lookupClass) {
         Access.check(token);
-        // FIXME: Use sun.misc.Unsafe to dig up the dirt on the field.
-        throw new UnsupportedOperationException("Not yet implemented");
+        // Use sun. misc.Unsafe to dig up the dirt on the field.
+        MethodHandle mh = new FieldAccessor(token, member, isSetter);
+        return mh;
     }
 
     public static
     MethodHandle accessArrayElement(Access token,
-                           Class<?> arrayClass, boolean isSetter) {
+                                    Class<?> arrayClass, boolean isSetter) {
         Access.check(token);
         if (!arrayClass.isArray())
             throw newIllegalArgumentException("not an array: "+arrayClass);
-        // FIXME: Use sun.misc.Unsafe to dig up the dirt on the array.
-        throw new UnsupportedOperationException("Not yet implemented");
+        Class<?> elemClass = arrayClass.getComponentType();
+        MethodHandle[] mhs = FieldAccessor.ARRAY_CACHE.get(elemClass);
+        if (mhs == null) {
+            if (!FieldAccessor.doCache(elemClass))
+                return FieldAccessor.ahandle(arrayClass, isSetter);
+            mhs = new MethodHandle[] {
+                FieldAccessor.ahandle(arrayClass, false),
+                FieldAccessor.ahandle(arrayClass, true)
+            };
+            if (mhs[0].type().parameterType(0) == Class.class) {
+                mhs[0] = MethodHandles.insertArguments(mhs[0], 0, elemClass);
+                mhs[1] = MethodHandles.insertArguments(mhs[1], 0, elemClass);
+            }
+            synchronized (FieldAccessor.ARRAY_CACHE) {}  // memory barrier
+            FieldAccessor.ARRAY_CACHE.put(elemClass, mhs);
+        }
+        return mhs[isSetter ? 1 : 0];
+    }
+
+    static final class FieldAccessor<C,V> extends JavaMethodHandle {
+        private static final Unsafe unsafe = Unsafe.getUnsafe();
+        final Object base;  // for static refs only
+        final long offset;
+        final String name;
+
+        public FieldAccessor(Access token, MemberName field, boolean isSetter) {
+            super(fhandle(field.getDeclaringClass(), field.getFieldType(), isSetter, field.isStatic()));
+            this.offset = (long) field.getVMIndex(token);
+            this.name = field.getName();
+            this.base = staticBase(field);
+        }
+        public String toString() { return name; }
+
+        int getFieldI(C obj) { return unsafe.getInt(obj, offset); }
+        void setFieldI(C obj, int x) { unsafe.putInt(obj, offset, x); }
+        long getFieldJ(C obj) { return unsafe.getLong(obj, offset); }
+        void setFieldJ(C obj, long x) { unsafe.putLong(obj, offset, x); }
+        float getFieldF(C obj) { return unsafe.getFloat(obj, offset); }
+        void setFieldF(C obj, float x) { unsafe.putFloat(obj, offset, x); }
+        double getFieldD(C obj) { return unsafe.getDouble(obj, offset); }
+        void setFieldD(C obj, double x) { unsafe.putDouble(obj, offset, x); }
+        boolean getFieldZ(C obj) { return unsafe.getBoolean(obj, offset); }
+        void setFieldZ(C obj, boolean x) { unsafe.putBoolean(obj, offset, x); }
+        byte getFieldB(C obj) { return unsafe.getByte(obj, offset); }
+        void setFieldB(C obj, byte x) { unsafe.putByte(obj, offset, x); }
+        short getFieldS(C obj) { return unsafe.getShort(obj, offset); }
+        void setFieldS(C obj, short x) { unsafe.putShort(obj, offset, x); }
+        char getFieldC(C obj) { return unsafe.getChar(obj, offset); }
+        void setFieldC(C obj, char x) { unsafe.putChar(obj, offset, x); }
+        @SuppressWarnings("unchecked")
+        V getFieldL(C obj) { return (V) unsafe.getObject(obj, offset); }
+        @SuppressWarnings("unchecked")
+        void setFieldL(C obj, V x) { unsafe.putObject(obj, offset, x); }
+        // cast (V) is OK here, since we wrap convertArguments around the MH.
+
+        static Object staticBase(MemberName field) {
+            if (!field.isStatic())  return null;
+            Class c = field.getDeclaringClass();
+            java.lang.reflect.Field f;
+            try {
+                // FIXME:  Should not have to create 'f' to get this value.
+                f = c.getDeclaredField(field.getName());
+                return unsafe.staticFieldBase(f);
+            } catch (Exception ee) {
+                Error e = new InternalError();
+                e.initCause(ee);
+                throw e;
+            }
+        }
+
+        int getStaticI() { return unsafe.getInt(base, offset); }
+        void setStaticI(int x) { unsafe.putInt(base, offset, x); }
+        long getStaticJ() { return unsafe.getLong(base, offset); }
+        void setStaticJ(long x) { unsafe.putLong(base, offset, x); }
+        float getStaticF() { return unsafe.getFloat(base, offset); }
+        void setStaticF(float x) { unsafe.putFloat(base, offset, x); }
+        double getStaticD() { return unsafe.getDouble(base, offset); }
+        void setStaticD(double x) { unsafe.putDouble(base, offset, x); }
+        boolean getStaticZ() { return unsafe.getBoolean(base, offset); }
+        void setStaticZ(boolean x) { unsafe.putBoolean(base, offset, x); }
+        byte getStaticB() { return unsafe.getByte(base, offset); }
+        void setStaticB(byte x) { unsafe.putByte(base, offset, x); }
+        short getStaticS() { return unsafe.getShort(base, offset); }
+        void setStaticS(short x) { unsafe.putShort(base, offset, x); }
+        char getStaticC() { return unsafe.getChar(base, offset); }
+        void setStaticC(char x) { unsafe.putChar(base, offset, x); }
+        V getStaticL() { return (V) unsafe.getObject(base, offset); }
+        void setStaticL(V x) { unsafe.putObject(base, offset, x); }
+
+        static String fname(Class<?> vclass, boolean isSetter, boolean isStatic) {
+            String stem;
+            if (!isStatic)
+                stem = (!isSetter ? "getField" : "setField");
+            else
+                stem = (!isSetter ? "getStatic" : "setStatic");
+            return stem + Wrapper.basicTypeChar(vclass);
+        }
+        static MethodType ftype(Class<?> cclass, Class<?> vclass, boolean isSetter, boolean isStatic) {
+            MethodType type;
+            if (!isStatic) {
+                if (!isSetter)
+                    return MethodType.methodType(vclass, cclass);
+                else
+                    return MethodType.methodType(void.class, cclass, vclass);
+            } else {
+                if (!isSetter)
+                    return MethodType.methodType(vclass);
+                else
+                    return MethodType.methodType(void.class, vclass);
+            }
+        }
+        static MethodHandle fhandle(Class<?> cclass, Class<?> vclass, boolean isSetter, boolean isStatic) {
+            String name = FieldAccessor.fname(vclass, isSetter, isStatic);
+            if (cclass.isPrimitive())  throw newIllegalArgumentException("primitive "+cclass);
+            Class<?> ecclass = Object.class;  //erase this type
+            Class<?> evclass = vclass;
+            if (!evclass.isPrimitive())  evclass = Object.class;
+            MethodType type = FieldAccessor.ftype(ecclass, evclass, isSetter, isStatic);
+            MethodHandle mh;
+            try {
+                mh = IMPL_LOOKUP.findVirtual(FieldAccessor.class, name, type);
+            } catch (NoAccessException ee) {
+                Error e = new InternalError("name,type="+name+type);
+                e.initCause(ee);
+                throw e;
+            }
+            if (evclass != vclass || (!isStatic && ecclass != cclass)) {
+                MethodType strongType = FieldAccessor.ftype(cclass, vclass, isSetter, isStatic);
+                strongType = strongType.insertParameterTypes(0, FieldAccessor.class);
+                mh = MethodHandles.convertArguments(mh, strongType);
+            }
+            return mh;
+        }
+
+        /// Support for array element access
+        static final HashMap<Class<?>, MethodHandle[]> ARRAY_CACHE =
+                new HashMap<Class<?>, MethodHandle[]>();
+        // FIXME: Cache on the classes themselves, not here.
+        static boolean doCache(Class<?> elemClass) {
+            if (elemClass.isPrimitive())  return true;
+            ClassLoader cl = elemClass.getClassLoader();
+            return cl == null || cl == ClassLoader.getSystemClassLoader();
+        }
+        static int getElementI(int[] a, int i) { return a[i]; }
+        static void setElementI(int[] a, int i, int x) { a[i] = x; }
+        static long getElementJ(long[] a, int i) { return a[i]; }
+        static void setElementJ(long[] a, int i, long x) { a[i] = x; }
+        static float getElementF(float[] a, int i) { return a[i]; }
+        static void setElementF(float[] a, int i, float x) { a[i] = x; }
+        static double getElementD(double[] a, int i) { return a[i]; }
+        static void setElementD(double[] a, int i, double x) { a[i] = x; }
+        static boolean getElementZ(boolean[] a, int i) { return a[i]; }
+        static void setElementZ(boolean[] a, int i, boolean x) { a[i] = x; }
+        static byte getElementB(byte[] a, int i) { return a[i]; }
+        static void setElementB(byte[] a, int i, byte x) { a[i] = x; }
+        static short getElementS(short[] a, int i) { return a[i]; }
+        static void setElementS(short[] a, int i, short x) { a[i] = x; }
+        static char getElementC(char[] a, int i) { return a[i]; }
+        static void setElementC(char[] a, int i, char x) { a[i] = x; }
+        static Object getElementL(Object[] a, int i) { return a[i]; }
+        static void setElementL(Object[] a, int i, Object x) { a[i] = x; }
+        static <V> V getElementL(Class<V[]> aclass, V[] a, int i) { return aclass.cast(a)[i]; }
+        static <V> void setElementL(Class<V[]> aclass, V[] a, int i, V x) { aclass.cast(a)[i] = x; }
+
+        static String aname(Class<?> aclass, boolean isSetter) {
+            Class<?> vclass = aclass.getComponentType();
+            if (vclass == null)  throw new IllegalArgumentException();
+            return (!isSetter ? "getElement" : "setElement") + Wrapper.basicTypeChar(vclass);
+        }
+        static MethodType atype(Class<?> aclass, boolean isSetter) {
+            Class<?> vclass = aclass.getComponentType();
+            if (!isSetter)
+                return MethodType.methodType(vclass, aclass, int.class);
+            else
+                return MethodType.methodType(void.class, aclass, int.class, vclass);
+        }
+        static MethodHandle ahandle(Class<?> aclass, boolean isSetter) {
+            Class<?> vclass = aclass.getComponentType();
+            String name = FieldAccessor.aname(aclass, isSetter);
+            Class<?> caclass = null;
+            if (!vclass.isPrimitive() && vclass != Object.class) {
+                caclass = aclass;
+                aclass = Object[].class;
+                vclass = Object.class;
+            }
+            MethodType type = FieldAccessor.atype(aclass, isSetter);
+            if (caclass != null)
+                type = type.insertParameterTypes(0, Class.class);
+            MethodHandle mh;
+            try {
+                mh = IMPL_LOOKUP.findStatic(FieldAccessor.class, name, type);
+            } catch (NoAccessException ee) {
+                Error e = new InternalError("name,type="+name+type);
+                e.initCause(ee);
+                throw e;
+            }
+            if (caclass != null) {
+                MethodType strongType = FieldAccessor.atype(caclass, isSetter);
+                mh = MethodHandles.insertArguments(mh, 0, caclass);
+                mh = MethodHandles.convertArguments(mh, strongType);
+            }
+            return mh;
+        }
     }
 
     /** Bind a predetermined first argument to the given direct method handle.
@@ -203,8 +437,11 @@
             if (info instanceof DirectMethodHandle) {
                 DirectMethodHandle dmh = (DirectMethodHandle) info;
                 if (receiver == null ||
-                    dmh.type().parameterType(0).isAssignableFrom(receiver.getClass()))
-                    target = dmh;
+                    dmh.type().parameterType(0).isAssignableFrom(receiver.getClass())) {
+                    MethodHandle bmh = new BoundMethodHandle(dmh, receiver, 0);
+                    MethodType newType = target.type().dropParameterTypes(0, 1);
+                    return convertArguments(token, bmh, newType, bmh.type(), null);
+                }
             }
         }
         if (target instanceof DirectMethodHandle)
@@ -223,7 +460,7 @@
     MethodHandle bindArgument(Access token,
                               MethodHandle target, int argnum, Object receiver) {
         Access.check(token);
-        throw new UnsupportedOperationException("NYI");
+        return new BoundMethodHandle(target, receiver, argnum);
     }
 
     public static MethodHandle convertArguments(Access token,
@@ -232,6 +469,189 @@
                                                 MethodType oldType,
                                                 int[] permutationOrNull) {
         Access.check(token);
+        if (permutationOrNull != null) {
+            int outargs = oldType.parameterCount(), inargs = newType.parameterCount();
+            if (permutationOrNull.length != outargs)
+                throw newIllegalArgumentException("wrong number of arguments in permutation");
+            // Make the individual outgoing argument types match up first.
+            Class<?>[] callTypeArgs = new Class<?>[outargs];
+            for (int i = 0; i < outargs; i++)
+                callTypeArgs[i] = newType.parameterType(permutationOrNull[i]);
+            MethodType callType = MethodType.methodType(oldType.returnType(), callTypeArgs);
+            target = convertArguments(token, target, callType, oldType, null);
+            assert(target != null);
+            oldType = target.type();
+            List<Integer> goal = new ArrayList<Integer>();  // i*TOKEN
+            List<Integer> state = new ArrayList<Integer>(); // i*TOKEN
+            List<Integer> drops = new ArrayList<Integer>(); // not tokens
+            List<Integer> dups = new ArrayList<Integer>();  // not tokens
+            final int TOKEN = 10; // to mark items which are symbolic only
+            // state represents the argument values coming into target
+            for (int i = 0; i < outargs; i++) {
+                state.add(permutationOrNull[i] * TOKEN);
+            }
+            // goal represents the desired state
+            for (int i = 0; i < inargs; i++) {
+                if (state.contains(i * TOKEN)) {
+                    goal.add(i * TOKEN);
+                } else {
+                    // adapter must initially drop all unused arguments
+                    drops.add(i);
+                }
+            }
+            // detect duplications
+            while (state.size() > goal.size()) {
+                for (int i2 = 0; i2 < state.size(); i2++) {
+                    int arg1 = state.get(i2);
+                    int i1 = state.indexOf(arg1);
+                    if (i1 != i2) {
+                        // found duplicate occurrence at i2
+                        int arg2 = (inargs++) * TOKEN;
+                        state.set(i2, arg2);
+                        dups.add(goal.indexOf(arg1));
+                        goal.add(arg2);
+                    }
+                }
+            }
+            assert(state.size() == goal.size());
+            int size = goal.size();
+            while (!state.equals(goal)) {
+                // Look for a maximal sequence of adjacent misplaced arguments,
+                // and try to rotate them into place.
+                int bestRotArg = -10 * TOKEN, bestRotLen = 0;
+                int thisRotArg = -10 * TOKEN, thisRotLen = 0;
+                for (int i = 0; i < size; i++) {
+                    int arg = state.get(i);
+                    // Does this argument match the current run?
+                    if (arg == thisRotArg + TOKEN) {
+                        thisRotArg = arg;
+                        thisRotLen += 1;
+                        if (bestRotLen < thisRotLen) {
+                            bestRotLen = thisRotLen;
+                            bestRotArg = thisRotArg;
+                        }
+                    } else {
+                        // The old sequence (if any) stops here.
+                        thisRotLen = 0;
+                        thisRotArg = -10 * TOKEN;
+                        // But maybe a new one starts here also.
+                        int wantArg = goal.get(i);
+                        final int MAX_ARG_ROTATION = AdapterMethodHandle.MAX_ARG_ROTATION;
+                        if (arg != wantArg &&
+                            arg >= wantArg - TOKEN * MAX_ARG_ROTATION &&
+                            arg <= wantArg + TOKEN * MAX_ARG_ROTATION) {
+                            thisRotArg = arg;
+                            thisRotLen = 1;
+                        }
+                    }
+                }
+                if (bestRotLen >= 2) {
+                    // Do a rotation if it can improve argument positioning
+                    // by at least 2 arguments.  This is not always optimal,
+                    // but it seems to catch common cases.
+                    int dstEnd = state.indexOf(bestRotArg);
+                    int srcEnd = goal.indexOf(bestRotArg);
+                    int rotBy = dstEnd - srcEnd;
+                    int dstBeg = dstEnd - (bestRotLen - 1);
+                    int srcBeg = srcEnd - (bestRotLen - 1);
+                    assert((dstEnd | dstBeg | srcEnd | srcBeg) >= 0); // no negs
+                    // Make a span which covers both source and destination.
+                    int rotBeg = Math.min(dstBeg, srcBeg);
+                    int rotEnd = Math.max(dstEnd, srcEnd);
+                    int score = 0;
+                    for (int i = rotBeg; i <= rotEnd; i++) {
+                        if ((int)state.get(i) != (int)goal.get(i))
+                            score += 1;
+                    }
+                    List<Integer> rotSpan = state.subList(rotBeg, rotEnd+1);
+                    Collections.rotate(rotSpan, -rotBy);  // reverse direction
+                    for (int i = rotBeg; i <= rotEnd; i++) {
+                        if ((int)state.get(i) != (int)goal.get(i))
+                            score -= 1;
+                    }
+                    if (score >= 2) {
+                        // Improved at least two argument positions.  Do it.
+                        List<Class<?>> ptypes = Arrays.asList(oldType.parameterArray());
+                        Collections.rotate(ptypes.subList(rotBeg, rotEnd+1), -rotBy);
+                        MethodType rotType = MethodType.methodType(oldType.returnType(), ptypes);
+                        MethodHandle nextTarget
+                                = AdapterMethodHandle.makeRotateArguments(token, rotType, target,
+                                        rotBeg, rotSpan.size(), rotBy);
+                        if (nextTarget != null) {
+                            //System.out.println("Rot: "+rotSpan+" by "+rotBy);
+                            target = nextTarget;
+                            oldType = rotType;
+                            continue;
+                        }
+                    }
+                    // Else de-rotate, and drop through to the swap-fest.
+                    Collections.rotate(rotSpan, rotBy);
+                }
+
+                // Now swap like the wind!
+                List<Class<?>> ptypes = Arrays.asList(oldType.parameterArray());
+                for (int i = 0; i < size; i++) {
+                    // What argument do I want here?
+                    int arg = goal.get(i);
+                    if (arg != state.get(i)) {
+                        // Where is it now?
+                        int j = state.indexOf(arg);
+                        Collections.swap(ptypes, i, j);
+                        MethodType swapType = MethodType.methodType(oldType.returnType(), ptypes);
+                        target = AdapterMethodHandle.makeSwapArguments(token, swapType, target, i, j);
+                        if (target == null)  throw newIllegalArgumentException("cannot swap");
+                        assert(target.type() == swapType);
+                        oldType = swapType;
+                        Collections.swap(state, i, j);
+                    }
+                }
+                // One pass of swapping must finish the job.
+                assert(state.equals(goal));
+            }
+            while (!dups.isEmpty()) {
+                // Grab a contiguous trailing sequence of dups.
+                int grab = dups.size() - 1;
+                int dupArgPos = dups.get(grab), dupArgCount = 1;
+                while (grab - 1 >= 0) {
+                    int dup0 = dups.get(grab - 1);
+                    if (dup0 != dupArgPos - 1)  break;
+                    dupArgPos -= 1;
+                    dupArgCount += 1;
+                    grab -= 1;
+                }
+                //if (dupArgCount > 1)  System.out.println("Dup: "+dups.subList(grab, dups.size()));
+                dups.subList(grab, dups.size()).clear();
+                // In the new target type drop that many args from the tail:
+                List<Class<?>> ptypes = oldType.parameterList();
+                ptypes = ptypes.subList(0, ptypes.size() - dupArgCount);
+                MethodType dupType = MethodType.methodType(oldType.returnType(), ptypes);
+                target = AdapterMethodHandle.makeDupArguments(token, dupType, target, dupArgPos, dupArgCount);
+                if (target == null)
+                    throw newIllegalArgumentException("cannot dup");
+                oldType = target.type();
+            }
+            while (!drops.isEmpty()) {
+                // Grab a contiguous initial sequence of drops.
+                int dropArgPos = drops.get(0), dropArgCount = 1;
+                while (dropArgCount < drops.size()) {
+                    int drop1 = drops.get(dropArgCount);
+                    if (drop1 != dropArgPos + dropArgCount)  break;
+                    dropArgCount += 1;
+                }
+                //if (dropArgCount > 1)  System.out.println("Drop: "+drops.subList(0, dropArgCount));
+                drops.subList(0, dropArgCount).clear();
+                List<Class<?>> dropTypes = newType.parameterList()
+                        .subList(dropArgPos, dropArgPos + dropArgCount);
+                MethodType dropType = oldType.insertParameterTypes(dropArgPos, dropTypes);
+                target = AdapterMethodHandle.makeDropArguments(token, dropType, target, dropArgPos, dropArgCount);
+                if (target == null)  throw newIllegalArgumentException("cannot drop");
+                oldType = target.type();
+            }
+        }
+        if (newType == oldType)
+            return target;
+        if (oldType.parameterCount() != newType.parameterCount())
+            throw newIllegalArgumentException("mismatched parameter count");
         MethodHandle res = AdapterMethodHandle.makePairwiseConvert(token, newType, target);
         if (res != null)
             return res;
@@ -241,7 +661,7 @@
         // Use a heavier method:  Convert all the arguments to Object,
         // then back to the desired types.  We might have to use Java-based
         // method handles to do this.
-        MethodType objType = MethodType.makeGeneric(argc);
+        MethodType objType = MethodType.genericMethodType(argc);
         MethodHandle objTarget = AdapterMethodHandle.makePairwiseConvert(token, objType, target);
         if (objTarget == null)
             objTarget = FromGeneric.make(target);
@@ -272,83 +692,386 @@
         Class<?>[] ptypes = oldType.parameterArray();
         for (int i = 0; i < spreadCount; i++)
             ptypes[spreadArg + i] = VerifyType.spreadArgElementType(spreadType, i);
-        MethodType midType = MethodType.make(newType.returnType(), ptypes);
+        MethodType midType = MethodType.methodType(newType.returnType(), ptypes);
         // after spreading, some arguments may need further conversion
-        target = convertArguments(token, target, midType, oldType, null);
-        if (target == null)
+        MethodHandle target2 = convertArguments(token, target, midType, oldType, null);
+        if (target2 == null)
             throw new UnsupportedOperationException("NYI: convert "+midType+" =calls=> "+oldType);
-        res = AdapterMethodHandle.makeSpreadArguments(token, newType, target, spreadArgType, spreadArg, spreadCount);
+        res = AdapterMethodHandle.makeSpreadArguments(token, newType, target2, spreadArgType, spreadArg, spreadCount);
+        if (res != null)
+            return res;
+        res = SpreadGeneric.make(target2, spreadCount);
+        if (res != null)
+            res = convertArguments(token, res, newType, res.type(), null);
         return res;
     }
 
     public static MethodHandle collectArguments(Access token,
                                                 MethodHandle target,
                                                 MethodType newType,
-                                                int collectArg) {
-        if (collectArg > 0)
-            throw new UnsupportedOperationException("NYI");
-        throw new UnsupportedOperationException("NYI");
+                                                int collectArg,
+                                                MethodHandle collector) {
+        MethodType oldType = target.type();     // (a...,c)=>r
+        if (collector == null) {
+            int numCollect = newType.parameterCount() - oldType.parameterCount() + 1;
+            collector = ValueConversions.varargsArray(numCollect);
+        }
+        //         newType                      // (a..., b...)=>r
+        MethodType colType = collector.type();  // (b...)=>c
+        //         oldType                      // (a..., b...)=>r
+        assert(newType.parameterCount() == collectArg + colType.parameterCount());
+        assert(oldType.parameterCount() == collectArg + 1);
+        MethodHandle gtarget = convertArguments(token, target, oldType.generic(), oldType, null);
+        MethodHandle gcollector = convertArguments(token, collector, colType.generic(), colType, null);
+        if (gtarget == null || gcollector == null)  return null;
+        MethodHandle gresult = FilterGeneric.makeArgumentCollector(gcollector, gtarget);
+        MethodHandle result = convertArguments(token, gresult, newType, gresult.type(), null);
+        return result;
     }
+
+    public static MethodHandle filterArgument(Access token,
+                                              MethodHandle target,
+                                              int pos,
+                                              MethodHandle filter) {
+        Access.check(token);
+        MethodType ttype = target.type(), gttype = ttype.generic();
+        if (ttype != gttype) {
+            target = convertArguments(token, target, gttype, ttype, null);
+            ttype = gttype;
+        }
+        MethodType ftype = filter.type(), gftype = ftype.generic();
+        if (ftype.parameterCount() != 1)
+            throw new InternalError();
+        if (ftype != gftype) {
+            filter = convertArguments(token, filter, gftype, ftype, null);
+            ftype = gftype;
+        }
+        if (ftype == ttype) {
+            // simple unary case
+            return FilterOneArgument.make(filter, target);
+        }
+        return FilterGeneric.makeArgumentFilter(pos, filter, target);
+    }
+
+    public static MethodHandle foldArguments(Access token,
+                                             MethodHandle target,
+                                             MethodType newType,
+                                             MethodHandle combiner) {
+        Access.check(token);
+        MethodType oldType = target.type();
+        MethodType ctype = combiner.type();
+        MethodHandle gtarget = convertArguments(token, target, oldType.generic(), oldType, null);
+        MethodHandle gcombiner = convertArguments(token, combiner, ctype.generic(), ctype, null);
+        if (gtarget == null || gcombiner == null)  return null;
+        MethodHandle gresult = FilterGeneric.makeArgumentFolder(gcombiner, gtarget);
+        MethodHandle result = convertArguments(token, gresult, newType, gresult.type(), null);
+        return result;
+    }
+
     public static
     MethodHandle dropArguments(Access token, MethodHandle target,
                                MethodType newType, int argnum) {
         Access.check(token);
+        int drops = newType.parameterCount() - target.type().parameterCount();
+        MethodHandle res = AdapterMethodHandle.makeDropArguments(token, newType, target, argnum, drops);
+        if (res != null)
+            return res;
         throw new UnsupportedOperationException("NYI");
     }
 
+    private static class GuardWithTest extends JavaMethodHandle {
+        private final MethodHandle test, target, fallback;
+        public GuardWithTest(MethodHandle test, MethodHandle target, MethodHandle fallback) {
+            this(INVOKES[target.type().parameterCount()], test, target, fallback);
+        }
+        public GuardWithTest(MethodHandle invoker,
+                             MethodHandle test, MethodHandle target, MethodHandle fallback) {
+            super(invoker);
+            this.test = test;
+            this.target = target;
+            this.fallback = fallback;
+        }
+        @Override
+        public String toString() {
+            return target.toString();
+        }
+        private Object invoke_V(Object... av) throws Throwable {
+            if (test.<boolean>invoke(av))
+                return target.<Object>invoke(av);
+            return fallback.<Object>invoke(av);
+        }
+        private Object invoke_L0() throws Throwable {
+            if (test.<boolean>invoke())
+                return target.<Object>invoke();
+            return fallback.<Object>invoke();
+        }
+        private Object invoke_L1(Object a0) throws Throwable {
+            if (test.<boolean>invoke(a0))
+                return target.<Object>invoke(a0);
+            return fallback.<Object>invoke(a0);
+        }
+        private Object invoke_L2(Object a0, Object a1) throws Throwable {
+            if (test.<boolean>invoke(a0, a1))
+                return target.<Object>invoke(a0, a1);
+            return fallback.<Object>invoke(a0, a1);
+        }
+        private Object invoke_L3(Object a0, Object a1, Object a2) throws Throwable {
+            if (test.<boolean>invoke(a0, a1, a2))
+                return target.<Object>invoke(a0, a1, a2);
+            return fallback.<Object>invoke(a0, a1, a2);
+        }
+        private Object invoke_L4(Object a0, Object a1, Object a2, Object a3) throws Throwable {
+            if (test.<boolean>invoke(a0, a1, a2, a3))
+                return target.<Object>invoke(a0, a1, a2, a3);
+            return fallback.<Object>invoke(a0, a1, a2, a3);
+        }
+        private Object invoke_L5(Object a0, Object a1, Object a2, Object a3, Object a4) throws Throwable {
+            if (test.<boolean>invoke(a0, a1, a2, a3, a4))
+                return target.<Object>invoke(a0, a1, a2, a3, a4);
+            return fallback.<Object>invoke(a0, a1, a2, a3, a4);
+        }
+        private Object invoke_L6(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) throws Throwable {
+            if (test.<boolean>invoke(a0, a1, a2, a3, a4, a5))
+                return target.<Object>invoke(a0, a1, a2, a3, a4, a5);
+            return fallback.<Object>invoke(a0, a1, a2, a3, a4, a5);
+        }
+        private Object invoke_L7(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) throws Throwable {
+            if (test.<boolean>invoke(a0, a1, a2, a3, a4, a5, a6))
+                return target.<Object>invoke(a0, a1, a2, a3, a4, a5, a6);
+            return fallback.<Object>invoke(a0, a1, a2, a3, a4, a5, a6);
+        }
+        private Object invoke_L8(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) throws Throwable {
+            if (test.<boolean>invoke(a0, a1, a2, a3, a4, a5, a6, a7))
+                return target.<Object>invoke(a0, a1, a2, a3, a4, a5, a6, a7);
+            return fallback.<Object>invoke(a0, a1, a2, a3, a4, a5, a6, a7);
+        }
+        static MethodHandle[] makeInvokes() {
+            ArrayList<MethodHandle> invokes = new ArrayList<MethodHandle>();
+            MethodHandles.Lookup lookup = IMPL_LOOKUP;
+            for (;;) {
+                int nargs = invokes.size();
+                String name = "invoke_L"+nargs;
+                MethodHandle invoke = null;
+                try {
+                    invoke = lookup.findVirtual(GuardWithTest.class, name, MethodType.genericMethodType(nargs));
+                } catch (NoAccessException ex) {
+                }
+                if (invoke == null)  break;
+                invokes.add(invoke);
+            }
+            assert(invokes.size() == 9);  // current number of methods
+            return invokes.toArray(new MethodHandle[0]);
+        };
+        static final MethodHandle[] INVOKES = makeInvokes();
+        // For testing use this:
+        //static final MethodHandle[] INVOKES = Arrays.copyOf(makeInvokes(), 2);
+        static final MethodHandle VARARGS_INVOKE;
+        static {
+            try {
+                VARARGS_INVOKE = IMPL_LOOKUP.findVirtual(GuardWithTest.class, "invoke_V", MethodType.genericMethodType(0, true));
+            } catch (NoAccessException ex) {
+                throw new InternalError("");
+            }
+        }
+    }
+
     public static
     MethodHandle makeGuardWithTest(Access token,
-                                   final MethodHandle test,
-                                   final MethodHandle target,
-                                   final MethodHandle fallback) {
+                                   MethodHandle test,
+                                   MethodHandle target,
+                                   MethodHandle fallback) {
         Access.check(token);
-        // %%% This is just a sketch.  It needs to be de-boxed.
-        // Adjust the handles to accept varargs lists.
         MethodType type = target.type();
-        Class<?>  rtype = type.returnType();
-        if (type.parameterCount() != 1 || type.parameterType(0).isPrimitive()) {
-            MethodType vatestType   = MethodType.make(boolean.class, Object[].class);
-            MethodType vatargetType = MethodType.make(rtype, Object[].class);
-            MethodHandle vaguard = makeGuardWithTest(token,
-                    MethodHandles.spreadArguments(test, vatestType),
-                    MethodHandles.spreadArguments(target, vatargetType),
-                    MethodHandles.spreadArguments(fallback, vatargetType));
-            return MethodHandles.collectArguments(vaguard, type);
+        int nargs = type.parameterCount();
+        if (nargs < GuardWithTest.INVOKES.length) {
+            MethodType gtype = type.generic();
+            MethodHandle gtest = convertArguments(token, test, gtype.changeReturnType(boolean.class), test.type(), null);
+            MethodHandle gtarget = convertArguments(token, target, gtype, type, null);
+            MethodHandle gfallback = convertArguments(token, fallback, gtype, type, null);
+            if (gtest == null || gtarget == null || gfallback == null)  return null;
+            MethodHandle gguard = new GuardWithTest(gtest, gtarget, gfallback);
+            return convertArguments(token, gguard, type, gtype, null);
+        } else {
+            MethodType gtype = MethodType.genericMethodType(0, true);
+            MethodHandle gtest = spreadArguments(token, test, gtype.changeReturnType(boolean.class), 0);
+            MethodHandle gtarget = spreadArguments(token, target, gtype, 0);
+            MethodHandle gfallback = spreadArguments(token, fallback, gtype, 0);
+            MethodHandle gguard = new GuardWithTest(GuardWithTest.VARARGS_INVOKE, gtest, gtarget, gfallback);
+            if (gtest == null || gtarget == null || gfallback == null)  return null;
+            return collectArguments(token, gguard, type, 0, null);
+        }
+    }
+
+    private static class GuardWithCatch extends JavaMethodHandle {
+        private final MethodHandle target;
+        private final Class<? extends Throwable> exType;
+        private final MethodHandle catcher;
+        public GuardWithCatch(MethodHandle target, Class<? extends Throwable> exType, MethodHandle catcher) {
+            this(INVOKES[target.type().parameterCount()], target, exType, catcher);
+        }
+        public GuardWithCatch(MethodHandle invoker,
+                              MethodHandle target, Class<? extends Throwable> exType, MethodHandle catcher) {
+            super(invoker);
+            this.target = target;
+            this.exType = exType;
+            this.catcher = catcher;
         }
-        if (rtype.isPrimitive()) {
-            MethodType boxtype = type.changeReturnType(Object.class);
-            MethodHandle boxguard = makeGuardWithTest(token,
-                    test,
-                    MethodHandles.convertArguments(target, boxtype),
-                    MethodHandles.convertArguments(fallback, boxtype));
-            return MethodHandles.convertArguments(boxguard, type);
+        @Override
+        public String toString() {
+            return target.toString();
+        }
+        private Object invoke_V(Object... av) throws Throwable {
+            try {
+                return target.<Object>invoke(av);
+            } catch (Throwable t) {
+                if (!exType.isInstance(t))  throw t;
+                return catcher.<Object>invoke(t, av);
+            }
+        }
+        private Object invoke_L0() throws Throwable {
+            try {
+                return target.<Object>invoke();
+            } catch (Throwable t) {
+                if (!exType.isInstance(t))  throw t;
+                return catcher.<Object>invoke(t);
+            }
         }
-        // Got here?  Reduced calling sequence to Object(Object).
-        class Guarder {
-            Object invoke(Object x) {
-                // If javac supports MethodHandle.invoke directly:
-                //z = vatest.invoke<boolean>(arguments);
-                // If javac does not support direct MH.invoke calls:
-                boolean z = (Boolean) MethodHandles.invoke_1(test, x);
-                MethodHandle mh = (z ? target : fallback);
-                return MethodHandles.invoke_1(mh, x);
+        private Object invoke_L1(Object a0) throws Throwable {
+            try {
+                return target.<Object>invoke(a0);
+            } catch (Throwable t) {
+                if (!exType.isInstance(t))  throw t;
+                return catcher.<Object>invoke(t, a0);
             }
-            MethodHandle handle() {
-                MethodType invokeType = MethodType.makeGeneric(0, true);
-                MethodHandle vh = IMPL_LOOKUP.bind(this, "invoke", invokeType);
-                return MethodHandles.collectArguments(vh, target.type());
+        }
+        private Object invoke_L2(Object a0, Object a1) throws Throwable {
+            try {
+                return target.<Object>invoke(a0, a1);
+            } catch (Throwable t) {
+                if (!exType.isInstance(t))  throw t;
+                return catcher.<Object>invoke(t, a0, a1);
+            }
+        }
+        private Object invoke_L3(Object a0, Object a1, Object a2) throws Throwable {
+            try {
+                return target.<Object>invoke(a0, a1, a2);
+            } catch (Throwable t) {
+                if (!exType.isInstance(t))  throw t;
+                return catcher.<Object>invoke(t, a0, a1, a2);
             }
         }
-        return new Guarder().handle();
+        private Object invoke_L4(Object a0, Object a1, Object a2, Object a3) throws Throwable {
+            try {
+                return target.<Object>invoke(a0, a1, a2, a3);
+            } catch (Throwable t) {
+                if (!exType.isInstance(t))  throw t;
+                return catcher.<Object>invoke(t, a0, a1, a2, a3);
+            }
+        }
+        private Object invoke_L5(Object a0, Object a1, Object a2, Object a3, Object a4) throws Throwable {
+            try {
+                return target.<Object>invoke(a0, a1, a2, a3, a4);
+            } catch (Throwable t) {
+                if (!exType.isInstance(t))  throw t;
+                return catcher.<Object>invoke(t, a0, a1, a2, a3, a4);
+            }
+        }
+        private Object invoke_L6(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) throws Throwable {
+            try {
+                return target.<Object>invoke(a0, a1, a2, a3, a4, a5);
+            } catch (Throwable t) {
+                if (!exType.isInstance(t))  throw t;
+                return catcher.<Object>invoke(t, a0, a1, a2, a3, a4, a5);
+            }
+        }
+        private Object invoke_L7(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) throws Throwable {
+            try {
+                return target.<Object>invoke(a0, a1, a2, a3, a4, a5, a6);
+            } catch (Throwable t) {
+                if (!exType.isInstance(t))  throw t;
+                return catcher.<Object>invoke(t, a0, a1, a2, a3, a4, a5, a6);
+            }
+        }
+        private Object invoke_L8(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) throws Throwable {
+            try {
+                return target.<Object>invoke(a0, a1, a2, a3, a4, a5, a6, a7);
+            } catch (Throwable t) {
+                if (!exType.isInstance(t))  throw t;
+                return catcher.<Object>invoke(t, a0, a1, a2, a3, a4, a5, a6, a7);
+            }
+        }
+        static MethodHandle[] makeInvokes() {
+            ArrayList<MethodHandle> invokes = new ArrayList<MethodHandle>();
+            MethodHandles.Lookup lookup = IMPL_LOOKUP;
+            for (;;) {
+                int nargs = invokes.size();
+                String name = "invoke_L"+nargs;
+                MethodHandle invoke = null;
+                try {
+                    invoke = lookup.findVirtual(GuardWithCatch.class, name, MethodType.genericMethodType(nargs));
+                } catch (NoAccessException ex) {
+                }
+                if (invoke == null)  break;
+                invokes.add(invoke);
+            }
+            assert(invokes.size() == 9);  // current number of methods
+            return invokes.toArray(new MethodHandle[0]);
+        };
+        static final MethodHandle[] INVOKES = makeInvokes();
+        // For testing use this:
+        //static final MethodHandle[] INVOKES = Arrays.copyOf(makeInvokes(), 2);
+        static final MethodHandle VARARGS_INVOKE;
+        static {
+            try {
+                VARARGS_INVOKE = IMPL_LOOKUP.findVirtual(GuardWithCatch.class, "invoke_V", MethodType.genericMethodType(0, true));
+            } catch (NoAccessException ex) {
+                throw new InternalError("");
+            }
+        }
+    }
+
+
+    public static
+    MethodHandle makeGuardWithCatch(Access token,
+                                    MethodHandle target,
+                                    Class<? extends Throwable> exType,
+                                    MethodHandle catcher) {
+        Access.check(token);
+        MethodType type = target.type();
+        MethodType ctype = catcher.type();
+        int nargs = type.parameterCount();
+        if (nargs < GuardWithCatch.INVOKES.length) {
+            MethodType gtype = type.generic();
+            MethodType gcatchType = gtype.insertParameterTypes(0, Throwable.class);
+            MethodHandle gtarget = convertArguments(token, target, gtype, type, null);
+            MethodHandle gcatcher = convertArguments(token, catcher, gcatchType, ctype, null);
+            MethodHandle gguard = new GuardWithCatch(gtarget, exType, gcatcher);
+            if (gtarget == null || gcatcher == null || gguard == null)  return null;
+            return convertArguments(token, gguard, type, gtype, null);
+        } else {
+            MethodType gtype = MethodType.genericMethodType(0, true);
+            MethodType gcatchType = gtype.insertParameterTypes(0, Throwable.class);
+            MethodHandle gtarget = spreadArguments(token, target, gtype, 0);
+            MethodHandle gcatcher = spreadArguments(token, catcher, gcatchType, 1);
+            MethodHandle gguard = new GuardWithCatch(GuardWithCatch.VARARGS_INVOKE, gtarget, exType, gcatcher);
+            if (gtarget == null || gcatcher == null || gguard == null)  return null;
+            return collectArguments(token, gguard, type, 0, null);
+        }
     }
 
     public static
-    MethodHandle combineArguments(Access token, MethodHandle target, MethodHandle checker, int pos) {
+    MethodHandle throwException(Access token, MethodType type) {
         Access.check(token);
-        throw new UnsupportedOperationException("Not yet implemented");
+        return AdapterMethodHandle.makeRetypeRaw(token, type, THROW_EXCEPTION);
     }
 
-    protected static String basicToString(MethodHandle target) {
+    static final MethodHandle THROW_EXCEPTION
+            = IMPL_LOOKUP.findStatic(MethodHandleImpl.class, "throwException",
+                    MethodType.methodType(Empty.class, Throwable.class));
+    static <T extends Throwable> Empty throwException(T t) throws T { throw t; }
+
+    public static String getNameString(Access token, MethodHandle target) {
+        Access.check(token);
         MemberName name = null;
         if (target != null)
             name = MethodHandleNatives.getMethodName(target);
@@ -357,17 +1080,30 @@
         return name.getName();
     }
 
-    protected static String addTypeString(MethodHandle target, String name) {
-        if (target == null)  return name;
-        return name+target.type();
+    public static String addTypeString(MethodHandle target) {
+        if (target == null)  return "null";
+        return target.toString() + target.type();
     }
-    static RuntimeException newIllegalArgumentException(String string) {
-        return new IllegalArgumentException(string);
+
+    public static void checkSpreadArgument(Object av, int n) {
+        if (av == null ? n != 0 : ((Object[])av).length != n)
+            throw newIllegalArgumentException("Array is not of length "+n);
     }
 
-    @Override
-    public String toString() {
-        MethodHandle self = (MethodHandle) this;
-        return addTypeString(self, basicToString(self));
+    public static void raiseException(int code, Object actual, Object required) {
+        String message;
+        // disregard the identity of the actual object, if it is not a class:
+        if (!(actual instanceof Class) && !(actual instanceof MethodType))
+            actual = actual.getClass();
+        if (actual != null)
+            message = "required "+required+" but encountered "+actual;
+        else
+            message = "required "+required;
+        switch (code) {
+        case 192: // checkcast
+            throw new ClassCastException(message);
+        default:
+            throw new InternalError("unexpected code "+code+": "+message);
+        }
     }
 }
--- a/jdk/src/share/classes/sun/dyn/MethodHandleNatives.java	Thu Dec 17 14:10:20 2009 -0800
+++ b/jdk/src/share/classes/sun/dyn/MethodHandleNatives.java	Wed Jul 05 17:04:56 2017 +0200
@@ -25,6 +25,7 @@
 
 package sun.dyn;
 
+import java.dyn.CallSite;
 import java.dyn.MethodHandle;
 import java.dyn.MethodType;
 import java.lang.reflect.AccessibleObject;
@@ -60,7 +61,7 @@
     static native void init(MethodType self);
 
     /** Tell the JVM that we need to change the target of an invokedynamic. */
-    static native void linkCallSite(CallSiteImpl site, MethodHandle target);
+    static native void linkCallSite(CallSite site, MethodHandle target);
 
     /** Fetch the vmtarget field.
      *  It will be sanitized as necessary to avoid exposing non-Java references.
@@ -84,8 +85,7 @@
     }
 
     /** Fetch the target of this method handle.
-     *  If it directly targets a method, return a tuple of method info.
-     *  The info is of the form new Object[]{defclass, name, sig, refclass}.
+     *  If it directly targets a method, return a MemberName for the method.
      *  If it is chained to another method handle, return that handle.
      */
     static Object getTargetInfo(MethodHandle self) {
@@ -123,7 +123,7 @@
             registerNatives();
             JVM_SUPPORT_ = true;
             JVM_PUSH_LIMIT_ = getConstant(Constants.GC_JVM_PUSH_LIMIT);
-            JVM_STACK_MOVE_UNIT_ = getConstant(Constants.GC_JVM_STACK_MOVE_LIMIT);
+            JVM_STACK_MOVE_UNIT_ = getConstant(Constants.GC_JVM_STACK_MOVE_UNIT);
             //sun.reflect.Reflection.registerMethodsToFilter(MethodHandleImpl.class, "init");
         } catch (UnsatisfiedLinkError ee) {
             // ignore; if we use init() methods later we'll see linkage errors
@@ -149,7 +149,7 @@
         // MethodHandleImpl
         static final int // for getConstant
                 GC_JVM_PUSH_LIMIT = 0,
-                GC_JVM_STACK_MOVE_LIMIT = 1;
+                GC_JVM_STACK_MOVE_UNIT = 1;
         static final int
                 ETF_HANDLE_OR_METHOD_NAME = 0, // all available data (immediate MH or method)
                 ETF_DIRECT_HANDLE         = 1, // ultimate method handle (will be a DMH, may be self)
@@ -178,19 +178,20 @@
          */
         static final int
             OP_RETYPE_ONLY   = 0x0, // no argument changes; straight retype
-            OP_CHECK_CAST    = 0x1, // ref-to-ref conversion; requires a Class argument
-            OP_PRIM_TO_PRIM  = 0x2, // converts from one primitive to another
-            OP_REF_TO_PRIM   = 0x3, // unboxes a wrapper to produce a primitive
-            OP_PRIM_TO_REF   = 0x4, // boxes a primitive into a wrapper (NYI)
-            OP_SWAP_ARGS     = 0x5, // swap arguments (vminfo is 2nd arg)
-            OP_ROT_ARGS      = 0x6, // rotate arguments (vminfo is displaced arg)
-            OP_DUP_ARGS      = 0x7, // duplicates one or more arguments (at TOS)
-            OP_DROP_ARGS     = 0x8, // remove one or more argument slots
-            OP_COLLECT_ARGS  = 0x9, // combine one or more arguments into a varargs (NYI)
-            OP_SPREAD_ARGS   = 0xA, // expand in place a varargs array (of known size)
-            OP_FLYBY         = 0xB, // operate first on reified argument list (NYI)
-            OP_RICOCHET      = 0xC, // run an adapter chain on the return value (NYI)
-            CONV_OP_LIMIT    = 0xD; // limit of CONV_OP enumeration
+            OP_RETYPE_RAW    = 0x1, // no argument changes; straight retype
+            OP_CHECK_CAST    = 0x2, // ref-to-ref conversion; requires a Class argument
+            OP_PRIM_TO_PRIM  = 0x3, // converts from one primitive to another
+            OP_REF_TO_PRIM   = 0x4, // unboxes a wrapper to produce a primitive
+            OP_PRIM_TO_REF   = 0x5, // boxes a primitive into a wrapper (NYI)
+            OP_SWAP_ARGS     = 0x6, // swap arguments (vminfo is 2nd arg)
+            OP_ROT_ARGS      = 0x7, // rotate arguments (vminfo is displaced arg)
+            OP_DUP_ARGS      = 0x8, // duplicates one or more arguments (at TOS)
+            OP_DROP_ARGS     = 0x9, // remove one or more argument slots
+            OP_COLLECT_ARGS  = 0xA, // combine one or more arguments into a varargs (NYI)
+            OP_SPREAD_ARGS   = 0xB, // expand in place a varargs array (of known size)
+            OP_FLYBY         = 0xC, // operate first on reified argument list (NYI)
+            OP_RICOCHET      = 0xD, // run an adapter chain on the return value (NYI)
+            CONV_OP_LIMIT    = 0xE; // limit of CONV_OP enumeration
         /** Shift and mask values for decoding the AMH.conversion field.
          *  These numbers are shared with the JVM for creating AMHs.
          */
@@ -209,6 +210,7 @@
                 // TODO: The following expression should be replaced by
                 // a JVM query.
                 ((1<<OP_RETYPE_ONLY)
+                |(1<<OP_RETYPE_RAW)
                 |(1<<OP_CHECK_CAST)
                 |(1<<OP_PRIM_TO_PRIM)
                 |(1<<OP_REF_TO_PRIM)
@@ -216,6 +218,7 @@
                 |(1<<OP_ROT_ARGS)
                 |(1<<OP_DUP_ARGS)
                 |(1<<OP_DROP_ARGS)
+                //|(1<<OP_SPREAD_ARGS) // FIXME: Check JVM assembly code.
                 );
 
         /**
--- a/jdk/src/share/classes/sun/dyn/MethodTypeImpl.java	Thu Dec 17 14:10:20 2009 -0800
+++ b/jdk/src/share/classes/sun/dyn/MethodTypeImpl.java	Wed Jul 05 17:04:56 2017 +0200
@@ -27,6 +27,7 @@
 
 import java.dyn.*;
 import sun.dyn.util.Wrapper;
+import static sun.dyn.MemberName.newIllegalArgumentException;
 
 /**
  * Shared information for a group of method types, which differ
@@ -56,8 +57,8 @@
     // Cached adapter information:
     /*lazy*/ ToGeneric   toGeneric;     // convert cs. with prims to w/o
     /*lazy*/ FromGeneric fromGeneric;   // convert cs. w/o prims to with
+    /*lazy*/ SpreadGeneric[] spreadGeneric; // expand one argument to many
     /*lazy*/ FilterGeneric filterGeneric; // convert argument(s) on the fly
-    ///*lazy*/ Invokers    invokers;    // cache of handy higher-order adapters
 
     public MethodType erasedType() {
         return erasedType;
@@ -68,7 +69,7 @@
     }
 
     /** Access methods for the internals of MethodType, supplied to
-     *  MethodTypeForm as a trusted agent.
+     *  MethodTypeImpl as a trusted agent.
      */
     static public interface MethodTypeFriend {
         Class<?>[]     ptypes(MethodType mt);
@@ -150,7 +151,7 @@
         this.argToSlotTable = argToSlotTab;
         this.slotToArgTable = slotToArgTab;
 
-        if (pslotCount >= 256)  throw new IllegalArgumentException("too many arguments");
+        if (pslotCount >= 256)  throw newIllegalArgumentException("too many arguments");
 
         // send a few bits down to the JVM:
         this.vmslots = parameterSlotCount();
@@ -378,10 +379,10 @@
     static MethodTypeImpl findForm(MethodType mt) {
         MethodType erased = canonicalize(mt, ERASE, ERASE);
         if (erased == null) {
-            // It is already erased.  Make a new MethodTypeForm.
+            // It is already erased.  Make a new MethodTypeImpl.
             return METHOD_TYPE_FRIEND.newMethodTypeForm(mt);
         } else {
-            // Share the MethodTypeForm with the erased version.
+            // Share the MethodTypeImpl with the erased version.
             return METHOD_TYPE_FRIEND.form(erased);
         }
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/sun/dyn/SpreadGeneric.java	Wed Jul 05 17:04:56 2017 +0200
@@ -0,0 +1,682 @@
+/*
+ * Copyright 2008-2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * 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.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package sun.dyn;
+
+import java.dyn.JavaMethodHandle;
+import java.dyn.MethodHandle;
+import java.dyn.MethodHandles;
+import java.dyn.MethodType;
+import java.dyn.NoAccessException;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.util.ArrayList;
+import sun.dyn.util.ValueConversions;
+import static sun.dyn.MemberName.newIllegalArgumentException;
+
+/**
+ * Generic spread adapter.
+ * Expands a final argument into multiple (zero or more) arguments, keeping the others the same.
+ * @author jrose
+ */
+class SpreadGeneric {
+    // type for the outgoing call
+    private final MethodType targetType;
+    // number of arguments to spread
+    private final int spreadCount;
+    // prototype adapter (clone and customize for each new target!)
+    private final Adapter adapter;
+    // entry point for adapter (Adapter mh, a...) => ...
+    private final MethodHandle entryPoint;
+
+    /** Compute and cache information common to all spreading adapters
+     *  that accept calls of the given (generic) type.
+     */
+    private SpreadGeneric(MethodType targetType, int spreadCount) {
+        assert(targetType == targetType.generic());
+        this.targetType = targetType;
+        this.spreadCount = spreadCount;
+        // the target invoker will generally need casts on reference arguments
+        MethodHandle[] ep = { null };
+        Adapter ad = findAdapter(this, ep);
+        if (ad != null) {
+            this.adapter = ad;
+            this.entryPoint = ep[0];
+            return;
+        }
+        this.adapter = buildAdapterFromBytecodes(targetType, spreadCount, ep);
+        this.entryPoint = ep[0];
+    }
+
+    /** From targetType remove the last spreadCount arguments, and instead
+     *  append a simple Object argument.
+     */
+    static MethodType preSpreadType(MethodType targetType, int spreadCount) {
+        @SuppressWarnings("unchecked")
+        ArrayList<Class<?>> params = new ArrayList(targetType.parameterList());
+        int outargs = params.size();
+        params.subList(outargs - spreadCount, outargs).clear();
+        params.add(Object.class);
+        return MethodType.methodType(targetType.returnType(), params);
+    }
+
+    MethodHandle makeInstance(MethodHandle target) {
+        MethodType type = target.type();
+        if (type != targetType) {
+            throw new UnsupportedOperationException("NYI type="+type);
+        }
+        return adapter.makeInstance(this, target);
+    }
+
+    /** Build an adapter of the given generic type, which invokes typedTarget
+     *  on the incoming arguments, after unboxing as necessary.
+     *  The return value is boxed if necessary.
+     * @param genericType  the required type of the result
+     * @param typedTarget the target
+     * @return an adapter method handle
+     */
+    public static MethodHandle make(MethodHandle target, int spreadCount) {
+        MethodType type = target.type();
+        MethodType gtype = type.generic();
+        if (type == gtype) {
+            return SpreadGeneric.of(type, spreadCount).makeInstance(target);
+        } else {
+            MethodHandle gtarget = FromGeneric.make(target);
+            assert(gtarget.type() == gtype);
+            MethodHandle gspread = SpreadGeneric.of(gtype, spreadCount).makeInstance(gtarget);
+            return ToGeneric.make(preSpreadType(type, spreadCount), gspread);
+        }
+    }
+
+    /** Return the adapter information for this type's erasure. */
+    static SpreadGeneric of(MethodType targetType, int spreadCount) {
+        if (targetType != targetType.generic())
+            throw new UnsupportedOperationException("NYI type="+targetType);
+        MethodTypeImpl form = MethodTypeImpl.of(targetType);
+        int outcount = form.parameterCount();
+        assert(spreadCount <= outcount);
+        SpreadGeneric[] spreadGens = form.spreadGeneric;
+        if (spreadGens == null)
+            form.spreadGeneric = spreadGens = new SpreadGeneric[outcount+1];
+        SpreadGeneric spreadGen = spreadGens[spreadCount];
+        if (spreadGen == null)
+            spreadGens[spreadCount] = spreadGen = new SpreadGeneric(form.erasedType(), spreadCount);
+        return spreadGen;
+    }
+
+    public String toString() {
+        return getClass().getSimpleName()+targetType+"["+spreadCount+"]";
+    }
+
+    // This mini-api is called from an Adapter to manage the spread.
+    /** A check/coercion that happens once before any selections. */
+    protected Object check(Object av, int n) {
+        MethodHandleImpl.checkSpreadArgument(av, n);
+        return av;
+    }
+
+    /** The selection operator for spreading; note that it takes Object not Object[]. */
+    protected Object select(Object av, int n) {
+        return ((Object[])av)[n];
+    }
+    /*
+    protected int select_I(Object av, int n) {
+        // maybe return ((int[])select)[n]
+        throw new UnsupportedOperationException("subclass resp.");
+    }
+    protected int select_J(Object av, int n) {
+        // maybe return ((long[])select)[n]
+        throw new UnsupportedOperationException("subclass resp.");
+    }
+    // */
+
+    /* Create an adapter that handles spreading calls for the given type. */
+    static Adapter findAdapter(SpreadGeneric outer, MethodHandle[] ep) {
+        MethodType targetType = outer.targetType;
+        int spreadCount = outer.spreadCount;
+        int outargs = targetType.parameterCount();
+        int inargs = outargs - spreadCount;
+        if (inargs < 0)  return null;
+        MethodType entryType = MethodType.genericMethodType(inargs + 1); // 1 for av
+        String cname1 = "S" + outargs;
+        String[] cnames = { cname1 };
+        String iname = "invoke_S"+spreadCount;
+        // e.g., D5I2, D5, L5I2, L5; invoke_D5
+        for (String cname : cnames) {
+            Class<? extends Adapter> acls = Adapter.findSubClass(cname);
+            if (acls == null)  continue;
+            // see if it has the required invoke method
+            MethodHandle entryPoint = null;
+            try {
+                entryPoint = MethodHandleImpl.IMPL_LOOKUP.findSpecial(acls, iname, entryType, acls);
+            } catch (NoAccessException ex) {
+            }
+            if (entryPoint == null)  continue;
+            Constructor<? extends Adapter> ctor = null;
+            try {
+                ctor = acls.getDeclaredConstructor(SpreadGeneric.class);
+            } catch (NoSuchMethodException ex) {
+            } catch (SecurityException ex) {
+            }
+            if (ctor == null)  continue;
+            try {
+                // Produce an instance configured as a prototype.
+                Adapter ad = ctor.newInstance(outer);
+                ep[0] = entryPoint;
+                return ad;
+            } catch (IllegalArgumentException ex) {
+            } catch (InvocationTargetException wex) {
+                Throwable ex = wex.getTargetException();
+                if (ex instanceof Error)  throw (Error)ex;
+                if (ex instanceof RuntimeException)  throw (RuntimeException)ex;
+            } catch (InstantiationException ex) {
+            } catch (IllegalAccessException ex) {
+            }
+        }
+        return null;
+    }
+
+    static Adapter buildAdapterFromBytecodes(MethodType targetType,
+            int spreadCount, MethodHandle[] ep) {
+        throw new UnsupportedOperationException("NYI");
+    }
+
+    /**
+     * This adapter takes some untyped arguments, and returns an untyped result.
+     * Internally, it applies the invoker to the target, which causes the
+     * objects to be unboxed; the result is a raw type in L/I/J/F/D.
+     * This result is passed to convert, which is responsible for
+     * converting the raw result into a boxed object.
+     * The invoker is kept separate from the target because it can be
+     * generated once per type erasure family, and reused across adapters.
+     */
+    static abstract class Adapter extends JavaMethodHandle {
+        /*
+         * class X<<R,int M,int N>> extends Adapter {
+         *   (Object**N)=>R target;
+         *   static int S = N-M;
+         *   Object invoke(Object**M a, Object v) = target(a..., v[0]...v[S-1]);
+         * }
+         */
+        protected final SpreadGeneric outer;
+        protected final MethodHandle target;   // (any**N) => R
+
+        @Override
+        public String toString() {
+            return target.toString();
+        }
+
+        static final MethodHandle NO_ENTRY = ValueConversions.identity();
+
+        protected boolean isPrototype() { return target == null; }
+        protected Adapter(SpreadGeneric outer) {
+            super(NO_ENTRY);
+            this.outer = outer;
+            this.target = null;
+            assert(isPrototype());
+        }
+
+        protected Adapter(SpreadGeneric outer, MethodHandle target) {
+            super(outer.entryPoint);
+            this.outer = outer;
+            this.target = target;
+        }
+
+        /** Make a copy of self, with new fields. */
+        protected abstract Adapter makeInstance(SpreadGeneric outer, MethodHandle target);
+        // { return new ThisType(outer, target); }
+
+        protected Object check(Object av, int n) {
+            return outer.check(av, n);
+        }
+        protected Object select(Object av, int n) {
+            return outer.select(av, n);
+        }
+
+        static private final String CLASS_PREFIX; // "sun.dyn.SpreadGeneric$"
+        static {
+            String aname = Adapter.class.getName();
+            String sname = Adapter.class.getSimpleName();
+            if (!aname.endsWith(sname))  throw new InternalError();
+            CLASS_PREFIX = aname.substring(0, aname.length() - sname.length());
+        }
+        /** Find a sibing class of Adapter. */
+        static Class<? extends Adapter> findSubClass(String name) {
+            String cname = Adapter.CLASS_PREFIX + name;
+            try {
+                return Class.forName(cname).asSubclass(Adapter.class);
+            } catch (ClassNotFoundException ex) {
+                return null;
+            } catch (ClassCastException ex) {
+                return null;
+            }
+        }
+    }
+
+    /* generated classes follow this pattern:
+    static class xS2 extends Adapter {
+        protected xS2(SpreadGeneric outer) { super(outer); }  // to build prototype
+        protected xS2(SpreadGeneric outer, MethodHandle t) { super(outer, t); }
+        protected xS2 makeInstance(SpreadGeneric outer, MethodHandle t) { return new xS2(outer, t); }
+        protected Object invoke_S0(Object a0, Object a1, Object av) throws Throwable { av = super.check(av,0);
+             return target.<Object>invoke(a0, a1)); }
+        protected Object invoke_S1(Object a0, Object av) throws Throwable { av = super.check(av,1);
+             return target.<Object>invoke(a0,
+                super.select(av,0)); }
+        protected Object invoke_S2(Object a0, Object av) throws Throwable { av = super.check(av,1);
+             return target.<Object>invoke(
+                super.select(av,0), super.select(av,1)); }
+    }
+    // */
+
+/*
+: SHELL; n=SpreadGeneric; cp -p $n.java $n.java-; sed < $n.java- > $n.java+ -e '/{{*{{/,/}}*}}/w /tmp/genclasses.java' -e '/}}*}}/q'; (cd /tmp; javac -d . genclasses.java; java -cp . genclasses) >> $n.java+; echo '}' >> $n.java+; mv $n.java+ $n.java; mv $n.java- $n.java~
+//{{{
+import java.util.*;
+class genclasses {
+    static String[][] TEMPLATES = { {
+        "@for@ N=0..10",
+        "    //@each-cat@",
+        "    static class @cat@ extends Adapter {",
+        "        protected @cat@(SpreadGeneric outer) { super(outer); }  // to build prototype",
+        "        protected @cat@(SpreadGeneric outer, MethodHandle t) { super(outer, t); }",
+        "        protected @cat@ makeInstance(SpreadGeneric outer, MethodHandle t) { return new @cat@(outer, t); }",
+        "        protected Object invoke_S0(@Tvav,@Object av) throws Throwable { av = super.check(av, 0);",
+        "            return target.<Object>invoke(@av@); }",
+        "        //@each-S@",
+        "        protected Object invoke_S@S@(@Tvav,@Object av) throws Throwable { av = super.check(av, @S@);",
+        "            return target.<Object>invoke(@av,@@sv@); }",
+        "        //@end-S@",
+        "    }",
+    } };
+    static final String NEWLINE_INDENT = "\n                ";
+    enum VAR {
+        cat, N, S, av, av_, Tvav_, sv;
+        public final String pattern = "@"+toString().replace('_','.')+"@";
+        public String binding = toString();
+        static void makeBindings(boolean topLevel, int outargs, int spread) {
+            int inargs = outargs - spread;
+            VAR.cat.binding = "S"+outargs;
+            VAR.N.binding = String.valueOf(outargs); // outgoing arg count
+            VAR.S.binding = String.valueOf(spread);  // spread count
+            String[] av = new String[inargs];
+            String[] Tvav = new String[inargs];
+            for (int i = 0; i < inargs; i++) {
+                av[i] = arg(i);
+                Tvav[i] = param("Object", av[i]);
+            }
+            VAR.av.binding = comma(av);
+            VAR.av_.binding = comma(av, ", ");
+            VAR.Tvav_.binding = comma(Tvav, ", ");
+            String[] sv = new String[spread];
+            for (int i = 0; i < spread; i++) {
+                String spc = "";
+                if (i % 4 == 0) spc = NEWLINE_INDENT;
+                sv[i] = spc+"super.select(av,"+i+")";
+            }
+            VAR.sv.binding = comma(sv);
+        }
+        static String arg(int i) { return "a"+i; }
+        static String param(String t, String a) { return t+" "+a; }
+        static String comma(String[] v) { return comma(v, ""); }
+        static String comma(String[] v, String sep) {
+            if (v.length == 0)  return "";
+            String res = v[0];
+            for (int i = 1; i < v.length; i++)  res += ", "+v[i];
+            return res + sep;
+        }
+        static String transform(String string) {
+            for (VAR var : values())
+                string = string.replaceAll(var.pattern, var.binding);
+            return string;
+        }
+    }
+    static String[] stringsIn(String[] strings, int beg, int end) {
+        return Arrays.copyOfRange(strings, beg, Math.min(end, strings.length));
+    }
+    static String[] stringsBefore(String[] strings, int pos) {
+        return stringsIn(strings, 0, pos);
+    }
+    static String[] stringsAfter(String[] strings, int pos) {
+        return stringsIn(strings, pos, strings.length);
+    }
+    static int indexAfter(String[] strings, int pos, String tag) {
+        return Math.min(indexBefore(strings, pos, tag) + 1, strings.length);
+    }
+    static int indexBefore(String[] strings, int pos, String tag) {
+        for (int i = pos, end = strings.length; ; i++) {
+            if (i == end || strings[i].endsWith(tag))  return i;
+        }
+    }
+    static int MIN_ARITY, MAX_ARITY;
+    public static void main(String... av) {
+        for (String[] template : TEMPLATES) {
+            int forLinesLimit = indexBefore(template, 0, "@each-cat@");
+            String[] forLines = stringsBefore(template, forLinesLimit);
+            template = stringsAfter(template, forLinesLimit);
+            for (String forLine : forLines)
+                expandTemplate(forLine, template);
+        }
+    }
+    static void expandTemplate(String forLine, String[] template) {
+        String[] params = forLine.split("[^0-9]+");
+        if (params[0].length() == 0)  params = stringsAfter(params, 1);
+        System.out.println("//params="+Arrays.asList(params));
+        int pcur = 0;
+        MIN_ARITY = Integer.valueOf(params[pcur++]);
+        MAX_ARITY = Integer.valueOf(params[pcur++]);
+        if (pcur != params.length)  throw new RuntimeException("bad extra param: "+forLine);
+        for (int outargs = MIN_ARITY; outargs <= MAX_ARITY; outargs++) {
+            expandTemplate(template, true, outargs, 0);
+        }
+    }
+    static void expandTemplate(String[] template, boolean topLevel, int outargs, int spread) {
+        VAR.makeBindings(topLevel, outargs, spread);
+        for (int i = 0; i < template.length; i++) {
+            String line = template[i];
+            if (line.endsWith("@each-cat@")) {
+                // ignore
+            } else if (line.endsWith("@each-S@")) {
+                int blockEnd = indexAfter(template, i, "@end-S@");
+                String[] block = stringsIn(template, i+1, blockEnd-1);
+                for (int spread1 = spread+1; spread1 <= outargs; spread1++)
+                    expandTemplate(block, false, outargs, spread1);
+                VAR.makeBindings(topLevel, outargs, spread);
+                i = blockEnd-1; continue;
+            } else {
+                System.out.println(VAR.transform(line));
+            }
+        }
+    }
+}
+//}}} */
+//params=[0, 10]
+    static class S0 extends Adapter {
+        protected S0(SpreadGeneric outer) { super(outer); }  // to build prototype
+        protected S0(SpreadGeneric outer, MethodHandle t) { super(outer, t); }
+        protected S0 makeInstance(SpreadGeneric outer, MethodHandle t) { return new S0(outer, t); }
+        protected Object invoke_S0(Object av) throws Throwable { av = super.check(av, 0);
+            return target.<Object>invoke(); }
+    }
+    static class S1 extends Adapter {
+        protected S1(SpreadGeneric outer) { super(outer); }  // to build prototype
+        protected S1(SpreadGeneric outer, MethodHandle t) { super(outer, t); }
+        protected S1 makeInstance(SpreadGeneric outer, MethodHandle t) { return new S1(outer, t); }
+        protected Object invoke_S0(Object a0, Object av) throws Throwable { av = super.check(av, 0);
+            return target.<Object>invoke(a0); }
+        protected Object invoke_S1(Object av) throws Throwable { av = super.check(av, 1);
+            return target.<Object>invoke(
+                super.select(av,0)); }
+    }
+    static class S2 extends Adapter {
+        protected S2(SpreadGeneric outer) { super(outer); }  // to build prototype
+        protected S2(SpreadGeneric outer, MethodHandle t) { super(outer, t); }
+        protected S2 makeInstance(SpreadGeneric outer, MethodHandle t) { return new S2(outer, t); }
+        protected Object invoke_S0(Object a0, Object a1, Object av) throws Throwable { av = super.check(av, 0);
+            return target.<Object>invoke(a0, a1); }
+        protected Object invoke_S1(Object a0, Object av) throws Throwable { av = super.check(av, 1);
+            return target.<Object>invoke(a0,
+                super.select(av,0)); }
+        protected Object invoke_S2(Object av) throws Throwable { av = super.check(av, 2);
+            return target.<Object>invoke(
+                super.select(av,0), super.select(av,1)); }
+    }
+    static class S3 extends Adapter {
+        protected S3(SpreadGeneric outer) { super(outer); }  // to build prototype
+        protected S3(SpreadGeneric outer, MethodHandle t) { super(outer, t); }
+        protected S3 makeInstance(SpreadGeneric outer, MethodHandle t) { return new S3(outer, t); }
+        protected Object invoke_S0(Object a0, Object a1, Object a2, Object av) throws Throwable { av = super.check(av, 0);
+            return target.<Object>invoke(a0, a1, a2); }
+        protected Object invoke_S1(Object a0, Object a1, Object av) throws Throwable { av = super.check(av, 1);
+            return target.<Object>invoke(a0, a1,
+                super.select(av,0)); }
+        protected Object invoke_S2(Object a0, Object av) throws Throwable { av = super.check(av, 2);
+            return target.<Object>invoke(a0,
+                super.select(av,0), super.select(av,1)); }
+        protected Object invoke_S3(Object av) throws Throwable { av = super.check(av, 3);
+            return target.<Object>invoke(
+                super.select(av,0), super.select(av,1), super.select(av,2)); }
+    }
+    static class S4 extends Adapter {
+        protected S4(SpreadGeneric outer) { super(outer); }  // to build prototype
+        protected S4(SpreadGeneric outer, MethodHandle t) { super(outer, t); }
+        protected S4 makeInstance(SpreadGeneric outer, MethodHandle t) { return new S4(outer, t); }
+        protected Object invoke_S0(Object a0, Object a1, Object a2, Object a3, Object av) throws Throwable { av = super.check(av, 0);
+            return target.<Object>invoke(a0, a1, a2, a3); }
+        protected Object invoke_S1(Object a0, Object a1, Object a2, Object av) throws Throwable { av = super.check(av, 1);
+            return target.<Object>invoke(a0, a1, a2,
+                super.select(av,0)); }
+        protected Object invoke_S2(Object a0, Object a1, Object av) throws Throwable { av = super.check(av, 2);
+            return target.<Object>invoke(a0, a1,
+                super.select(av,0), super.select(av,1)); }
+        protected Object invoke_S3(Object a0, Object av) throws Throwable { av = super.check(av, 3);
+            return target.<Object>invoke(a0,
+                super.select(av,0), super.select(av,1), super.select(av,2)); }
+        protected Object invoke_S4(Object av) throws Throwable { av = super.check(av, 4);
+            return target.<Object>invoke(
+                super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3)); }
+    }
+    static class S5 extends Adapter {
+        protected S5(SpreadGeneric outer) { super(outer); }  // to build prototype
+        protected S5(SpreadGeneric outer, MethodHandle t) { super(outer, t); }
+        protected S5 makeInstance(SpreadGeneric outer, MethodHandle t) { return new S5(outer, t); }
+        protected Object invoke_S0(Object a0, Object a1, Object a2, Object a3, Object a4, Object av) throws Throwable { av = super.check(av, 0);
+            return target.<Object>invoke(a0, a1, a2, a3, a4); }
+        protected Object invoke_S1(Object a0, Object a1, Object a2, Object a3, Object av) throws Throwable { av = super.check(av, 1);
+            return target.<Object>invoke(a0, a1, a2, a3,
+                super.select(av,0)); }
+        protected Object invoke_S2(Object a0, Object a1, Object a2, Object av) throws Throwable { av = super.check(av, 2);
+            return target.<Object>invoke(a0, a1, a2,
+                super.select(av,0), super.select(av,1)); }
+        protected Object invoke_S3(Object a0, Object a1, Object av) throws Throwable { av = super.check(av, 3);
+            return target.<Object>invoke(a0, a1,
+                super.select(av,0), super.select(av,1), super.select(av,2)); }
+        protected Object invoke_S4(Object a0, Object av) throws Throwable { av = super.check(av, 4);
+            return target.<Object>invoke(a0,
+                super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3)); }
+        protected Object invoke_S5(Object av) throws Throwable { av = super.check(av, 5);
+            return target.<Object>invoke(
+                super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3),
+                super.select(av,4)); }
+    }
+    static class S6 extends Adapter {
+        protected S6(SpreadGeneric outer) { super(outer); }  // to build prototype
+        protected S6(SpreadGeneric outer, MethodHandle t) { super(outer, t); }
+        protected S6 makeInstance(SpreadGeneric outer, MethodHandle t) { return new S6(outer, t); }
+        protected Object invoke_S0(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object av) throws Throwable { av = super.check(av, 0);
+            return target.<Object>invoke(a0, a1, a2, a3, a4, a5); }
+        protected Object invoke_S1(Object a0, Object a1, Object a2, Object a3, Object a4, Object av) throws Throwable { av = super.check(av, 1);
+            return target.<Object>invoke(a0, a1, a2, a3, a4,
+                super.select(av,0)); }
+        protected Object invoke_S2(Object a0, Object a1, Object a2, Object a3, Object av) throws Throwable { av = super.check(av, 2);
+            return target.<Object>invoke(a0, a1, a2, a3,
+                super.select(av,0), super.select(av,1)); }
+        protected Object invoke_S3(Object a0, Object a1, Object a2, Object av) throws Throwable { av = super.check(av, 3);
+            return target.<Object>invoke(a0, a1, a2,
+                super.select(av,0), super.select(av,1), super.select(av,2)); }
+        protected Object invoke_S4(Object a0, Object a1, Object av) throws Throwable { av = super.check(av, 4);
+            return target.<Object>invoke(a0, a1,
+                super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3)); }
+        protected Object invoke_S5(Object a0, Object av) throws Throwable { av = super.check(av, 5);
+            return target.<Object>invoke(a0,
+                super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3),
+                super.select(av,4)); }
+        protected Object invoke_S6(Object av) throws Throwable { av = super.check(av, 6);
+            return target.<Object>invoke(
+                super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3),
+                super.select(av,4), super.select(av,5)); }
+    }
+    static class S7 extends Adapter {
+        protected S7(SpreadGeneric outer) { super(outer); }  // to build prototype
+        protected S7(SpreadGeneric outer, MethodHandle t) { super(outer, t); }
+        protected S7 makeInstance(SpreadGeneric outer, MethodHandle t) { return new S7(outer, t); }
+        protected Object invoke_S0(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object av) throws Throwable { av = super.check(av, 0);
+            return target.<Object>invoke(a0, a1, a2, a3, a4, a5, a6); }
+        protected Object invoke_S1(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object av) throws Throwable { av = super.check(av, 1);
+            return target.<Object>invoke(a0, a1, a2, a3, a4, a5,
+                super.select(av,0)); }
+        protected Object invoke_S2(Object a0, Object a1, Object a2, Object a3, Object a4, Object av) throws Throwable { av = super.check(av, 2);
+            return target.<Object>invoke(a0, a1, a2, a3, a4,
+                super.select(av,0), super.select(av,1)); }
+        protected Object invoke_S3(Object a0, Object a1, Object a2, Object a3, Object av) throws Throwable { av = super.check(av, 3);
+            return target.<Object>invoke(a0, a1, a2, a3,
+                super.select(av,0), super.select(av,1), super.select(av,2)); }
+        protected Object invoke_S4(Object a0, Object a1, Object a2, Object av) throws Throwable { av = super.check(av, 4);
+            return target.<Object>invoke(a0, a1, a2,
+                super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3)); }
+        protected Object invoke_S5(Object a0, Object a1, Object av) throws Throwable { av = super.check(av, 5);
+            return target.<Object>invoke(a0, a1,
+                super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3),
+                super.select(av,4)); }
+        protected Object invoke_S6(Object a0, Object av) throws Throwable { av = super.check(av, 6);
+            return target.<Object>invoke(a0,
+                super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3),
+                super.select(av,4), super.select(av,5)); }
+        protected Object invoke_S7(Object av) throws Throwable { av = super.check(av, 7);
+            return target.<Object>invoke(
+                super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3),
+                super.select(av,4), super.select(av,5), super.select(av,6)); }
+    }
+    static class S8 extends Adapter {
+        protected S8(SpreadGeneric outer) { super(outer); }  // to build prototype
+        protected S8(SpreadGeneric outer, MethodHandle t) { super(outer, t); }
+        protected S8 makeInstance(SpreadGeneric outer, MethodHandle t) { return new S8(outer, t); }
+        protected Object invoke_S0(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object av) throws Throwable { av = super.check(av, 0);
+            return target.<Object>invoke(a0, a1, a2, a3, a4, a5, a6, a7); }
+        protected Object invoke_S1(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object av) throws Throwable { av = super.check(av, 1);
+            return target.<Object>invoke(a0, a1, a2, a3, a4, a5, a6,
+                super.select(av,0)); }
+        protected Object invoke_S2(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object av) throws Throwable { av = super.check(av, 2);
+            return target.<Object>invoke(a0, a1, a2, a3, a4, a5,
+                super.select(av,0), super.select(av,1)); }
+        protected Object invoke_S3(Object a0, Object a1, Object a2, Object a3, Object a4, Object av) throws Throwable { av = super.check(av, 3);
+            return target.<Object>invoke(a0, a1, a2, a3, a4,
+                super.select(av,0), super.select(av,1), super.select(av,2)); }
+        protected Object invoke_S4(Object a0, Object a1, Object a2, Object a3, Object av) throws Throwable { av = super.check(av, 4);
+            return target.<Object>invoke(a0, a1, a2, a3,
+                super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3)); }
+        protected Object invoke_S5(Object a0, Object a1, Object a2, Object av) throws Throwable { av = super.check(av, 5);
+            return target.<Object>invoke(a0, a1, a2,
+                super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3),
+                super.select(av,4)); }
+        protected Object invoke_S6(Object a0, Object a1, Object av) throws Throwable { av = super.check(av, 6);
+            return target.<Object>invoke(a0, a1,
+                super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3),
+                super.select(av,4), super.select(av,5)); }
+        protected Object invoke_S7(Object a0, Object av) throws Throwable { av = super.check(av, 7);
+            return target.<Object>invoke(a0,
+                super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3),
+                super.select(av,4), super.select(av,5), super.select(av,6)); }
+        protected Object invoke_S8(Object av) throws Throwable { av = super.check(av, 8);
+            return target.<Object>invoke(
+                super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3),
+                super.select(av,4), super.select(av,5), super.select(av,6), super.select(av,7)); }
+    }
+    static class S9 extends Adapter {
+        protected S9(SpreadGeneric outer) { super(outer); }  // to build prototype
+        protected S9(SpreadGeneric outer, MethodHandle t) { super(outer, t); }
+        protected S9 makeInstance(SpreadGeneric outer, MethodHandle t) { return new S9(outer, t); }
+        protected Object invoke_S0(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object av) throws Throwable { av = super.check(av, 0);
+            return target.<Object>invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8); }
+        protected Object invoke_S1(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object av) throws Throwable { av = super.check(av, 1);
+            return target.<Object>invoke(a0, a1, a2, a3, a4, a5, a6, a7,
+                super.select(av,0)); }
+        protected Object invoke_S2(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object av) throws Throwable { av = super.check(av, 2);
+            return target.<Object>invoke(a0, a1, a2, a3, a4, a5, a6,
+                super.select(av,0), super.select(av,1)); }
+        protected Object invoke_S3(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object av) throws Throwable { av = super.check(av, 3);
+            return target.<Object>invoke(a0, a1, a2, a3, a4, a5,
+                super.select(av,0), super.select(av,1), super.select(av,2)); }
+        protected Object invoke_S4(Object a0, Object a1, Object a2, Object a3, Object a4, Object av) throws Throwable { av = super.check(av, 4);
+            return target.<Object>invoke(a0, a1, a2, a3, a4,
+                super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3)); }
+        protected Object invoke_S5(Object a0, Object a1, Object a2, Object a3, Object av) throws Throwable { av = super.check(av, 5);
+            return target.<Object>invoke(a0, a1, a2, a3,
+                super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3),
+                super.select(av,4)); }
+        protected Object invoke_S6(Object a0, Object a1, Object a2, Object av) throws Throwable { av = super.check(av, 6);
+            return target.<Object>invoke(a0, a1, a2,
+                super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3),
+                super.select(av,4), super.select(av,5)); }
+        protected Object invoke_S7(Object a0, Object a1, Object av) throws Throwable { av = super.check(av, 7);
+            return target.<Object>invoke(a0, a1,
+                super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3),
+                super.select(av,4), super.select(av,5), super.select(av,6)); }
+        protected Object invoke_S8(Object a0, Object av) throws Throwable { av = super.check(av, 8);
+            return target.<Object>invoke(a0,
+                super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3),
+                super.select(av,4), super.select(av,5), super.select(av,6), super.select(av,7)); }
+        protected Object invoke_S9(Object av) throws Throwable { av = super.check(av, 9);
+            return target.<Object>invoke(
+                super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3),
+                super.select(av,4), super.select(av,5), super.select(av,6), super.select(av,7),
+                super.select(av,8)); }
+    }
+    static class S10 extends Adapter {
+        protected S10(SpreadGeneric outer) { super(outer); }  // to build prototype
+        protected S10(SpreadGeneric outer, MethodHandle t) { super(outer, t); }
+        protected S10 makeInstance(SpreadGeneric outer, MethodHandle t) { return new S10(outer, t); }
+        protected Object invoke_S0(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object a9, Object av) throws Throwable { av = super.check(av, 0);
+            return target.<Object>invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
+        protected Object invoke_S1(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object av) throws Throwable { av = super.check(av, 1);
+            return target.<Object>invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8,
+                super.select(av,0)); }
+        protected Object invoke_S2(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object av) throws Throwable { av = super.check(av, 2);
+            return target.<Object>invoke(a0, a1, a2, a3, a4, a5, a6, a7,
+                super.select(av,0), super.select(av,1)); }
+        protected Object invoke_S3(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object av) throws Throwable { av = super.check(av, 3);
+            return target.<Object>invoke(a0, a1, a2, a3, a4, a5, a6,
+                super.select(av,0), super.select(av,1), super.select(av,2)); }
+        protected Object invoke_S4(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object av) throws Throwable { av = super.check(av, 4);
+            return target.<Object>invoke(a0, a1, a2, a3, a4, a5,
+                super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3)); }
+        protected Object invoke_S5(Object a0, Object a1, Object a2, Object a3, Object a4, Object av) throws Throwable { av = super.check(av, 5);
+            return target.<Object>invoke(a0, a1, a2, a3, a4,
+                super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3),
+                super.select(av,4)); }
+        protected Object invoke_S6(Object a0, Object a1, Object a2, Object a3, Object av) throws Throwable { av = super.check(av, 6);
+            return target.<Object>invoke(a0, a1, a2, a3,
+                super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3),
+                super.select(av,4), super.select(av,5)); }
+        protected Object invoke_S7(Object a0, Object a1, Object a2, Object av) throws Throwable { av = super.check(av, 7);
+            return target.<Object>invoke(a0, a1, a2,
+                super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3),
+                super.select(av,4), super.select(av,5), super.select(av,6)); }
+        protected Object invoke_S8(Object a0, Object a1, Object av) throws Throwable { av = super.check(av, 8);
+            return target.<Object>invoke(a0, a1,
+                super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3),
+                super.select(av,4), super.select(av,5), super.select(av,6), super.select(av,7)); }
+        protected Object invoke_S9(Object a0, Object av) throws Throwable { av = super.check(av, 9);
+            return target.<Object>invoke(a0,
+                super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3),
+                super.select(av,4), super.select(av,5), super.select(av,6), super.select(av,7),
+                super.select(av,8)); }
+        protected Object invoke_S10(Object av) throws Throwable { av = super.check(av, 10);
+            return target.<Object>invoke(
+                super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3),
+                super.select(av,4), super.select(av,5), super.select(av,6), super.select(av,7),
+                super.select(av,8), super.select(av,9)); }
+    }
+}
--- a/jdk/src/share/classes/sun/dyn/ToGeneric.java	Thu Dec 17 14:10:20 2009 -0800
+++ b/jdk/src/share/classes/sun/dyn/ToGeneric.java	Wed Jul 05 17:04:56 2017 +0200
@@ -34,6 +34,7 @@
 import java.lang.reflect.InvocationTargetException;
 import sun.dyn.util.ValueConversions;
 import sun.dyn.util.Wrapper;
+import static sun.dyn.MemberName.newIllegalArgumentException;
 
 /**
  * Adapters which mediate between incoming calls which are not generic
@@ -68,7 +69,7 @@
     // conversion which unboxes a primitive return value
     private final MethodHandle returnConversion;
 
-    /** Compute and cache information common to all collecting adapters
+    /** Compute and cache information common to all generifying (boxing) adapters
      *  that implement members of the erasure-family of the given erased type.
      */
     private ToGeneric(MethodType entryType) {
@@ -111,30 +112,48 @@
         // primitive arguments according to their "raw" types int/long
         MethodType intsAtEnd = MethodTypeImpl.of(primsAtEnd).primsAsInts();
         ad = findAdapter(rawEntryTypeInit = intsAtEnd);
-        if (ad == null) {
+        MethodHandle rawEntryPoint;
+        if (ad != null) {
+            rawEntryPoint = ad.prototypeEntryPoint();
+        } else {
             // Perhaps the adapter is available only for longs.
             // If so, we can use it, but there will have to be a little
             // more stack motion on each call.
             MethodType longsAtEnd = MethodTypeImpl.of(primsAtEnd).primsAsLongs();
             ad = findAdapter(rawEntryTypeInit = longsAtEnd);
-            if (ad == null) {
+            if (ad != null) {
+                MethodType eptWithLongs = longsAtEnd.insertParameterTypes(0, ad.getClass());
+                MethodType eptWithInts  =  intsAtEnd.insertParameterTypes(0, ad.getClass());
+                rawEntryPoint = ad.prototypeEntryPoint();
+                MethodType midType = eptWithLongs;  // will change longs to ints
+                for (int i = 0, nargs = midType.parameterCount(); i < nargs; i++) {
+                    if (midType.parameterType(i) != eptWithInts.parameterType(i)) {
+                        assert(midType.parameterType(i) == long.class);
+                        assert(eptWithInts.parameterType(i) == int.class);
+                        MethodType nextType = midType.changeParameterType(i, int.class);
+                        rawEntryPoint = MethodHandle.convertArguments(Access.TOKEN,
+                                rawEntryPoint, nextType, midType, null);
+                        midType = nextType;
+                    }
+                }
+                assert(midType == eptWithInts);
+            } else {
                 // If there is no statically compiled adapter,
                 // build one by means of dynamic bytecode generation.
                 ad = buildAdapterFromBytecodes(rawEntryTypeInit = intsAtEnd);
+                rawEntryPoint = ad.prototypeEntryPoint();
             }
         }
-        MethodHandle rawEntryPoint = ad.prototypeEntryPoint();
-        MethodType tepType = entryType.insertParameterType(0, ad.getClass());
+        MethodType tepType = entryType.insertParameterTypes(0, ad.getClass());
         this.entryPoint =
-            AdapterMethodHandle.makeRawRetypeOnly(Access.TOKEN, tepType, rawEntryPoint);
+            AdapterMethodHandle.makeRetypeRaw(Access.TOKEN, tepType, rawEntryPoint);
         if (this.entryPoint == null)
             throw new UnsupportedOperationException("cannot retype to "+entryType
-                    +" from "+rawEntryPoint.type().dropParameterType(0));
+                    +" from "+rawEntryPoint.type().dropParameterTypes(0, 1));
         this.returnConversion = computeReturnConversion(entryType, rawEntryTypeInit, false);
         this.rawEntryType = rawEntryTypeInit;
         this.adapter = ad;
-        this.invoker = makeRawArgumentFilter(invoker0,
-                rawEntryPoint.type().dropParameterType(0), entryType);
+        this.invoker = makeRawArgumentFilter(invoker0, rawEntryTypeInit, entryType);
     }
 
     /** A generic argument list will be created by a call of type 'raw'.
@@ -157,8 +176,8 @@
                 if (filteredInvoker == null)  throw new UnsupportedOperationException("NYI");
             }
             MethodHandle reboxer = ValueConversions.rebox(dst, false);
-            FilterGeneric gen = new FilterGeneric(filteredInvoker.type(), (short)(1+i), (short)1, 'R');
-            filteredInvoker = gen.makeInstance(reboxer, filteredInvoker);
+            filteredInvoker = FilterGeneric.makeArgumentFilter(1+i, reboxer, filteredInvoker);
+            if (filteredInvoker == null)  throw new InternalError();
         }
         if (filteredInvoker == null)  return invoker;
         return AdapterMethodHandle.makeRetypeOnly(Access.TOKEN, invoker.type(), filteredInvoker);
@@ -209,9 +228,9 @@
         if (convert == null)
             convert = computeReturnConversion(type, rawEntryType, true);
         // retype erased reference arguments (the cast makes it safe to do this)
-        MethodType tepType = type.insertParameterType(0, adapter.getClass());
+        MethodType tepType = type.insertParameterTypes(0, adapter.getClass());
         MethodHandle typedEntryPoint =
-            AdapterMethodHandle.makeRawRetypeOnly(Access.TOKEN, tepType, entryPoint);
+            AdapterMethodHandle.makeRetypeRaw(Access.TOKEN, tepType, entryPoint);
         return adapter.makeInstance(typedEntryPoint, invoker, convert, genericTarget);
     }
 
@@ -225,7 +244,7 @@
     public static MethodHandle make(MethodType type, MethodHandle genericTarget) {
         MethodType gtype = genericTarget.type();
         if (type.generic() != gtype)
-            throw new IllegalArgumentException();
+            throw newIllegalArgumentException("type must be generic");
         if (type == gtype)  return genericTarget;
         return ToGeneric.of(type).makeInstance(type, genericTarget);
     }
@@ -283,7 +302,10 @@
                 try {
                     return ctor.newInstance(entryPoint);
                 } catch (IllegalArgumentException ex) {
-                } catch (InvocationTargetException ex) {
+                } catch (InvocationTargetException wex) {
+                    Throwable ex = wex.getTargetException();
+                    if (ex instanceof Error)  throw (Error)ex;
+                    if (ex instanceof RuntimeException)  throw (RuntimeException)ex;
                 } catch (InstantiationException ex) {
                 } catch (IllegalAccessException ex) {
                 }
@@ -317,6 +339,11 @@
         protected final MethodHandle target;   // Object... -> Object
         protected final MethodHandle convert;  // Object -> R
 
+        @Override
+        public String toString() {
+            return target.toString();
+        }
+
         protected boolean isPrototype() { return target == null; }
         /* Prototype constructor. */
         protected Adapter(MethodHandle entryPoint) {
@@ -344,33 +371,33 @@
         // { return new ThisType(entryPoint, convert, target); }
 
         // Code to run when the arguments (<= 4) have all been boxed.
-        protected Object target()               { return invoker.<Object>invoke(target); }
-        protected Object target(Object a0)      { return invoker.<Object>invoke(target, a0); }
+        protected Object target()               throws Throwable { return invoker.<Object>invoke(target); }
+        protected Object target(Object a0)      throws Throwable { return invoker.<Object>invoke(target, a0); }
         protected Object target(Object a0, Object a1)
-                                                { return invoker.<Object>invoke(target, a0, a1); }
+                                                throws Throwable { return invoker.<Object>invoke(target, a0, a1); }
         protected Object target(Object a0, Object a1, Object a2)
-                                                { return invoker.<Object>invoke(target, a0, a1, a2); }
+                                                throws Throwable { return invoker.<Object>invoke(target, a0, a1, a2); }
         protected Object target(Object a0, Object a1, Object a2, Object a3)
-                                                { return invoker.<Object>invoke(target, a0, a1, a2, a3); }
+                                                throws Throwable { return invoker.<Object>invoke(target, a0, a1, a2, a3); }
         /*
-        protected Object target_0(Object... av) { return invoker.<Object>invoke(target, av); }
+        protected Object target_0(Object... av) throws Throwable { return invoker.<Object>invoke(target, av); }
         protected Object target_1(Object a0, Object... av)
-                                                { return invoker.<Object>invoke(target, a0, (Object)av); }
+                                                throws Throwable { return invoker.<Object>invoke(target, a0, (Object)av); }
         protected Object target_2(Object a0, Object a1, Object... av)
-                                                { return invoker.<Object>invoke(target, a0, a1, (Object)av); }
+                                                throws Throwable { return invoker.<Object>invoke(target, a0, a1, (Object)av); }
         protected Object target_3(Object a0, Object a1, Object a2, Object... av)
-                                                { return invoker.<Object>invoke(target, a0, a1, a2, (Object)av); }
+                                                throws Throwable { return invoker.<Object>invoke(target, a0, a1, a2, (Object)av); }
         protected Object target_4(Object a0, Object a1, Object a2, Object a3, Object... av)
-                                                { return invoker.<Object>invoke(target, a0, a1, a2, a3, (Object)av); }
+                                                throws Throwable { return invoker.<Object>invoke(target, a0, a1, a2, a3, (Object)av); }
         // */
         // (For more than 4 arguments, generate the code in the adapter itself.)
 
         // Code to run when the generic target has finished and produced a value.
-        protected Object return_L(Object res) { return convert.<Object>invoke(res); }
-        protected int    return_I(Object res) { return convert.<int   >invoke(res); }
-        protected long   return_J(Object res) { return convert.<long  >invoke(res); }
-        protected float  return_F(Object res) { return convert.<float >invoke(res); }
-        protected double return_D(Object res) { return convert.<double>invoke(res); }
+        protected Object return_L(Object res) throws Throwable { return convert.<Object>invoke(res); }
+        protected int    return_I(Object res) throws Throwable { return convert.<int   >invoke(res); }
+        protected long   return_J(Object res) throws Throwable { return convert.<long  >invoke(res); }
+        protected float  return_F(Object res) throws Throwable { return convert.<float >invoke(res); }
+        protected double return_D(Object res) throws Throwable { return convert.<double>invoke(res); }
 
         static private final String CLASS_PREFIX; // "sun.dyn.ToGeneric$"
         static {
@@ -397,25 +424,25 @@
         protected A1(MethodHandle entryPoint) { super(entryPoint); }  // to build prototype
         protected A1(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { super(e, i, c, t); }
         protected A1 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { return new A1(e, i, c, t); }
-        protected Object target(Object a0)    { return invoker.<Object>invoke(target, a0); }
-        protected Object targetA1(Object a0) { return target(a0); }
-        protected Object targetA1(int    a0) { return target(a0); }
-        protected Object targetA1(long   a0) { return target(a0); }
-        protected Object invoke_L(Object a0) { return return_L(targetA1(a0)); }
-        protected int    invoke_I(Object a0) { return return_I(targetA1(a0)); }
-        protected long   invoke_J(Object a0) { return return_J(targetA1(a0)); }
-        protected float  invoke_F(Object a0) { return return_F(targetA1(a0)); }
-        protected double invoke_D(Object a0) { return return_D(targetA1(a0)); }
-        protected Object invoke_L(int    a0) { return return_L(targetA1(a0)); }
-        protected int    invoke_I(int    a0) { return return_I(targetA1(a0)); }
-        protected long   invoke_J(int    a0) { return return_J(targetA1(a0)); }
-        protected float  invoke_F(int    a0) { return return_F(targetA1(a0)); }
-        protected double invoke_D(int    a0) { return return_D(targetA1(a0)); }
-        protected Object invoke_L(long   a0) { return return_L(targetA1(a0)); }
-        protected int    invoke_I(long   a0) { return return_I(targetA1(a0)); }
-        protected long   invoke_J(long   a0) { return return_J(targetA1(a0)); }
-        protected float  invoke_F(long   a0) { return return_F(targetA1(a0)); }
-        protected double invoke_D(long   a0) { return return_D(targetA1(a0)); }
+        protected Object target(Object a0)   throws Throwable { return invoker.<Object>invoke(target, a0); }
+        protected Object targetA1(Object a0) throws Throwable { return target(a0); }
+        protected Object targetA1(int    a0) throws Throwable { return target(a0); }
+        protected Object targetA1(long   a0) throws Throwable { return target(a0); }
+        protected Object invoke_L(Object a0) throws Throwable { return return_L(targetA1(a0)); }
+        protected int    invoke_I(Object a0) throws Throwable { return return_I(targetA1(a0)); }
+        protected long   invoke_J(Object a0) throws Throwable { return return_J(targetA1(a0)); }
+        protected float  invoke_F(Object a0) throws Throwable { return return_F(targetA1(a0)); }
+        protected double invoke_D(Object a0) throws Throwable { return return_D(targetA1(a0)); }
+        protected Object invoke_L(int    a0) throws Throwable { return return_L(targetA1(a0)); }
+        protected int    invoke_I(int    a0) throws Throwable { return return_I(targetA1(a0)); }
+        protected long   invoke_J(int    a0) throws Throwable { return return_J(targetA1(a0)); }
+        protected float  invoke_F(int    a0) throws Throwable { return return_F(targetA1(a0)); }
+        protected double invoke_D(int    a0) throws Throwable { return return_D(targetA1(a0)); }
+        protected Object invoke_L(long   a0) throws Throwable { return return_L(targetA1(a0)); }
+        protected int    invoke_I(long   a0) throws Throwable { return return_I(targetA1(a0)); }
+        protected long   invoke_J(long   a0) throws Throwable { return return_J(targetA1(a0)); }
+        protected float  invoke_F(long   a0) throws Throwable { return return_F(targetA1(a0)); }
+        protected double invoke_D(long   a0) throws Throwable { return return_D(targetA1(a0)); }
     }
     // */
 
@@ -435,13 +462,13 @@
         "        protected @cat@(MethodHandle entryPoint) { super(entryPoint); }  // to build prototype",
         "        protected @cat@(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { super(e, i, c, t); }",
         "        protected @cat@ makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { return new @cat@(e, i, c, t); }",
-        "        protected Object target(@Ovav@)   { return invoker.<Object>invoke(target, @av@); }",
+        "        protected Object target(@Ovav@)   throws Throwable { return invoker.<Object>invoke(target, @av@); }",
         "        //@each-Tv@",
-        "        protected Object target@cat@(@Tvav@) { return target(@av@); }",
+        "        protected Object target@cat@(@Tvav@) throws Throwable { return target(@av@); }",
         "        //@end-Tv@",
         "        //@each-Tv@",
         "        //@each-R@",
-        "        protected @R@ invoke_@Rc@(@Tvav@) { return return_@Rc@(target@cat@(@av@)); }",
+        "        protected @R@ invoke_@Rc@(@Tvav@) throws Throwable { return return_@Rc@(target@cat@(@av@)); }",
         "        //@end-R@",
         "        //@end-Tv@",
         "    }",
@@ -595,424 +622,424 @@
         protected A0(MethodHandle entryPoint) { super(entryPoint); }  // to build prototype
         protected A0(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { super(e, i, c, t); }
         protected A0 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { return new A0(e, i, c, t); }
-        protected Object target()   { return invoker.<Object>invoke(target); }
-        protected Object targetA0() { return target(); }
-        protected Object invoke_L() { return return_L(targetA0()); }
-        protected int    invoke_I() { return return_I(targetA0()); }
-        protected long   invoke_J() { return return_J(targetA0()); }
-        protected float  invoke_F() { return return_F(targetA0()); }
-        protected double invoke_D() { return return_D(targetA0()); }
+        protected Object target()   throws Throwable { return invoker.<Object>invoke(target); }
+        protected Object targetA0() throws Throwable { return target(); }
+        protected Object invoke_L() throws Throwable { return return_L(targetA0()); }
+        protected int    invoke_I() throws Throwable { return return_I(targetA0()); }
+        protected long   invoke_J() throws Throwable { return return_J(targetA0()); }
+        protected float  invoke_F() throws Throwable { return return_F(targetA0()); }
+        protected double invoke_D() throws Throwable { return return_D(targetA0()); }
     }
     static class A1 extends Adapter {
         protected A1(MethodHandle entryPoint) { super(entryPoint); }  // to build prototype
         protected A1(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { super(e, i, c, t); }
         protected A1 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { return new A1(e, i, c, t); }
-        protected Object target(Object a0)   { return invoker.<Object>invoke(target, a0); }
-        protected Object targetA1(Object a0) { return target(a0); }
-        protected Object targetA1(int    a0) { return target(a0); }
-        protected Object targetA1(long   a0) { return target(a0); }
-        protected Object invoke_L(Object a0) { return return_L(targetA1(a0)); }
-        protected int    invoke_I(Object a0) { return return_I(targetA1(a0)); }
-        protected long   invoke_J(Object a0) { return return_J(targetA1(a0)); }
-        protected float  invoke_F(Object a0) { return return_F(targetA1(a0)); }
-        protected double invoke_D(Object a0) { return return_D(targetA1(a0)); }
-        protected Object invoke_L(int    a0) { return return_L(targetA1(a0)); }
-        protected int    invoke_I(int    a0) { return return_I(targetA1(a0)); }
-        protected long   invoke_J(int    a0) { return return_J(targetA1(a0)); }
-        protected float  invoke_F(int    a0) { return return_F(targetA1(a0)); }
-        protected double invoke_D(int    a0) { return return_D(targetA1(a0)); }
-        protected Object invoke_L(long   a0) { return return_L(targetA1(a0)); }
-        protected int    invoke_I(long   a0) { return return_I(targetA1(a0)); }
-        protected long   invoke_J(long   a0) { return return_J(targetA1(a0)); }
-        protected float  invoke_F(long   a0) { return return_F(targetA1(a0)); }
-        protected double invoke_D(long   a0) { return return_D(targetA1(a0)); }
+        protected Object target(Object a0)   throws Throwable { return invoker.<Object>invoke(target, a0); }
+        protected Object targetA1(Object a0) throws Throwable { return target(a0); }
+        protected Object targetA1(int    a0) throws Throwable { return target(a0); }
+        protected Object targetA1(long   a0) throws Throwable { return target(a0); }
+        protected Object invoke_L(Object a0) throws Throwable { return return_L(targetA1(a0)); }
+        protected int    invoke_I(Object a0) throws Throwable { return return_I(targetA1(a0)); }
+        protected long   invoke_J(Object a0) throws Throwable { return return_J(targetA1(a0)); }
+        protected float  invoke_F(Object a0) throws Throwable { return return_F(targetA1(a0)); }
+        protected double invoke_D(Object a0) throws Throwable { return return_D(targetA1(a0)); }
+        protected Object invoke_L(int    a0) throws Throwable { return return_L(targetA1(a0)); }
+        protected int    invoke_I(int    a0) throws Throwable { return return_I(targetA1(a0)); }
+        protected long   invoke_J(int    a0) throws Throwable { return return_J(targetA1(a0)); }
+        protected float  invoke_F(int    a0) throws Throwable { return return_F(targetA1(a0)); }
+        protected double invoke_D(int    a0) throws Throwable { return return_D(targetA1(a0)); }
+        protected Object invoke_L(long   a0) throws Throwable { return return_L(targetA1(a0)); }
+        protected int    invoke_I(long   a0) throws Throwable { return return_I(targetA1(a0)); }
+        protected long   invoke_J(long   a0) throws Throwable { return return_J(targetA1(a0)); }
+        protected float  invoke_F(long   a0) throws Throwable { return return_F(targetA1(a0)); }
+        protected double invoke_D(long   a0) throws Throwable { return return_D(targetA1(a0)); }
     }
     static class A2 extends Adapter {
         protected A2(MethodHandle entryPoint) { super(entryPoint); }  // to build prototype
         protected A2(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { super(e, i, c, t); }
         protected A2 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { return new A2(e, i, c, t); }
-        protected Object target(Object a0, Object a1)   { return invoker.<Object>invoke(target, a0, a1); }
-        protected Object targetA2(Object a0, Object a1) { return target(a0, a1); }
-        protected Object targetA2(Object a0, int    a1) { return target(a0, a1); }
-        protected Object targetA2(int    a0, int    a1) { return target(a0, a1); }
-        protected Object targetA2(Object a0, long   a1) { return target(a0, a1); }
-        protected Object targetA2(long   a0, long   a1) { return target(a0, a1); }
-        protected Object invoke_L(Object a0, Object a1) { return return_L(targetA2(a0, a1)); }
-        protected int    invoke_I(Object a0, Object a1) { return return_I(targetA2(a0, a1)); }
-        protected long   invoke_J(Object a0, Object a1) { return return_J(targetA2(a0, a1)); }
-        protected float  invoke_F(Object a0, Object a1) { return return_F(targetA2(a0, a1)); }
-        protected double invoke_D(Object a0, Object a1) { return return_D(targetA2(a0, a1)); }
-        protected Object invoke_L(Object a0, int    a1) { return return_L(targetA2(a0, a1)); }
-        protected int    invoke_I(Object a0, int    a1) { return return_I(targetA2(a0, a1)); }
-        protected long   invoke_J(Object a0, int    a1) { return return_J(targetA2(a0, a1)); }
-        protected float  invoke_F(Object a0, int    a1) { return return_F(targetA2(a0, a1)); }
-        protected double invoke_D(Object a0, int    a1) { return return_D(targetA2(a0, a1)); }
-        protected Object invoke_L(int    a0, int    a1) { return return_L(targetA2(a0, a1)); }
-        protected int    invoke_I(int    a0, int    a1) { return return_I(targetA2(a0, a1)); }
-        protected long   invoke_J(int    a0, int    a1) { return return_J(targetA2(a0, a1)); }
-        protected float  invoke_F(int    a0, int    a1) { return return_F(targetA2(a0, a1)); }
-        protected double invoke_D(int    a0, int    a1) { return return_D(targetA2(a0, a1)); }
-        protected Object invoke_L(Object a0, long   a1) { return return_L(targetA2(a0, a1)); }
-        protected int    invoke_I(Object a0, long   a1) { return return_I(targetA2(a0, a1)); }
-        protected long   invoke_J(Object a0, long   a1) { return return_J(targetA2(a0, a1)); }
-        protected float  invoke_F(Object a0, long   a1) { return return_F(targetA2(a0, a1)); }
-        protected double invoke_D(Object a0, long   a1) { return return_D(targetA2(a0, a1)); }
-        protected Object invoke_L(long   a0, long   a1) { return return_L(targetA2(a0, a1)); }
-        protected int    invoke_I(long   a0, long   a1) { return return_I(targetA2(a0, a1)); }
-        protected long   invoke_J(long   a0, long   a1) { return return_J(targetA2(a0, a1)); }
-        protected float  invoke_F(long   a0, long   a1) { return return_F(targetA2(a0, a1)); }
-        protected double invoke_D(long   a0, long   a1) { return return_D(targetA2(a0, a1)); }
+        protected Object target(Object a0, Object a1)   throws Throwable { return invoker.<Object>invoke(target, a0, a1); }
+        protected Object targetA2(Object a0, Object a1) throws Throwable { return target(a0, a1); }
+        protected Object targetA2(Object a0, int    a1) throws Throwable { return target(a0, a1); }
+        protected Object targetA2(int    a0, int    a1) throws Throwable { return target(a0, a1); }
+        protected Object targetA2(Object a0, long   a1) throws Throwable { return target(a0, a1); }
+        protected Object targetA2(long   a0, long   a1) throws Throwable { return target(a0, a1); }
+        protected Object invoke_L(Object a0, Object a1) throws Throwable { return return_L(targetA2(a0, a1)); }
+        protected int    invoke_I(Object a0, Object a1) throws Throwable { return return_I(targetA2(a0, a1)); }
+        protected long   invoke_J(Object a0, Object a1) throws Throwable { return return_J(targetA2(a0, a1)); }
+        protected float  invoke_F(Object a0, Object a1) throws Throwable { return return_F(targetA2(a0, a1)); }
+        protected double invoke_D(Object a0, Object a1) throws Throwable { return return_D(targetA2(a0, a1)); }
+        protected Object invoke_L(Object a0, int    a1) throws Throwable { return return_L(targetA2(a0, a1)); }
+        protected int    invoke_I(Object a0, int    a1) throws Throwable { return return_I(targetA2(a0, a1)); }
+        protected long   invoke_J(Object a0, int    a1) throws Throwable { return return_J(targetA2(a0, a1)); }
+        protected float  invoke_F(Object a0, int    a1) throws Throwable { return return_F(targetA2(a0, a1)); }
+        protected double invoke_D(Object a0, int    a1) throws Throwable { return return_D(targetA2(a0, a1)); }
+        protected Object invoke_L(int    a0, int    a1) throws Throwable { return return_L(targetA2(a0, a1)); }
+        protected int    invoke_I(int    a0, int    a1) throws Throwable { return return_I(targetA2(a0, a1)); }
+        protected long   invoke_J(int    a0, int    a1) throws Throwable { return return_J(targetA2(a0, a1)); }
+        protected float  invoke_F(int    a0, int    a1) throws Throwable { return return_F(targetA2(a0, a1)); }
+        protected double invoke_D(int    a0, int    a1) throws Throwable { return return_D(targetA2(a0, a1)); }
+        protected Object invoke_L(Object a0, long   a1) throws Throwable { return return_L(targetA2(a0, a1)); }
+        protected int    invoke_I(Object a0, long   a1) throws Throwable { return return_I(targetA2(a0, a1)); }
+        protected long   invoke_J(Object a0, long   a1) throws Throwable { return return_J(targetA2(a0, a1)); }
+        protected float  invoke_F(Object a0, long   a1) throws Throwable { return return_F(targetA2(a0, a1)); }
+        protected double invoke_D(Object a0, long   a1) throws Throwable { return return_D(targetA2(a0, a1)); }
+        protected Object invoke_L(long   a0, long   a1) throws Throwable { return return_L(targetA2(a0, a1)); }
+        protected int    invoke_I(long   a0, long   a1) throws Throwable { return return_I(targetA2(a0, a1)); }
+        protected long   invoke_J(long   a0, long   a1) throws Throwable { return return_J(targetA2(a0, a1)); }
+        protected float  invoke_F(long   a0, long   a1) throws Throwable { return return_F(targetA2(a0, a1)); }
+        protected double invoke_D(long   a0, long   a1) throws Throwable { return return_D(targetA2(a0, a1)); }
     }
     static class A3 extends Adapter {
         protected A3(MethodHandle entryPoint) { super(entryPoint); }  // to build prototype
         protected A3(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { super(e, i, c, t); }
         protected A3 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { return new A3(e, i, c, t); }
-        protected Object target(Object a0, Object a1, Object a2)   { return invoker.<Object>invoke(target, a0, a1, a2); }
-        protected Object targetA3(Object a0, Object a1, Object a2) { return target(a0, a1, a2); }
-        protected Object targetA3(Object a0, Object a1, int    a2) { return target(a0, a1, a2); }
-        protected Object targetA3(Object a0, int    a1, int    a2) { return target(a0, a1, a2); }
-        protected Object targetA3(int    a0, int    a1, int    a2) { return target(a0, a1, a2); }
-        protected Object targetA3(Object a0, Object a1, long   a2) { return target(a0, a1, a2); }
-        protected Object targetA3(Object a0, long   a1, long   a2) { return target(a0, a1, a2); }
-        protected Object targetA3(long   a0, long   a1, long   a2) { return target(a0, a1, a2); }
-        protected Object invoke_L(Object a0, Object a1, Object a2) { return return_L(targetA3(a0, a1, a2)); }
-        protected int    invoke_I(Object a0, Object a1, Object a2) { return return_I(targetA3(a0, a1, a2)); }
-        protected long   invoke_J(Object a0, Object a1, Object a2) { return return_J(targetA3(a0, a1, a2)); }
-        protected float  invoke_F(Object a0, Object a1, Object a2) { return return_F(targetA3(a0, a1, a2)); }
-        protected double invoke_D(Object a0, Object a1, Object a2) { return return_D(targetA3(a0, a1, a2)); }
-        protected Object invoke_L(Object a0, Object a1, int    a2) { return return_L(targetA3(a0, a1, a2)); }
-        protected int    invoke_I(Object a0, Object a1, int    a2) { return return_I(targetA3(a0, a1, a2)); }
-        protected long   invoke_J(Object a0, Object a1, int    a2) { return return_J(targetA3(a0, a1, a2)); }
-        protected float  invoke_F(Object a0, Object a1, int    a2) { return return_F(targetA3(a0, a1, a2)); }
-        protected double invoke_D(Object a0, Object a1, int    a2) { return return_D(targetA3(a0, a1, a2)); }
-        protected Object invoke_L(Object a0, int    a1, int    a2) { return return_L(targetA3(a0, a1, a2)); }
-        protected int    invoke_I(Object a0, int    a1, int    a2) { return return_I(targetA3(a0, a1, a2)); }
-        protected long   invoke_J(Object a0, int    a1, int    a2) { return return_J(targetA3(a0, a1, a2)); }
-        protected float  invoke_F(Object a0, int    a1, int    a2) { return return_F(targetA3(a0, a1, a2)); }
-        protected double invoke_D(Object a0, int    a1, int    a2) { return return_D(targetA3(a0, a1, a2)); }
-        protected Object invoke_L(int    a0, int    a1, int    a2) { return return_L(targetA3(a0, a1, a2)); }
-        protected int    invoke_I(int    a0, int    a1, int    a2) { return return_I(targetA3(a0, a1, a2)); }
-        protected long   invoke_J(int    a0, int    a1, int    a2) { return return_J(targetA3(a0, a1, a2)); }
-        protected float  invoke_F(int    a0, int    a1, int    a2) { return return_F(targetA3(a0, a1, a2)); }
-        protected double invoke_D(int    a0, int    a1, int    a2) { return return_D(targetA3(a0, a1, a2)); }
-        protected Object invoke_L(Object a0, Object a1, long   a2) { return return_L(targetA3(a0, a1, a2)); }
-        protected int    invoke_I(Object a0, Object a1, long   a2) { return return_I(targetA3(a0, a1, a2)); }
-        protected long   invoke_J(Object a0, Object a1, long   a2) { return return_J(targetA3(a0, a1, a2)); }
-        protected float  invoke_F(Object a0, Object a1, long   a2) { return return_F(targetA3(a0, a1, a2)); }
-        protected double invoke_D(Object a0, Object a1, long   a2) { return return_D(targetA3(a0, a1, a2)); }
-        protected Object invoke_L(Object a0, long   a1, long   a2) { return return_L(targetA3(a0, a1, a2)); }
-        protected int    invoke_I(Object a0, long   a1, long   a2) { return return_I(targetA3(a0, a1, a2)); }
-        protected long   invoke_J(Object a0, long   a1, long   a2) { return return_J(targetA3(a0, a1, a2)); }
-        protected float  invoke_F(Object a0, long   a1, long   a2) { return return_F(targetA3(a0, a1, a2)); }
-        protected double invoke_D(Object a0, long   a1, long   a2) { return return_D(targetA3(a0, a1, a2)); }
-        protected Object invoke_L(long   a0, long   a1, long   a2) { return return_L(targetA3(a0, a1, a2)); }
-        protected int    invoke_I(long   a0, long   a1, long   a2) { return return_I(targetA3(a0, a1, a2)); }
-        protected long   invoke_J(long   a0, long   a1, long   a2) { return return_J(targetA3(a0, a1, a2)); }
-        protected float  invoke_F(long   a0, long   a1, long   a2) { return return_F(targetA3(a0, a1, a2)); }
-        protected double invoke_D(long   a0, long   a1, long   a2) { return return_D(targetA3(a0, a1, a2)); }
+        protected Object target(Object a0, Object a1, Object a2)   throws Throwable { return invoker.<Object>invoke(target, a0, a1, a2); }
+        protected Object targetA3(Object a0, Object a1, Object a2) throws Throwable { return target(a0, a1, a2); }
+        protected Object targetA3(Object a0, Object a1, int    a2) throws Throwable { return target(a0, a1, a2); }
+        protected Object targetA3(Object a0, int    a1, int    a2) throws Throwable { return target(a0, a1, a2); }
+        protected Object targetA3(int    a0, int    a1, int    a2) throws Throwable { return target(a0, a1, a2); }
+        protected Object targetA3(Object a0, Object a1, long   a2) throws Throwable { return target(a0, a1, a2); }
+        protected Object targetA3(Object a0, long   a1, long   a2) throws Throwable { return target(a0, a1, a2); }
+        protected Object targetA3(long   a0, long   a1, long   a2) throws Throwable { return target(a0, a1, a2); }
+        protected Object invoke_L(Object a0, Object a1, Object a2) throws Throwable { return return_L(targetA3(a0, a1, a2)); }
+        protected int    invoke_I(Object a0, Object a1, Object a2) throws Throwable { return return_I(targetA3(a0, a1, a2)); }
+        protected long   invoke_J(Object a0, Object a1, Object a2) throws Throwable { return return_J(targetA3(a0, a1, a2)); }
+        protected float  invoke_F(Object a0, Object a1, Object a2) throws Throwable { return return_F(targetA3(a0, a1, a2)); }
+        protected double invoke_D(Object a0, Object a1, Object a2) throws Throwable { return return_D(targetA3(a0, a1, a2)); }
+        protected Object invoke_L(Object a0, Object a1, int    a2) throws Throwable { return return_L(targetA3(a0, a1, a2)); }
+        protected int    invoke_I(Object a0, Object a1, int    a2) throws Throwable { return return_I(targetA3(a0, a1, a2)); }
+        protected long   invoke_J(Object a0, Object a1, int    a2) throws Throwable { return return_J(targetA3(a0, a1, a2)); }
+        protected float  invoke_F(Object a0, Object a1, int    a2) throws Throwable { return return_F(targetA3(a0, a1, a2)); }
+        protected double invoke_D(Object a0, Object a1, int    a2) throws Throwable { return return_D(targetA3(a0, a1, a2)); }
+        protected Object invoke_L(Object a0, int    a1, int    a2) throws Throwable { return return_L(targetA3(a0, a1, a2)); }
+        protected int    invoke_I(Object a0, int    a1, int    a2) throws Throwable { return return_I(targetA3(a0, a1, a2)); }
+        protected long   invoke_J(Object a0, int    a1, int    a2) throws Throwable { return return_J(targetA3(a0, a1, a2)); }
+        protected float  invoke_F(Object a0, int    a1, int    a2) throws Throwable { return return_F(targetA3(a0, a1, a2)); }
+        protected double invoke_D(Object a0, int    a1, int    a2) throws Throwable { return return_D(targetA3(a0, a1, a2)); }
+        protected Object invoke_L(int    a0, int    a1, int    a2) throws Throwable { return return_L(targetA3(a0, a1, a2)); }
+        protected int    invoke_I(int    a0, int    a1, int    a2) throws Throwable { return return_I(targetA3(a0, a1, a2)); }
+        protected long   invoke_J(int    a0, int    a1, int    a2) throws Throwable { return return_J(targetA3(a0, a1, a2)); }
+        protected float  invoke_F(int    a0, int    a1, int    a2) throws Throwable { return return_F(targetA3(a0, a1, a2)); }
+        protected double invoke_D(int    a0, int    a1, int    a2) throws Throwable { return return_D(targetA3(a0, a1, a2)); }
+        protected Object invoke_L(Object a0, Object a1, long   a2) throws Throwable { return return_L(targetA3(a0, a1, a2)); }
+        protected int    invoke_I(Object a0, Object a1, long   a2) throws Throwable { return return_I(targetA3(a0, a1, a2)); }
+        protected long   invoke_J(Object a0, Object a1, long   a2) throws Throwable { return return_J(targetA3(a0, a1, a2)); }
+        protected float  invoke_F(Object a0, Object a1, long   a2) throws Throwable { return return_F(targetA3(a0, a1, a2)); }
+        protected double invoke_D(Object a0, Object a1, long   a2) throws Throwable { return return_D(targetA3(a0, a1, a2)); }
+        protected Object invoke_L(Object a0, long   a1, long   a2) throws Throwable { return return_L(targetA3(a0, a1, a2)); }
+        protected int    invoke_I(Object a0, long   a1, long   a2) throws Throwable { return return_I(targetA3(a0, a1, a2)); }
+        protected long   invoke_J(Object a0, long   a1, long   a2) throws Throwable { return return_J(targetA3(a0, a1, a2)); }
+        protected float  invoke_F(Object a0, long   a1, long   a2) throws Throwable { return return_F(targetA3(a0, a1, a2)); }
+        protected double invoke_D(Object a0, long   a1, long   a2) throws Throwable { return return_D(targetA3(a0, a1, a2)); }
+        protected Object invoke_L(long   a0, long   a1, long   a2) throws Throwable { return return_L(targetA3(a0, a1, a2)); }
+        protected int    invoke_I(long   a0, long   a1, long   a2) throws Throwable { return return_I(targetA3(a0, a1, a2)); }
+        protected long   invoke_J(long   a0, long   a1, long   a2) throws Throwable { return return_J(targetA3(a0, a1, a2)); }
+        protected float  invoke_F(long   a0, long   a1, long   a2) throws Throwable { return return_F(targetA3(a0, a1, a2)); }
+        protected double invoke_D(long   a0, long   a1, long   a2) throws Throwable { return return_D(targetA3(a0, a1, a2)); }
     }
 //params=[4, 5, 2, 99, 99, 99]
     static class A4 extends Adapter {
         protected A4(MethodHandle entryPoint) { super(entryPoint); }  // to build prototype
         protected A4(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { super(e, i, c, t); }
         protected A4 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { return new A4(e, i, c, t); }
-        protected Object target(Object a0, Object a1, Object a2, Object a3)   { return invoker.<Object>invoke(target, a0, a1, a2, a3); }
-        protected Object targetA4(Object a0, Object a1, Object a2, Object a3) { return target(a0, a1, a2, a3); }
-        protected Object targetA4(Object a0, Object a1, Object a2, int    a3) { return target(a0, a1, a2, a3); }
-        protected Object targetA4(Object a0, Object a1, int    a2, int    a3) { return target(a0, a1, a2, a3); }
-        protected Object targetA4(Object a0, int    a1, int    a2, int    a3) { return target(a0, a1, a2, a3); }
-        protected Object targetA4(int    a0, int    a1, int    a2, int    a3) { return target(a0, a1, a2, a3); }
-        protected Object targetA4(Object a0, Object a1, Object a2, long   a3) { return target(a0, a1, a2, a3); }
-        protected Object targetA4(Object a0, Object a1, long   a2, long   a3) { return target(a0, a1, a2, a3); }
-        protected Object targetA4(Object a0, long   a1, long   a2, long   a3) { return target(a0, a1, a2, a3); }
-        protected Object targetA4(long   a0, long   a1, long   a2, long   a3) { return target(a0, a1, a2, a3); }
-        protected Object invoke_L(Object a0, Object a1, Object a2, Object a3) { return return_L(targetA4(a0, a1, a2, a3)); }
-        protected int    invoke_I(Object a0, Object a1, Object a2, Object a3) { return return_I(targetA4(a0, a1, a2, a3)); }
-        protected long   invoke_J(Object a0, Object a1, Object a2, Object a3) { return return_J(targetA4(a0, a1, a2, a3)); }
-        protected Object invoke_L(Object a0, Object a1, Object a2, int    a3) { return return_L(targetA4(a0, a1, a2, a3)); }
-        protected int    invoke_I(Object a0, Object a1, Object a2, int    a3) { return return_I(targetA4(a0, a1, a2, a3)); }
-        protected long   invoke_J(Object a0, Object a1, Object a2, int    a3) { return return_J(targetA4(a0, a1, a2, a3)); }
-        protected Object invoke_L(Object a0, Object a1, int    a2, int    a3) { return return_L(targetA4(a0, a1, a2, a3)); }
-        protected int    invoke_I(Object a0, Object a1, int    a2, int    a3) { return return_I(targetA4(a0, a1, a2, a3)); }
-        protected long   invoke_J(Object a0, Object a1, int    a2, int    a3) { return return_J(targetA4(a0, a1, a2, a3)); }
-        protected Object invoke_L(Object a0, int    a1, int    a2, int    a3) { return return_L(targetA4(a0, a1, a2, a3)); }
-        protected int    invoke_I(Object a0, int    a1, int    a2, int    a3) { return return_I(targetA4(a0, a1, a2, a3)); }
-        protected long   invoke_J(Object a0, int    a1, int    a2, int    a3) { return return_J(targetA4(a0, a1, a2, a3)); }
-        protected Object invoke_L(int    a0, int    a1, int    a2, int    a3) { return return_L(targetA4(a0, a1, a2, a3)); }
-        protected int    invoke_I(int    a0, int    a1, int    a2, int    a3) { return return_I(targetA4(a0, a1, a2, a3)); }
-        protected long   invoke_J(int    a0, int    a1, int    a2, int    a3) { return return_J(targetA4(a0, a1, a2, a3)); }
-        protected Object invoke_L(Object a0, Object a1, Object a2, long   a3) { return return_L(targetA4(a0, a1, a2, a3)); }
-        protected int    invoke_I(Object a0, Object a1, Object a2, long   a3) { return return_I(targetA4(a0, a1, a2, a3)); }
-        protected long   invoke_J(Object a0, Object a1, Object a2, long   a3) { return return_J(targetA4(a0, a1, a2, a3)); }
-        protected Object invoke_L(Object a0, Object a1, long   a2, long   a3) { return return_L(targetA4(a0, a1, a2, a3)); }
-        protected int    invoke_I(Object a0, Object a1, long   a2, long   a3) { return return_I(targetA4(a0, a1, a2, a3)); }
-        protected long   invoke_J(Object a0, Object a1, long   a2, long   a3) { return return_J(targetA4(a0, a1, a2, a3)); }
-        protected Object invoke_L(Object a0, long   a1, long   a2, long   a3) { return return_L(targetA4(a0, a1, a2, a3)); }
-        protected int    invoke_I(Object a0, long   a1, long   a2, long   a3) { return return_I(targetA4(a0, a1, a2, a3)); }
-        protected long   invoke_J(Object a0, long   a1, long   a2, long   a3) { return return_J(targetA4(a0, a1, a2, a3)); }
-        protected Object invoke_L(long   a0, long   a1, long   a2, long   a3) { return return_L(targetA4(a0, a1, a2, a3)); }
-        protected int    invoke_I(long   a0, long   a1, long   a2, long   a3) { return return_I(targetA4(a0, a1, a2, a3)); }
-        protected long   invoke_J(long   a0, long   a1, long   a2, long   a3) { return return_J(targetA4(a0, a1, a2, a3)); }
+        protected Object target(Object a0, Object a1, Object a2, Object a3)   throws Throwable { return invoker.<Object>invoke(target, a0, a1, a2, a3); }
+        protected Object targetA4(Object a0, Object a1, Object a2, Object a3) throws Throwable { return target(a0, a1, a2, a3); }
+        protected Object targetA4(Object a0, Object a1, Object a2, int    a3) throws Throwable { return target(a0, a1, a2, a3); }
+        protected Object targetA4(Object a0, Object a1, int    a2, int    a3) throws Throwable { return target(a0, a1, a2, a3); }
+        protected Object targetA4(Object a0, int    a1, int    a2, int    a3) throws Throwable { return target(a0, a1, a2, a3); }
+        protected Object targetA4(int    a0, int    a1, int    a2, int    a3) throws Throwable { return target(a0, a1, a2, a3); }
+        protected Object targetA4(Object a0, Object a1, Object a2, long   a3) throws Throwable { return target(a0, a1, a2, a3); }
+        protected Object targetA4(Object a0, Object a1, long   a2, long   a3) throws Throwable { return target(a0, a1, a2, a3); }
+        protected Object targetA4(Object a0, long   a1, long   a2, long   a3) throws Throwable { return target(a0, a1, a2, a3); }
+        protected Object targetA4(long   a0, long   a1, long   a2, long   a3) throws Throwable { return target(a0, a1, a2, a3); }
+        protected Object invoke_L(Object a0, Object a1, Object a2, Object a3) throws Throwable { return return_L(targetA4(a0, a1, a2, a3)); }
+        protected int    invoke_I(Object a0, Object a1, Object a2, Object a3) throws Throwable { return return_I(targetA4(a0, a1, a2, a3)); }
+        protected long   invoke_J(Object a0, Object a1, Object a2, Object a3) throws Throwable { return return_J(targetA4(a0, a1, a2, a3)); }
+        protected Object invoke_L(Object a0, Object a1, Object a2, int    a3) throws Throwable { return return_L(targetA4(a0, a1, a2, a3)); }
+        protected int    invoke_I(Object a0, Object a1, Object a2, int    a3) throws Throwable { return return_I(targetA4(a0, a1, a2, a3)); }
+        protected long   invoke_J(Object a0, Object a1, Object a2, int    a3) throws Throwable { return return_J(targetA4(a0, a1, a2, a3)); }
+        protected Object invoke_L(Object a0, Object a1, int    a2, int    a3) throws Throwable { return return_L(targetA4(a0, a1, a2, a3)); }
+        protected int    invoke_I(Object a0, Object a1, int    a2, int    a3) throws Throwable { return return_I(targetA4(a0, a1, a2, a3)); }
+        protected long   invoke_J(Object a0, Object a1, int    a2, int    a3) throws Throwable { return return_J(targetA4(a0, a1, a2, a3)); }
+        protected Object invoke_L(Object a0, int    a1, int    a2, int    a3) throws Throwable { return return_L(targetA4(a0, a1, a2, a3)); }
+        protected int    invoke_I(Object a0, int    a1, int    a2, int    a3) throws Throwable { return return_I(targetA4(a0, a1, a2, a3)); }
+        protected long   invoke_J(Object a0, int    a1, int    a2, int    a3) throws Throwable { return return_J(targetA4(a0, a1, a2, a3)); }
+        protected Object invoke_L(int    a0, int    a1, int    a2, int    a3) throws Throwable { return return_L(targetA4(a0, a1, a2, a3)); }
+        protected int    invoke_I(int    a0, int    a1, int    a2, int    a3) throws Throwable { return return_I(targetA4(a0, a1, a2, a3)); }
+        protected long   invoke_J(int    a0, int    a1, int    a2, int    a3) throws Throwable { return return_J(targetA4(a0, a1, a2, a3)); }
+        protected Object invoke_L(Object a0, Object a1, Object a2, long   a3) throws Throwable { return return_L(targetA4(a0, a1, a2, a3)); }
+        protected int    invoke_I(Object a0, Object a1, Object a2, long   a3) throws Throwable { return return_I(targetA4(a0, a1, a2, a3)); }
+        protected long   invoke_J(Object a0, Object a1, Object a2, long   a3) throws Throwable { return return_J(targetA4(a0, a1, a2, a3)); }
+        protected Object invoke_L(Object a0, Object a1, long   a2, long   a3) throws Throwable { return return_L(targetA4(a0, a1, a2, a3)); }
+        protected int    invoke_I(Object a0, Object a1, long   a2, long   a3) throws Throwable { return return_I(targetA4(a0, a1, a2, a3)); }
+        protected long   invoke_J(Object a0, Object a1, long   a2, long   a3) throws Throwable { return return_J(targetA4(a0, a1, a2, a3)); }
+        protected Object invoke_L(Object a0, long   a1, long   a2, long   a3) throws Throwable { return return_L(targetA4(a0, a1, a2, a3)); }
+        protected int    invoke_I(Object a0, long   a1, long   a2, long   a3) throws Throwable { return return_I(targetA4(a0, a1, a2, a3)); }
+        protected long   invoke_J(Object a0, long   a1, long   a2, long   a3) throws Throwable { return return_J(targetA4(a0, a1, a2, a3)); }
+        protected Object invoke_L(long   a0, long   a1, long   a2, long   a3) throws Throwable { return return_L(targetA4(a0, a1, a2, a3)); }
+        protected int    invoke_I(long   a0, long   a1, long   a2, long   a3) throws Throwable { return return_I(targetA4(a0, a1, a2, a3)); }
+        protected long   invoke_J(long   a0, long   a1, long   a2, long   a3) throws Throwable { return return_J(targetA4(a0, a1, a2, a3)); }
     }
     static class A5 extends Adapter {
         protected A5(MethodHandle entryPoint) { super(entryPoint); }  // to build prototype
         protected A5(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { super(e, i, c, t); }
         protected A5 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { return new A5(e, i, c, t); }
-        protected Object target(Object a0, Object a1, Object a2, Object a3, Object a4)   { return invoker.<Object>invoke(target, a0, a1, a2, a3, a4); }
-        protected Object targetA5(Object a0, Object a1, Object a2, Object a3, Object a4) { return target(a0, a1, a2, a3, a4); }
-        protected Object targetA5(Object a0, Object a1, Object a2, Object a3, int    a4) { return target(a0, a1, a2, a3, a4); }
-        protected Object targetA5(Object a0, Object a1, Object a2, int    a3, int    a4) { return target(a0, a1, a2, a3, a4); }
-        protected Object targetA5(Object a0, Object a1, int    a2, int    a3, int    a4) { return target(a0, a1, a2, a3, a4); }
-        protected Object targetA5(Object a0, int    a1, int    a2, int    a3, int    a4) { return target(a0, a1, a2, a3, a4); }
-        protected Object targetA5(int    a0, int    a1, int    a2, int    a3, int    a4) { return target(a0, a1, a2, a3, a4); }
-        protected Object targetA5(Object a0, Object a1, Object a2, Object a3, long   a4) { return target(a0, a1, a2, a3, a4); }
-        protected Object targetA5(Object a0, Object a1, Object a2, long   a3, long   a4) { return target(a0, a1, a2, a3, a4); }
-        protected Object targetA5(Object a0, Object a1, long   a2, long   a3, long   a4) { return target(a0, a1, a2, a3, a4); }
-        protected Object targetA5(Object a0, long   a1, long   a2, long   a3, long   a4) { return target(a0, a1, a2, a3, a4); }
-        protected Object targetA5(long   a0, long   a1, long   a2, long   a3, long   a4) { return target(a0, a1, a2, a3, a4); }
-        protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4) { return return_L(targetA5(a0, a1, a2, a3, a4)); }
-        protected int    invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4) { return return_I(targetA5(a0, a1, a2, a3, a4)); }
-        protected long   invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4) { return return_J(targetA5(a0, a1, a2, a3, a4)); }
-        protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, int    a4) { return return_L(targetA5(a0, a1, a2, a3, a4)); }
-        protected int    invoke_I(Object a0, Object a1, Object a2, Object a3, int    a4) { return return_I(targetA5(a0, a1, a2, a3, a4)); }
-        protected long   invoke_J(Object a0, Object a1, Object a2, Object a3, int    a4) { return return_J(targetA5(a0, a1, a2, a3, a4)); }
-        protected Object invoke_L(Object a0, Object a1, Object a2, int    a3, int    a4) { return return_L(targetA5(a0, a1, a2, a3, a4)); }
-        protected int    invoke_I(Object a0, Object a1, Object a2, int    a3, int    a4) { return return_I(targetA5(a0, a1, a2, a3, a4)); }
-        protected long   invoke_J(Object a0, Object a1, Object a2, int    a3, int    a4) { return return_J(targetA5(a0, a1, a2, a3, a4)); }
-        protected Object invoke_L(Object a0, Object a1, int    a2, int    a3, int    a4) { return return_L(targetA5(a0, a1, a2, a3, a4)); }
-        protected int    invoke_I(Object a0, Object a1, int    a2, int    a3, int    a4) { return return_I(targetA5(a0, a1, a2, a3, a4)); }
-        protected long   invoke_J(Object a0, Object a1, int    a2, int    a3, int    a4) { return return_J(targetA5(a0, a1, a2, a3, a4)); }
-        protected Object invoke_L(Object a0, int    a1, int    a2, int    a3, int    a4) { return return_L(targetA5(a0, a1, a2, a3, a4)); }
-        protected int    invoke_I(Object a0, int    a1, int    a2, int    a3, int    a4) { return return_I(targetA5(a0, a1, a2, a3, a4)); }
-        protected long   invoke_J(Object a0, int    a1, int    a2, int    a3, int    a4) { return return_J(targetA5(a0, a1, a2, a3, a4)); }
-        protected Object invoke_L(int    a0, int    a1, int    a2, int    a3, int    a4) { return return_L(targetA5(a0, a1, a2, a3, a4)); }
-        protected int    invoke_I(int    a0, int    a1, int    a2, int    a3, int    a4) { return return_I(targetA5(a0, a1, a2, a3, a4)); }
-        protected long   invoke_J(int    a0, int    a1, int    a2, int    a3, int    a4) { return return_J(targetA5(a0, a1, a2, a3, a4)); }
-        protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, long   a4) { return return_L(targetA5(a0, a1, a2, a3, a4)); }
-        protected int    invoke_I(Object a0, Object a1, Object a2, Object a3, long   a4) { return return_I(targetA5(a0, a1, a2, a3, a4)); }
-        protected long   invoke_J(Object a0, Object a1, Object a2, Object a3, long   a4) { return return_J(targetA5(a0, a1, a2, a3, a4)); }
-        protected Object invoke_L(Object a0, Object a1, Object a2, long   a3, long   a4) { return return_L(targetA5(a0, a1, a2, a3, a4)); }
-        protected int    invoke_I(Object a0, Object a1, Object a2, long   a3, long   a4) { return return_I(targetA5(a0, a1, a2, a3, a4)); }
-        protected long   invoke_J(Object a0, Object a1, Object a2, long   a3, long   a4) { return return_J(targetA5(a0, a1, a2, a3, a4)); }
-        protected Object invoke_L(Object a0, Object a1, long   a2, long   a3, long   a4) { return return_L(targetA5(a0, a1, a2, a3, a4)); }
-        protected int    invoke_I(Object a0, Object a1, long   a2, long   a3, long   a4) { return return_I(targetA5(a0, a1, a2, a3, a4)); }
-        protected long   invoke_J(Object a0, Object a1, long   a2, long   a3, long   a4) { return return_J(targetA5(a0, a1, a2, a3, a4)); }
-        protected Object invoke_L(Object a0, long   a1, long   a2, long   a3, long   a4) { return return_L(targetA5(a0, a1, a2, a3, a4)); }
-        protected int    invoke_I(Object a0, long   a1, long   a2, long   a3, long   a4) { return return_I(targetA5(a0, a1, a2, a3, a4)); }
-        protected long   invoke_J(Object a0, long   a1, long   a2, long   a3, long   a4) { return return_J(targetA5(a0, a1, a2, a3, a4)); }
-        protected Object invoke_L(long   a0, long   a1, long   a2, long   a3, long   a4) { return return_L(targetA5(a0, a1, a2, a3, a4)); }
-        protected int    invoke_I(long   a0, long   a1, long   a2, long   a3, long   a4) { return return_I(targetA5(a0, a1, a2, a3, a4)); }
-        protected long   invoke_J(long   a0, long   a1, long   a2, long   a3, long   a4) { return return_J(targetA5(a0, a1, a2, a3, a4)); }
+        protected Object target(Object a0, Object a1, Object a2, Object a3, Object a4)   throws Throwable { return invoker.<Object>invoke(target, a0, a1, a2, a3, a4); }
+        protected Object targetA5(Object a0, Object a1, Object a2, Object a3, Object a4) throws Throwable { return target(a0, a1, a2, a3, a4); }
+        protected Object targetA5(Object a0, Object a1, Object a2, Object a3, int    a4) throws Throwable { return target(a0, a1, a2, a3, a4); }
+        protected Object targetA5(Object a0, Object a1, Object a2, int    a3, int    a4) throws Throwable { return target(a0, a1, a2, a3, a4); }
+        protected Object targetA5(Object a0, Object a1, int    a2, int    a3, int    a4) throws Throwable { return target(a0, a1, a2, a3, a4); }
+        protected Object targetA5(Object a0, int    a1, int    a2, int    a3, int    a4) throws Throwable { return target(a0, a1, a2, a3, a4); }
+        protected Object targetA5(int    a0, int    a1, int    a2, int    a3, int    a4) throws Throwable { return target(a0, a1, a2, a3, a4); }
+        protected Object targetA5(Object a0, Object a1, Object a2, Object a3, long   a4) throws Throwable { return target(a0, a1, a2, a3, a4); }
+        protected Object targetA5(Object a0, Object a1, Object a2, long   a3, long   a4) throws Throwable { return target(a0, a1, a2, a3, a4); }
+        protected Object targetA5(Object a0, Object a1, long   a2, long   a3, long   a4) throws Throwable { return target(a0, a1, a2, a3, a4); }
+        protected Object targetA5(Object a0, long   a1, long   a2, long   a3, long   a4) throws Throwable { return target(a0, a1, a2, a3, a4); }
+        protected Object targetA5(long   a0, long   a1, long   a2, long   a3, long   a4) throws Throwable { return target(a0, a1, a2, a3, a4); }
+        protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4) throws Throwable { return return_L(targetA5(a0, a1, a2, a3, a4)); }
+        protected int    invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4) throws Throwable { return return_I(targetA5(a0, a1, a2, a3, a4)); }
+        protected long   invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4) throws Throwable { return return_J(targetA5(a0, a1, a2, a3, a4)); }
+        protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, int    a4) throws Throwable { return return_L(targetA5(a0, a1, a2, a3, a4)); }
+        protected int    invoke_I(Object a0, Object a1, Object a2, Object a3, int    a4) throws Throwable { return return_I(targetA5(a0, a1, a2, a3, a4)); }
+        protected long   invoke_J(Object a0, Object a1, Object a2, Object a3, int    a4) throws Throwable { return return_J(targetA5(a0, a1, a2, a3, a4)); }
+        protected Object invoke_L(Object a0, Object a1, Object a2, int    a3, int    a4) throws Throwable { return return_L(targetA5(a0, a1, a2, a3, a4)); }
+        protected int    invoke_I(Object a0, Object a1, Object a2, int    a3, int    a4) throws Throwable { return return_I(targetA5(a0, a1, a2, a3, a4)); }
+        protected long   invoke_J(Object a0, Object a1, Object a2, int    a3, int    a4) throws Throwable { return return_J(targetA5(a0, a1, a2, a3, a4)); }
+        protected Object invoke_L(Object a0, Object a1, int    a2, int    a3, int    a4) throws Throwable { return return_L(targetA5(a0, a1, a2, a3, a4)); }
+        protected int    invoke_I(Object a0, Object a1, int    a2, int    a3, int    a4) throws Throwable { return return_I(targetA5(a0, a1, a2, a3, a4)); }
+        protected long   invoke_J(Object a0, Object a1, int    a2, int    a3, int    a4) throws Throwable { return return_J(targetA5(a0, a1, a2, a3, a4)); }
+        protected Object invoke_L(Object a0, int    a1, int    a2, int    a3, int    a4) throws Throwable { return return_L(targetA5(a0, a1, a2, a3, a4)); }
+        protected int    invoke_I(Object a0, int    a1, int    a2, int    a3, int    a4) throws Throwable { return return_I(targetA5(a0, a1, a2, a3, a4)); }
+        protected long   invoke_J(Object a0, int    a1, int    a2, int    a3, int    a4) throws Throwable { return return_J(targetA5(a0, a1, a2, a3, a4)); }
+        protected Object invoke_L(int    a0, int    a1, int    a2, int    a3, int    a4) throws Throwable { return return_L(targetA5(a0, a1, a2, a3, a4)); }
+        protected int    invoke_I(int    a0, int    a1, int    a2, int    a3, int    a4) throws Throwable { return return_I(targetA5(a0, a1, a2, a3, a4)); }
+        protected long   invoke_J(int    a0, int    a1, int    a2, int    a3, int    a4) throws Throwable { return return_J(targetA5(a0, a1, a2, a3, a4)); }
+        protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, long   a4) throws Throwable { return return_L(targetA5(a0, a1, a2, a3, a4)); }
+        protected int    invoke_I(Object a0, Object a1, Object a2, Object a3, long   a4) throws Throwable { return return_I(targetA5(a0, a1, a2, a3, a4)); }
+        protected long   invoke_J(Object a0, Object a1, Object a2, Object a3, long   a4) throws Throwable { return return_J(targetA5(a0, a1, a2, a3, a4)); }
+        protected Object invoke_L(Object a0, Object a1, Object a2, long   a3, long   a4) throws Throwable { return return_L(targetA5(a0, a1, a2, a3, a4)); }
+        protected int    invoke_I(Object a0, Object a1, Object a2, long   a3, long   a4) throws Throwable { return return_I(targetA5(a0, a1, a2, a3, a4)); }
+        protected long   invoke_J(Object a0, Object a1, Object a2, long   a3, long   a4) throws Throwable { return return_J(targetA5(a0, a1, a2, a3, a4)); }
+        protected Object invoke_L(Object a0, Object a1, long   a2, long   a3, long   a4) throws Throwable { return return_L(targetA5(a0, a1, a2, a3, a4)); }
+        protected int    invoke_I(Object a0, Object a1, long   a2, long   a3, long   a4) throws Throwable { return return_I(targetA5(a0, a1, a2, a3, a4)); }
+        protected long   invoke_J(Object a0, Object a1, long   a2, long   a3, long   a4) throws Throwable { return return_J(targetA5(a0, a1, a2, a3, a4)); }
+        protected Object invoke_L(Object a0, long   a1, long   a2, long   a3, long   a4) throws Throwable { return return_L(targetA5(a0, a1, a2, a3, a4)); }
+        protected int    invoke_I(Object a0, long   a1, long   a2, long   a3, long   a4) throws Throwable { return return_I(targetA5(a0, a1, a2, a3, a4)); }
+        protected long   invoke_J(Object a0, long   a1, long   a2, long   a3, long   a4) throws Throwable { return return_J(targetA5(a0, a1, a2, a3, a4)); }
+        protected Object invoke_L(long   a0, long   a1, long   a2, long   a3, long   a4) throws Throwable { return return_L(targetA5(a0, a1, a2, a3, a4)); }
+        protected int    invoke_I(long   a0, long   a1, long   a2, long   a3, long   a4) throws Throwable { return return_I(targetA5(a0, a1, a2, a3, a4)); }
+        protected long   invoke_J(long   a0, long   a1, long   a2, long   a3, long   a4) throws Throwable { return return_J(targetA5(a0, a1, a2, a3, a4)); }
     }
 //params=[6, 10, 2, 99, 0, 99]
     static class A6 extends Adapter {
         protected A6(MethodHandle entryPoint) { super(entryPoint); }  // to build prototype
         protected A6(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { super(e, i, c, t); }
         protected A6 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { return new A6(e, i, c, t); }
-        protected Object target(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5)   { return invoker.<Object>invoke(target, a0, a1, a2, a3, a4, a5); }
-        protected Object targetA6(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) { return target(a0, a1, a2, a3, a4, a5); }
-        protected Object targetA6(Object a0, Object a1, Object a2, Object a3, Object a4, long   a5) { return target(a0, a1, a2, a3, a4, a5); }
-        protected Object targetA6(Object a0, Object a1, Object a2, Object a3, long   a4, long   a5) { return target(a0, a1, a2, a3, a4, a5); }
-        protected Object targetA6(Object a0, Object a1, Object a2, long   a3, long   a4, long   a5) { return target(a0, a1, a2, a3, a4, a5); }
-        protected Object targetA6(Object a0, Object a1, long   a2, long   a3, long   a4, long   a5) { return target(a0, a1, a2, a3, a4, a5); }
-        protected Object targetA6(Object a0, long   a1, long   a2, long   a3, long   a4, long   a5) { return target(a0, a1, a2, a3, a4, a5); }
-        protected Object targetA6(long   a0, long   a1, long   a2, long   a3, long   a4, long   a5) { return target(a0, a1, a2, a3, a4, a5); }
-        protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) { return return_L(targetA6(a0, a1, a2, a3, a4, a5)); }
-        protected int    invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) { return return_I(targetA6(a0, a1, a2, a3, a4, a5)); }
-        protected long   invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) { return return_J(targetA6(a0, a1, a2, a3, a4, a5)); }
-        protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, long   a5) { return return_L(targetA6(a0, a1, a2, a3, a4, a5)); }
-        protected int    invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, long   a5) { return return_I(targetA6(a0, a1, a2, a3, a4, a5)); }
-        protected long   invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, long   a5) { return return_J(targetA6(a0, a1, a2, a3, a4, a5)); }
-        protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, long   a4, long   a5) { return return_L(targetA6(a0, a1, a2, a3, a4, a5)); }
-        protected int    invoke_I(Object a0, Object a1, Object a2, Object a3, long   a4, long   a5) { return return_I(targetA6(a0, a1, a2, a3, a4, a5)); }
-        protected long   invoke_J(Object a0, Object a1, Object a2, Object a3, long   a4, long   a5) { return return_J(targetA6(a0, a1, a2, a3, a4, a5)); }
-        protected Object invoke_L(Object a0, Object a1, Object a2, long   a3, long   a4, long   a5) { return return_L(targetA6(a0, a1, a2, a3, a4, a5)); }
-        protected int    invoke_I(Object a0, Object a1, Object a2, long   a3, long   a4, long   a5) { return return_I(targetA6(a0, a1, a2, a3, a4, a5)); }
-        protected long   invoke_J(Object a0, Object a1, Object a2, long   a3, long   a4, long   a5) { return return_J(targetA6(a0, a1, a2, a3, a4, a5)); }
-        protected Object invoke_L(Object a0, Object a1, long   a2, long   a3, long   a4, long   a5) { return return_L(targetA6(a0, a1, a2, a3, a4, a5)); }
-        protected int    invoke_I(Object a0, Object a1, long   a2, long   a3, long   a4, long   a5) { return return_I(targetA6(a0, a1, a2, a3, a4, a5)); }
-        protected long   invoke_J(Object a0, Object a1, long   a2, long   a3, long   a4, long   a5) { return return_J(targetA6(a0, a1, a2, a3, a4, a5)); }
-        protected Object invoke_L(Object a0, long   a1, long   a2, long   a3, long   a4, long   a5) { return return_L(targetA6(a0, a1, a2, a3, a4, a5)); }
-        protected int    invoke_I(Object a0, long   a1, long   a2, long   a3, long   a4, long   a5) { return return_I(targetA6(a0, a1, a2, a3, a4, a5)); }
-        protected long   invoke_J(Object a0, long   a1, long   a2, long   a3, long   a4, long   a5) { return return_J(targetA6(a0, a1, a2, a3, a4, a5)); }
-        protected Object invoke_L(long   a0, long   a1, long   a2, long   a3, long   a4, long   a5) { return return_L(targetA6(a0, a1, a2, a3, a4, a5)); }
-        protected int    invoke_I(long   a0, long   a1, long   a2, long   a3, long   a4, long   a5) { return return_I(targetA6(a0, a1, a2, a3, a4, a5)); }
-        protected long   invoke_J(long   a0, long   a1, long   a2, long   a3, long   a4, long   a5) { return return_J(targetA6(a0, a1, a2, a3, a4, a5)); }
+        protected Object target(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5)   throws Throwable { return invoker.<Object>invoke(target, a0, a1, a2, a3, a4, a5); }
+        protected Object targetA6(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) throws Throwable { return target(a0, a1, a2, a3, a4, a5); }
+        protected Object targetA6(Object a0, Object a1, Object a2, Object a3, Object a4, long   a5) throws Throwable { return target(a0, a1, a2, a3, a4, a5); }
+        protected Object targetA6(Object a0, Object a1, Object a2, Object a3, long   a4, long   a5) throws Throwable { return target(a0, a1, a2, a3, a4, a5); }
+        protected Object targetA6(Object a0, Object a1, Object a2, long   a3, long   a4, long   a5) throws Throwable { return target(a0, a1, a2, a3, a4, a5); }
+        protected Object targetA6(Object a0, Object a1, long   a2, long   a3, long   a4, long   a5) throws Throwable { return target(a0, a1, a2, a3, a4, a5); }
+        protected Object targetA6(Object a0, long   a1, long   a2, long   a3, long   a4, long   a5) throws Throwable { return target(a0, a1, a2, a3, a4, a5); }
+        protected Object targetA6(long   a0, long   a1, long   a2, long   a3, long   a4, long   a5) throws Throwable { return target(a0, a1, a2, a3, a4, a5); }
+        protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) throws Throwable { return return_L(targetA6(a0, a1, a2, a3, a4, a5)); }
+        protected int    invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) throws Throwable { return return_I(targetA6(a0, a1, a2, a3, a4, a5)); }
+        protected long   invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) throws Throwable { return return_J(targetA6(a0, a1, a2, a3, a4, a5)); }
+        protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, long   a5) throws Throwable { return return_L(targetA6(a0, a1, a2, a3, a4, a5)); }
+        protected int    invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, long   a5) throws Throwable { return return_I(targetA6(a0, a1, a2, a3, a4, a5)); }
+        protected long   invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, long   a5) throws Throwable { return return_J(targetA6(a0, a1, a2, a3, a4, a5)); }
+        protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, long   a4, long   a5) throws Throwable { return return_L(targetA6(a0, a1, a2, a3, a4, a5)); }
+        protected int    invoke_I(Object a0, Object a1, Object a2, Object a3, long   a4, long   a5) throws Throwable { return return_I(targetA6(a0, a1, a2, a3, a4, a5)); }
+        protected long   invoke_J(Object a0, Object a1, Object a2, Object a3, long   a4, long   a5) throws Throwable { return return_J(targetA6(a0, a1, a2, a3, a4, a5)); }
+        protected Object invoke_L(Object a0, Object a1, Object a2, long   a3, long   a4, long   a5) throws Throwable { return return_L(targetA6(a0, a1, a2, a3, a4, a5)); }
+        protected int    invoke_I(Object a0, Object a1, Object a2, long   a3, long   a4, long   a5) throws Throwable { return return_I(targetA6(a0, a1, a2, a3, a4, a5)); }
+        protected long   invoke_J(Object a0, Object a1, Object a2, long   a3, long   a4, long   a5) throws Throwable { return return_J(targetA6(a0, a1, a2, a3, a4, a5)); }
+        protected Object invoke_L(Object a0, Object a1, long   a2, long   a3, long   a4, long   a5) throws Throwable { return return_L(targetA6(a0, a1, a2, a3, a4, a5)); }
+        protected int    invoke_I(Object a0, Object a1, long   a2, long   a3, long   a4, long   a5) throws Throwable { return return_I(targetA6(a0, a1, a2, a3, a4, a5)); }
+        protected long   invoke_J(Object a0, Object a1, long   a2, long   a3, long   a4, long   a5) throws Throwable { return return_J(targetA6(a0, a1, a2, a3, a4, a5)); }
+        protected Object invoke_L(Object a0, long   a1, long   a2, long   a3, long   a4, long   a5) throws Throwable { return return_L(targetA6(a0, a1, a2, a3, a4, a5)); }
+        protected int    invoke_I(Object a0, long   a1, long   a2, long   a3, long   a4, long   a5) throws Throwable { return return_I(targetA6(a0, a1, a2, a3, a4, a5)); }
+        protected long   invoke_J(Object a0, long   a1, long   a2, long   a3, long   a4, long   a5) throws Throwable { return return_J(targetA6(a0, a1, a2, a3, a4, a5)); }
+        protected Object invoke_L(long   a0, long   a1, long   a2, long   a3, long   a4, long   a5) throws Throwable { return return_L(targetA6(a0, a1, a2, a3, a4, a5)); }
+        protected int    invoke_I(long   a0, long   a1, long   a2, long   a3, long   a4, long   a5) throws Throwable { return return_I(targetA6(a0, a1, a2, a3, a4, a5)); }
+        protected long   invoke_J(long   a0, long   a1, long   a2, long   a3, long   a4, long   a5) throws Throwable { return return_J(targetA6(a0, a1, a2, a3, a4, a5)); }
     }
     static class A7 extends Adapter {
         protected A7(MethodHandle entryPoint) { super(entryPoint); }  // to build prototype
         protected A7(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { super(e, i, c, t); }
         protected A7 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { return new A7(e, i, c, t); }
-        protected Object target(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6)   { return invoker.<Object>invoke(target, a0, a1, a2, a3, a4, a5, a6); }
-        protected Object targetA7(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) { return target(a0, a1, a2, a3, a4, a5, a6); }
-        protected Object targetA7(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, long   a6) { return target(a0, a1, a2, a3, a4, a5, a6); }
-        protected Object targetA7(Object a0, Object a1, Object a2, Object a3, Object a4, long   a5, long   a6) { return target(a0, a1, a2, a3, a4, a5, a6); }
-        protected Object targetA7(Object a0, Object a1, Object a2, Object a3, long   a4, long   a5, long   a6) { return target(a0, a1, a2, a3, a4, a5, a6); }
-        protected Object targetA7(Object a0, Object a1, Object a2, long   a3, long   a4, long   a5, long   a6) { return target(a0, a1, a2, a3, a4, a5, a6); }
-        protected Object targetA7(Object a0, Object a1, long   a2, long   a3, long   a4, long   a5, long   a6) { return target(a0, a1, a2, a3, a4, a5, a6); }
-        protected Object targetA7(Object a0, long   a1, long   a2, long   a3, long   a4, long   a5, long   a6) { return target(a0, a1, a2, a3, a4, a5, a6); }
-        protected Object targetA7(long   a0, long   a1, long   a2, long   a3, long   a4, long   a5, long   a6) { return target(a0, a1, a2, a3, a4, a5, a6); }
-        protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) { return return_L(targetA7(a0, a1, a2, a3, a4, a5, a6)); }
-        protected int    invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) { return return_I(targetA7(a0, a1, a2, a3, a4, a5, a6)); }
-        protected long   invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) { return return_J(targetA7(a0, a1, a2, a3, a4, a5, a6)); }
-        protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, long   a6) { return return_L(targetA7(a0, a1, a2, a3, a4, a5, a6)); }
-        protected int    invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, long   a6) { return return_I(targetA7(a0, a1, a2, a3, a4, a5, a6)); }
-        protected long   invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, long   a6) { return return_J(targetA7(a0, a1, a2, a3, a4, a5, a6)); }
-        protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, long   a5, long   a6) { return return_L(targetA7(a0, a1, a2, a3, a4, a5, a6)); }
-        protected int    invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, long   a5, long   a6) { return return_I(targetA7(a0, a1, a2, a3, a4, a5, a6)); }
-        protected long   invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, long   a5, long   a6) { return return_J(targetA7(a0, a1, a2, a3, a4, a5, a6)); }
-        protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, long   a4, long   a5, long   a6) { return return_L(targetA7(a0, a1, a2, a3, a4, a5, a6)); }
-        protected int    invoke_I(Object a0, Object a1, Object a2, Object a3, long   a4, long   a5, long   a6) { return return_I(targetA7(a0, a1, a2, a3, a4, a5, a6)); }
-        protected long   invoke_J(Object a0, Object a1, Object a2, Object a3, long   a4, long   a5, long   a6) { return return_J(targetA7(a0, a1, a2, a3, a4, a5, a6)); }
-        protected Object invoke_L(Object a0, Object a1, Object a2, long   a3, long   a4, long   a5, long   a6) { return return_L(targetA7(a0, a1, a2, a3, a4, a5, a6)); }
-        protected int    invoke_I(Object a0, Object a1, Object a2, long   a3, long   a4, long   a5, long   a6) { return return_I(targetA7(a0, a1, a2, a3, a4, a5, a6)); }
-        protected long   invoke_J(Object a0, Object a1, Object a2, long   a3, long   a4, long   a5, long   a6) { return return_J(targetA7(a0, a1, a2, a3, a4, a5, a6)); }
-        protected Object invoke_L(Object a0, Object a1, long   a2, long   a3, long   a4, long   a5, long   a6) { return return_L(targetA7(a0, a1, a2, a3, a4, a5, a6)); }
-        protected int    invoke_I(Object a0, Object a1, long   a2, long   a3, long   a4, long   a5, long   a6) { return return_I(targetA7(a0, a1, a2, a3, a4, a5, a6)); }
-        protected long   invoke_J(Object a0, Object a1, long   a2, long   a3, long   a4, long   a5, long   a6) { return return_J(targetA7(a0, a1, a2, a3, a4, a5, a6)); }
-        protected Object invoke_L(Object a0, long   a1, long   a2, long   a3, long   a4, long   a5, long   a6) { return return_L(targetA7(a0, a1, a2, a3, a4, a5, a6)); }
-        protected int    invoke_I(Object a0, long   a1, long   a2, long   a3, long   a4, long   a5, long   a6) { return return_I(targetA7(a0, a1, a2, a3, a4, a5, a6)); }
-        protected long   invoke_J(Object a0, long   a1, long   a2, long   a3, long   a4, long   a5, long   a6) { return return_J(targetA7(a0, a1, a2, a3, a4, a5, a6)); }
-        protected Object invoke_L(long   a0, long   a1, long   a2, long   a3, long   a4, long   a5, long   a6) { return return_L(targetA7(a0, a1, a2, a3, a4, a5, a6)); }
-        protected int    invoke_I(long   a0, long   a1, long   a2, long   a3, long   a4, long   a5, long   a6) { return return_I(targetA7(a0, a1, a2, a3, a4, a5, a6)); }
-        protected long   invoke_J(long   a0, long   a1, long   a2, long   a3, long   a4, long   a5, long   a6) { return return_J(targetA7(a0, a1, a2, a3, a4, a5, a6)); }
+        protected Object target(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6)   throws Throwable { return invoker.<Object>invoke(target, a0, a1, a2, a3, a4, a5, a6); }
+        protected Object targetA7(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6); }
+        protected Object targetA7(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, long   a6) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6); }
+        protected Object targetA7(Object a0, Object a1, Object a2, Object a3, Object a4, long   a5, long   a6) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6); }
+        protected Object targetA7(Object a0, Object a1, Object a2, Object a3, long   a4, long   a5, long   a6) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6); }
+        protected Object targetA7(Object a0, Object a1, Object a2, long   a3, long   a4, long   a5, long   a6) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6); }
+        protected Object targetA7(Object a0, Object a1, long   a2, long   a3, long   a4, long   a5, long   a6) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6); }
+        protected Object targetA7(Object a0, long   a1, long   a2, long   a3, long   a4, long   a5, long   a6) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6); }
+        protected Object targetA7(long   a0, long   a1, long   a2, long   a3, long   a4, long   a5, long   a6) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6); }
+        protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) throws Throwable { return return_L(targetA7(a0, a1, a2, a3, a4, a5, a6)); }
+        protected int    invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) throws Throwable { return return_I(targetA7(a0, a1, a2, a3, a4, a5, a6)); }
+        protected long   invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) throws Throwable { return return_J(targetA7(a0, a1, a2, a3, a4, a5, a6)); }
+        protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, long   a6) throws Throwable { return return_L(targetA7(a0, a1, a2, a3, a4, a5, a6)); }
+        protected int    invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, long   a6) throws Throwable { return return_I(targetA7(a0, a1, a2, a3, a4, a5, a6)); }
+        protected long   invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, long   a6) throws Throwable { return return_J(targetA7(a0, a1, a2, a3, a4, a5, a6)); }
+        protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, long   a5, long   a6) throws Throwable { return return_L(targetA7(a0, a1, a2, a3, a4, a5, a6)); }
+        protected int    invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, long   a5, long   a6) throws Throwable { return return_I(targetA7(a0, a1, a2, a3, a4, a5, a6)); }
+        protected long   invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, long   a5, long   a6) throws Throwable { return return_J(targetA7(a0, a1, a2, a3, a4, a5, a6)); }
+        protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, long   a4, long   a5, long   a6) throws Throwable { return return_L(targetA7(a0, a1, a2, a3, a4, a5, a6)); }
+        protected int    invoke_I(Object a0, Object a1, Object a2, Object a3, long   a4, long   a5, long   a6) throws Throwable { return return_I(targetA7(a0, a1, a2, a3, a4, a5, a6)); }
+        protected long   invoke_J(Object a0, Object a1, Object a2, Object a3, long   a4, long   a5, long   a6) throws Throwable { return return_J(targetA7(a0, a1, a2, a3, a4, a5, a6)); }
+        protected Object invoke_L(Object a0, Object a1, Object a2, long   a3, long   a4, long   a5, long   a6) throws Throwable { return return_L(targetA7(a0, a1, a2, a3, a4, a5, a6)); }
+        protected int    invoke_I(Object a0, Object a1, Object a2, long   a3, long   a4, long   a5, long   a6) throws Throwable { return return_I(targetA7(a0, a1, a2, a3, a4, a5, a6)); }
+        protected long   invoke_J(Object a0, Object a1, Object a2, long   a3, long   a4, long   a5, long   a6) throws Throwable { return return_J(targetA7(a0, a1, a2, a3, a4, a5, a6)); }
+        protected Object invoke_L(Object a0, Object a1, long   a2, long   a3, long   a4, long   a5, long   a6) throws Throwable { return return_L(targetA7(a0, a1, a2, a3, a4, a5, a6)); }
+        protected int    invoke_I(Object a0, Object a1, long   a2, long   a3, long   a4, long   a5, long   a6) throws Throwable { return return_I(targetA7(a0, a1, a2, a3, a4, a5, a6)); }
+        protected long   invoke_J(Object a0, Object a1, long   a2, long   a3, long   a4, long   a5, long   a6) throws Throwable { return return_J(targetA7(a0, a1, a2, a3, a4, a5, a6)); }
+        protected Object invoke_L(Object a0, long   a1, long   a2, long   a3, long   a4, long   a5, long   a6) throws Throwable { return return_L(targetA7(a0, a1, a2, a3, a4, a5, a6)); }
+        protected int    invoke_I(Object a0, long   a1, long   a2, long   a3, long   a4, long   a5, long   a6) throws Throwable { return return_I(targetA7(a0, a1, a2, a3, a4, a5, a6)); }
+        protected long   invoke_J(Object a0, long   a1, long   a2, long   a3, long   a4, long   a5, long   a6) throws Throwable { return return_J(targetA7(a0, a1, a2, a3, a4, a5, a6)); }
+        protected Object invoke_L(long   a0, long   a1, long   a2, long   a3, long   a4, long   a5, long   a6) throws Throwable { return return_L(targetA7(a0, a1, a2, a3, a4, a5, a6)); }
+        protected int    invoke_I(long   a0, long   a1, long   a2, long   a3, long   a4, long   a5, long   a6) throws Throwable { return return_I(targetA7(a0, a1, a2, a3, a4, a5, a6)); }
+        protected long   invoke_J(long   a0, long   a1, long   a2, long   a3, long   a4, long   a5, long   a6) throws Throwable { return return_J(targetA7(a0, a1, a2, a3, a4, a5, a6)); }
     }
     static class A8 extends Adapter {
         protected A8(MethodHandle entryPoint) { super(entryPoint); }  // to build prototype
         protected A8(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { super(e, i, c, t); }
         protected A8 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { return new A8(e, i, c, t); }
-        protected Object target(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7)   { return invoker.<Object>invoke(target, a0, a1, a2, a3, a4, a5, a6, a7); }
-        protected Object targetA8(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) { return target(a0, a1, a2, a3, a4, a5, a6, a7); }
-        protected Object targetA8(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, long   a7) { return target(a0, a1, a2, a3, a4, a5, a6, a7); }
-        protected Object targetA8(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, long   a6, long   a7) { return target(a0, a1, a2, a3, a4, a5, a6, a7); }
-        protected Object targetA8(Object a0, Object a1, Object a2, Object a3, Object a4, long   a5, long   a6, long   a7) { return target(a0, a1, a2, a3, a4, a5, a6, a7); }
-        protected Object targetA8(Object a0, Object a1, Object a2, Object a3, long   a4, long   a5, long   a6, long   a7) { return target(a0, a1, a2, a3, a4, a5, a6, a7); }
-        protected Object targetA8(Object a0, Object a1, Object a2, long   a3, long   a4, long   a5, long   a6, long   a7) { return target(a0, a1, a2, a3, a4, a5, a6, a7); }
-        protected Object targetA8(Object a0, Object a1, long   a2, long   a3, long   a4, long   a5, long   a6, long   a7) { return target(a0, a1, a2, a3, a4, a5, a6, a7); }
-        protected Object targetA8(Object a0, long   a1, long   a2, long   a3, long   a4, long   a5, long   a6, long   a7) { return target(a0, a1, a2, a3, a4, a5, a6, a7); }
-        protected Object targetA8(long   a0, long   a1, long   a2, long   a3, long   a4, long   a5, long   a6, long   a7) { return target(a0, a1, a2, a3, a4, a5, a6, a7); }
-        protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) { return return_L(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
-        protected int    invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) { return return_I(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
-        protected long   invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) { return return_J(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
-        protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, long   a7) { return return_L(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
-        protected int    invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, long   a7) { return return_I(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
-        protected long   invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, long   a7) { return return_J(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
-        protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, long   a6, long   a7) { return return_L(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
-        protected int    invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, long   a6, long   a7) { return return_I(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
-        protected long   invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, long   a6, long   a7) { return return_J(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
-        protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, long   a5, long   a6, long   a7) { return return_L(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
-        protected int    invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, long   a5, long   a6, long   a7) { return return_I(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
-        protected long   invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, long   a5, long   a6, long   a7) { return return_J(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
-        protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, long   a4, long   a5, long   a6, long   a7) { return return_L(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
-        protected int    invoke_I(Object a0, Object a1, Object a2, Object a3, long   a4, long   a5, long   a6, long   a7) { return return_I(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
-        protected long   invoke_J(Object a0, Object a1, Object a2, Object a3, long   a4, long   a5, long   a6, long   a7) { return return_J(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
-        protected Object invoke_L(Object a0, Object a1, Object a2, long   a3, long   a4, long   a5, long   a6, long   a7) { return return_L(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
-        protected int    invoke_I(Object a0, Object a1, Object a2, long   a3, long   a4, long   a5, long   a6, long   a7) { return return_I(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
-        protected long   invoke_J(Object a0, Object a1, Object a2, long   a3, long   a4, long   a5, long   a6, long   a7) { return return_J(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
-        protected Object invoke_L(Object a0, Object a1, long   a2, long   a3, long   a4, long   a5, long   a6, long   a7) { return return_L(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
-        protected int    invoke_I(Object a0, Object a1, long   a2, long   a3, long   a4, long   a5, long   a6, long   a7) { return return_I(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
-        protected long   invoke_J(Object a0, Object a1, long   a2, long   a3, long   a4, long   a5, long   a6, long   a7) { return return_J(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
-        protected Object invoke_L(Object a0, long   a1, long   a2, long   a3, long   a4, long   a5, long   a6, long   a7) { return return_L(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
-        protected int    invoke_I(Object a0, long   a1, long   a2, long   a3, long   a4, long   a5, long   a6, long   a7) { return return_I(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
-        protected long   invoke_J(Object a0, long   a1, long   a2, long   a3, long   a4, long   a5, long   a6, long   a7) { return return_J(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
-        protected Object invoke_L(long   a0, long   a1, long   a2, long   a3, long   a4, long   a5, long   a6, long   a7) { return return_L(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
-        protected int    invoke_I(long   a0, long   a1, long   a2, long   a3, long   a4, long   a5, long   a6, long   a7) { return return_I(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
-        protected long   invoke_J(long   a0, long   a1, long   a2, long   a3, long   a4, long   a5, long   a6, long   a7) { return return_J(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
+        protected Object target(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7)   throws Throwable { return invoker.<Object>invoke(target, a0, a1, a2, a3, a4, a5, a6, a7); }
+        protected Object targetA8(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7); }
+        protected Object targetA8(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, long   a7) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7); }
+        protected Object targetA8(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, long   a6, long   a7) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7); }
+        protected Object targetA8(Object a0, Object a1, Object a2, Object a3, Object a4, long   a5, long   a6, long   a7) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7); }
+        protected Object targetA8(Object a0, Object a1, Object a2, Object a3, long   a4, long   a5, long   a6, long   a7) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7); }
+        protected Object targetA8(Object a0, Object a1, Object a2, long   a3, long   a4, long   a5, long   a6, long   a7) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7); }
+        protected Object targetA8(Object a0, Object a1, long   a2, long   a3, long   a4, long   a5, long   a6, long   a7) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7); }
+        protected Object targetA8(Object a0, long   a1, long   a2, long   a3, long   a4, long   a5, long   a6, long   a7) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7); }
+        protected Object targetA8(long   a0, long   a1, long   a2, long   a3, long   a4, long   a5, long   a6, long   a7) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7); }
+        protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) throws Throwable { return return_L(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
+        protected int    invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) throws Throwable { return return_I(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
+        protected long   invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) throws Throwable { return return_J(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
+        protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, long   a7) throws Throwable { return return_L(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
+        protected int    invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, long   a7) throws Throwable { return return_I(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
+        protected long   invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, long   a7) throws Throwable { return return_J(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
+        protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, long   a6, long   a7) throws Throwable { return return_L(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
+        protected int    invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, long   a6, long   a7) throws Throwable { return return_I(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
+        protected long   invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, long   a6, long   a7) throws Throwable { return return_J(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
+        protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, long   a5, long   a6, long   a7) throws Throwable { return return_L(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
+        protected int    invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, long   a5, long   a6, long   a7) throws Throwable { return return_I(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
+        protected long   invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, long   a5, long   a6, long   a7) throws Throwable { return return_J(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
+        protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, long   a4, long   a5, long   a6, long   a7) throws Throwable { return return_L(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
+        protected int    invoke_I(Object a0, Object a1, Object a2, Object a3, long   a4, long   a5, long   a6, long   a7) throws Throwable { return return_I(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
+        protected long   invoke_J(Object a0, Object a1, Object a2, Object a3, long   a4, long   a5, long   a6, long   a7) throws Throwable { return return_J(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
+        protected Object invoke_L(Object a0, Object a1, Object a2, long   a3, long   a4, long   a5, long   a6, long   a7) throws Throwable { return return_L(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
+        protected int    invoke_I(Object a0, Object a1, Object a2, long   a3, long   a4, long   a5, long   a6, long   a7) throws Throwable { return return_I(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
+        protected long   invoke_J(Object a0, Object a1, Object a2, long   a3, long   a4, long   a5, long   a6, long   a7) throws Throwable { return return_J(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
+        protected Object invoke_L(Object a0, Object a1, long   a2, long   a3, long   a4, long   a5, long   a6, long   a7) throws Throwable { return return_L(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
+        protected int    invoke_I(Object a0, Object a1, long   a2, long   a3, long   a4, long   a5, long   a6, long   a7) throws Throwable { return return_I(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
+        protected long   invoke_J(Object a0, Object a1, long   a2, long   a3, long   a4, long   a5, long   a6, long   a7) throws Throwable { return return_J(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
+        protected Object invoke_L(Object a0, long   a1, long   a2, long   a3, long   a4, long   a5, long   a6, long   a7) throws Throwable { return return_L(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
+        protected int    invoke_I(Object a0, long   a1, long   a2, long   a3, long   a4, long   a5, long   a6, long   a7) throws Throwable { return return_I(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
+        protected long   invoke_J(Object a0, long   a1, long   a2, long   a3, long   a4, long   a5, long   a6, long   a7) throws Throwable { return return_J(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
+        protected Object invoke_L(long   a0, long   a1, long   a2, long   a3, long   a4, long   a5, long   a6, long   a7) throws Throwable { return return_L(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
+        protected int    invoke_I(long   a0, long   a1, long   a2, long   a3, long   a4, long   a5, long   a6, long   a7) throws Throwable { return return_I(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
+        protected long   invoke_J(long   a0, long   a1, long   a2, long   a3, long   a4, long   a5, long   a6, long   a7) throws Throwable { return return_J(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
     }
     static class A9 extends Adapter {
         protected A9(MethodHandle entryPoint) { super(entryPoint); }  // to build prototype
         protected A9(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { super(e, i, c, t); }
         protected A9 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { return new A9(e, i, c, t); }
-        protected Object target(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8)   { return invoker.<Object>invoke(target, a0, a1, a2, a3, a4, a5, a6, a7, a8); }
-        protected Object targetA9(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8) { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8); }
-        protected Object targetA9(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, long   a8) { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8); }
-        protected Object targetA9(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, long   a7, long   a8) { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8); }
-        protected Object targetA9(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, long   a6, long   a7, long   a8) { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8); }
-        protected Object targetA9(Object a0, Object a1, Object a2, Object a3, Object a4, long   a5, long   a6, long   a7, long   a8) { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8); }
-        protected Object targetA9(Object a0, Object a1, Object a2, Object a3, long   a4, long   a5, long   a6, long   a7, long   a8) { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8); }
-        protected Object targetA9(Object a0, Object a1, Object a2, long   a3, long   a4, long   a5, long   a6, long   a7, long   a8) { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8); }
-        protected Object targetA9(Object a0, Object a1, long   a2, long   a3, long   a4, long   a5, long   a6, long   a7, long   a8) { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8); }
-        protected Object targetA9(Object a0, long   a1, long   a2, long   a3, long   a4, long   a5, long   a6, long   a7, long   a8) { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8); }
-        protected Object targetA9(long   a0, long   a1, long   a2, long   a3, long   a4, long   a5, long   a6, long   a7, long   a8) { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8); }
-        protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8) { return return_L(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
-        protected int    invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8) { return return_I(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
-        protected long   invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8) { return return_J(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
-        protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, long   a8) { return return_L(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
-        protected int    invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, long   a8) { return return_I(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
-        protected long   invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, long   a8) { return return_J(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
-        protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, long   a7, long   a8) { return return_L(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
-        protected int    invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, long   a7, long   a8) { return return_I(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
-        protected long   invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, long   a7, long   a8) { return return_J(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
-        protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, long   a6, long   a7, long   a8) { return return_L(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
-        protected int    invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, long   a6, long   a7, long   a8) { return return_I(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
-        protected long   invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, long   a6, long   a7, long   a8) { return return_J(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
-        protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, long   a5, long   a6, long   a7, long   a8) { return return_L(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
-        protected int    invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, long   a5, long   a6, long   a7, long   a8) { return return_I(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
-        protected long   invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, long   a5, long   a6, long   a7, long   a8) { return return_J(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
-        protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, long   a4, long   a5, long   a6, long   a7, long   a8) { return return_L(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
-        protected int    invoke_I(Object a0, Object a1, Object a2, Object a3, long   a4, long   a5, long   a6, long   a7, long   a8) { return return_I(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
-        protected long   invoke_J(Object a0, Object a1, Object a2, Object a3, long   a4, long   a5, long   a6, long   a7, long   a8) { return return_J(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
-        protected Object invoke_L(Object a0, Object a1, Object a2, long   a3, long   a4, long   a5, long   a6, long   a7, long   a8) { return return_L(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
-        protected int    invoke_I(Object a0, Object a1, Object a2, long   a3, long   a4, long   a5, long   a6, long   a7, long   a8) { return return_I(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
-        protected long   invoke_J(Object a0, Object a1, Object a2, long   a3, long   a4, long   a5, long   a6, long   a7, long   a8) { return return_J(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
-        protected Object invoke_L(Object a0, Object a1, long   a2, long   a3, long   a4, long   a5, long   a6, long   a7, long   a8) { return return_L(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
-        protected int    invoke_I(Object a0, Object a1, long   a2, long   a3, long   a4, long   a5, long   a6, long   a7, long   a8) { return return_I(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
-        protected long   invoke_J(Object a0, Object a1, long   a2, long   a3, long   a4, long   a5, long   a6, long   a7, long   a8) { return return_J(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
-        protected Object invoke_L(Object a0, long   a1, long   a2, long   a3, long   a4, long   a5, long   a6, long   a7, long   a8) { return return_L(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
-        protected int    invoke_I(Object a0, long   a1, long   a2, long   a3, long   a4, long   a5, long   a6, long   a7, long   a8) { return return_I(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
-        protected long   invoke_J(Object a0, long   a1, long   a2, long   a3, long   a4, long   a5, long   a6, long   a7, long   a8) { return return_J(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
-        protected Object invoke_L(long   a0, long   a1, long   a2, long   a3, long   a4, long   a5, long   a6, long   a7, long   a8) { return return_L(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
-        protected int    invoke_I(long   a0, long   a1, long   a2, long   a3, long   a4, long   a5, long   a6, long   a7, long   a8) { return return_I(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
-        protected long   invoke_J(long   a0, long   a1, long   a2, long   a3, long   a4, long   a5, long   a6, long   a7, long   a8) { return return_J(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
+        protected Object target(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8)   throws Throwable { return invoker.<Object>invoke(target, a0, a1, a2, a3, a4, a5, a6, a7, a8); }
+        protected Object targetA9(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8); }
+        protected Object targetA9(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, long   a8) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8); }
+        protected Object targetA9(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, long   a7, long   a8) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8); }
+        protected Object targetA9(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, long   a6, long   a7, long   a8) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8); }
+        protected Object targetA9(Object a0, Object a1, Object a2, Object a3, Object a4, long   a5, long   a6, long   a7, long   a8) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8); }
+        protected Object targetA9(Object a0, Object a1, Object a2, Object a3, long   a4, long   a5, long   a6, long   a7, long   a8) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8); }
+        protected Object targetA9(Object a0, Object a1, Object a2, long   a3, long   a4, long   a5, long   a6, long   a7, long   a8) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8); }
+        protected Object targetA9(Object a0, Object a1, long   a2, long   a3, long   a4, long   a5, long   a6, long   a7, long   a8) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8); }
+        protected Object targetA9(Object a0, long   a1, long   a2, long   a3, long   a4, long   a5, long   a6, long   a7, long   a8) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8); }
+        protected Object targetA9(long   a0, long   a1, long   a2, long   a3, long   a4, long   a5, long   a6, long   a7, long   a8) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8); }
+        protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8) throws Throwable { return return_L(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
+        protected int    invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8) throws Throwable { return return_I(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
+        protected long   invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8) throws Throwable { return return_J(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
+        protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, long   a8) throws Throwable { return return_L(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
+        protected int    invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, long   a8) throws Throwable { return return_I(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
+        protected long   invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, long   a8) throws Throwable { return return_J(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
+        protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, long   a7, long   a8) throws Throwable { return return_L(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
+        protected int    invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, long   a7, long   a8) throws Throwable { return return_I(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
+        protected long   invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, long   a7, long   a8) throws Throwable { return return_J(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
+        protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, long   a6, long   a7, long   a8) throws Throwable { return return_L(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
+        protected int    invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, long   a6, long   a7, long   a8) throws Throwable { return return_I(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
+        protected long   invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, long   a6, long   a7, long   a8) throws Throwable { return return_J(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
+        protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, long   a5, long   a6, long   a7, long   a8) throws Throwable { return return_L(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
+        protected int    invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, long   a5, long   a6, long   a7, long   a8) throws Throwable { return return_I(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
+        protected long   invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, long   a5, long   a6, long   a7, long   a8) throws Throwable { return return_J(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
+        protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, long   a4, long   a5, long   a6, long   a7, long   a8) throws Throwable { return return_L(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
+        protected int    invoke_I(Object a0, Object a1, Object a2, Object a3, long   a4, long   a5, long   a6, long   a7, long   a8) throws Throwable { return return_I(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
+        protected long   invoke_J(Object a0, Object a1, Object a2, Object a3, long   a4, long   a5, long   a6, long   a7, long   a8) throws Throwable { return return_J(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
+        protected Object invoke_L(Object a0, Object a1, Object a2, long   a3, long   a4, long   a5, long   a6, long   a7, long   a8) throws Throwable { return return_L(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
+        protected int    invoke_I(Object a0, Object a1, Object a2, long   a3, long   a4, long   a5, long   a6, long   a7, long   a8) throws Throwable { return return_I(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
+        protected long   invoke_J(Object a0, Object a1, Object a2, long   a3, long   a4, long   a5, long   a6, long   a7, long   a8) throws Throwable { return return_J(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
+        protected Object invoke_L(Object a0, Object a1, long   a2, long   a3, long   a4, long   a5, long   a6, long   a7, long   a8) throws Throwable { return return_L(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
+        protected int    invoke_I(Object a0, Object a1, long   a2, long   a3, long   a4, long   a5, long   a6, long   a7, long   a8) throws Throwable { return return_I(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
+        protected long   invoke_J(Object a0, Object a1, long   a2, long   a3, long   a4, long   a5, long   a6, long   a7, long   a8) throws Throwable { return return_J(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
+        protected Object invoke_L(Object a0, long   a1, long   a2, long   a3, long   a4, long   a5, long   a6, long   a7, long   a8) throws Throwable { return return_L(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
+        protected int    invoke_I(Object a0, long   a1, long   a2, long   a3, long   a4, long   a5, long   a6, long   a7, long   a8) throws Throwable { return return_I(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
+        protected long   invoke_J(Object a0, long   a1, long   a2, long   a3, long   a4, long   a5, long   a6, long   a7, long   a8) throws Throwable { return return_J(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
+        protected Object invoke_L(long   a0, long   a1, long   a2, long   a3, long   a4, long   a5, long   a6, long   a7, long   a8) throws Throwable { return return_L(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
+        protected int    invoke_I(long   a0, long   a1, long   a2, long   a3, long   a4, long   a5, long   a6, long   a7, long   a8) throws Throwable { return return_I(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
+        protected long   invoke_J(long   a0, long   a1, long   a2, long   a3, long   a4, long   a5, long   a6, long   a7, long   a8) throws Throwable { return return_J(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
     }
     static class A10 extends Adapter {
         protected A10(MethodHandle entryPoint) { super(entryPoint); }  // to build prototype
         protected A10(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { super(e, i, c, t); }
         protected A10 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { return new A10(e, i, c, t); }
-        protected Object target(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object a9)   { return invoker.<Object>invoke(target, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
-        protected Object targetA10(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object a9) { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
-        protected Object targetA10(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, long   a9) { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
-        protected Object targetA10(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, long   a8, long   a9) { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
-        protected Object targetA10(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, long   a7, long   a8, long   a9) { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
-        protected Object targetA10(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, long   a6, long   a7, long   a8, long   a9) { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
-        protected Object targetA10(Object a0, Object a1, Object a2, Object a3, Object a4, long   a5, long   a6, long   a7, long   a8, long   a9) { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
-        protected Object targetA10(Object a0, Object a1, Object a2, Object a3, long   a4, long   a5, long   a6, long   a7, long   a8, long   a9) { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
-        protected Object targetA10(Object a0, Object a1, Object a2, long   a3, long   a4, long   a5, long   a6, long   a7, long   a8, long   a9) { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
-        protected Object targetA10(Object a0, Object a1, long   a2, long   a3, long   a4, long   a5, long   a6, long   a7, long   a8, long   a9) { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
-        protected Object targetA10(Object a0, long   a1, long   a2, long   a3, long   a4, long   a5, long   a6, long   a7, long   a8, long   a9) { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
-        protected Object targetA10(long   a0, long   a1, long   a2, long   a3, long   a4, long   a5, long   a6, long   a7, long   a8, long   a9) { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
-        protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object a9) { return return_L(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
-        protected int    invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object a9) { return return_I(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
-        protected long   invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object a9) { return return_J(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
-        protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, long   a9) { return return_L(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
-        protected int    invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, long   a9) { return return_I(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
-        protected long   invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, long   a9) { return return_J(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
-        protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, long   a8, long   a9) { return return_L(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
-        protected int    invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, long   a8, long   a9) { return return_I(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
-        protected long   invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, long   a8, long   a9) { return return_J(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
-        protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, long   a7, long   a8, long   a9) { return return_L(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
-        protected int    invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, long   a7, long   a8, long   a9) { return return_I(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
-        protected long   invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, long   a7, long   a8, long   a9) { return return_J(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
-        protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, long   a6, long   a7, long   a8, long   a9) { return return_L(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
-        protected int    invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, long   a6, long   a7, long   a8, long   a9) { return return_I(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
-        protected long   invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, long   a6, long   a7, long   a8, long   a9) { return return_J(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
-        protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, long   a5, long   a6, long   a7, long   a8, long   a9) { return return_L(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
-        protected int    invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, long   a5, long   a6, long   a7, long   a8, long   a9) { return return_I(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
-        protected long   invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, long   a5, long   a6, long   a7, long   a8, long   a9) { return return_J(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
-        protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, long   a4, long   a5, long   a6, long   a7, long   a8, long   a9) { return return_L(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
-        protected int    invoke_I(Object a0, Object a1, Object a2, Object a3, long   a4, long   a5, long   a6, long   a7, long   a8, long   a9) { return return_I(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
-        protected long   invoke_J(Object a0, Object a1, Object a2, Object a3, long   a4, long   a5, long   a6, long   a7, long   a8, long   a9) { return return_J(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
-        protected Object invoke_L(Object a0, Object a1, Object a2, long   a3, long   a4, long   a5, long   a6, long   a7, long   a8, long   a9) { return return_L(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
-        protected int    invoke_I(Object a0, Object a1, Object a2, long   a3, long   a4, long   a5, long   a6, long   a7, long   a8, long   a9) { return return_I(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
-        protected long   invoke_J(Object a0, Object a1, Object a2, long   a3, long   a4, long   a5, long   a6, long   a7, long   a8, long   a9) { return return_J(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
-        protected Object invoke_L(Object a0, Object a1, long   a2, long   a3, long   a4, long   a5, long   a6, long   a7, long   a8, long   a9) { return return_L(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
-        protected int    invoke_I(Object a0, Object a1, long   a2, long   a3, long   a4, long   a5, long   a6, long   a7, long   a8, long   a9) { return return_I(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
-        protected long   invoke_J(Object a0, Object a1, long   a2, long   a3, long   a4, long   a5, long   a6, long   a7, long   a8, long   a9) { return return_J(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
-        protected Object invoke_L(Object a0, long   a1, long   a2, long   a3, long   a4, long   a5, long   a6, long   a7, long   a8, long   a9) { return return_L(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
-        protected int    invoke_I(Object a0, long   a1, long   a2, long   a3, long   a4, long   a5, long   a6, long   a7, long   a8, long   a9) { return return_I(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
-        protected long   invoke_J(Object a0, long   a1, long   a2, long   a3, long   a4, long   a5, long   a6, long   a7, long   a8, long   a9) { return return_J(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
-        protected Object invoke_L(long   a0, long   a1, long   a2, long   a3, long   a4, long   a5, long   a6, long   a7, long   a8, long   a9) { return return_L(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
-        protected int    invoke_I(long   a0, long   a1, long   a2, long   a3, long   a4, long   a5, long   a6, long   a7, long   a8, long   a9) { return return_I(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
-        protected long   invoke_J(long   a0, long   a1, long   a2, long   a3, long   a4, long   a5, long   a6, long   a7, long   a8, long   a9) { return return_J(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
+        protected Object target(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object a9)   throws Throwable { return invoker.<Object>invoke(target, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
+        protected Object targetA10(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object a9) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
+        protected Object targetA10(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, long   a9) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
+        protected Object targetA10(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, long   a8, long   a9) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
+        protected Object targetA10(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, long   a7, long   a8, long   a9) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
+        protected Object targetA10(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, long   a6, long   a7, long   a8, long   a9) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
+        protected Object targetA10(Object a0, Object a1, Object a2, Object a3, Object a4, long   a5, long   a6, long   a7, long   a8, long   a9) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
+        protected Object targetA10(Object a0, Object a1, Object a2, Object a3, long   a4, long   a5, long   a6, long   a7, long   a8, long   a9) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
+        protected Object targetA10(Object a0, Object a1, Object a2, long   a3, long   a4, long   a5, long   a6, long   a7, long   a8, long   a9) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
+        protected Object targetA10(Object a0, Object a1, long   a2, long   a3, long   a4, long   a5, long   a6, long   a7, long   a8, long   a9) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
+        protected Object targetA10(Object a0, long   a1, long   a2, long   a3, long   a4, long   a5, long   a6, long   a7, long   a8, long   a9) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
+        protected Object targetA10(long   a0, long   a1, long   a2, long   a3, long   a4, long   a5, long   a6, long   a7, long   a8, long   a9) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
+        protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object a9) throws Throwable { return return_L(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
+        protected int    invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object a9) throws Throwable { return return_I(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
+        protected long   invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object a9) throws Throwable { return return_J(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
+        protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, long   a9) throws Throwable { return return_L(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
+        protected int    invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, long   a9) throws Throwable { return return_I(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
+        protected long   invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, long   a9) throws Throwable { return return_J(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
+        protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, long   a8, long   a9) throws Throwable { return return_L(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
+        protected int    invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, long   a8, long   a9) throws Throwable { return return_I(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
+        protected long   invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, long   a8, long   a9) throws Throwable { return return_J(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
+        protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, long   a7, long   a8, long   a9) throws Throwable { return return_L(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
+        protected int    invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, long   a7, long   a8, long   a9) throws Throwable { return return_I(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
+        protected long   invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, long   a7, long   a8, long   a9) throws Throwable { return return_J(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
+        protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, long   a6, long   a7, long   a8, long   a9) throws Throwable { return return_L(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
+        protected int    invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, long   a6, long   a7, long   a8, long   a9) throws Throwable { return return_I(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
+        protected long   invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, long   a6, long   a7, long   a8, long   a9) throws Throwable { return return_J(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
+        protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, long   a5, long   a6, long   a7, long   a8, long   a9) throws Throwable { return return_L(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
+        protected int    invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, long   a5, long   a6, long   a7, long   a8, long   a9) throws Throwable { return return_I(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
+        protected long   invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, long   a5, long   a6, long   a7, long   a8, long   a9) throws Throwable { return return_J(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
+        protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, long   a4, long   a5, long   a6, long   a7, long   a8, long   a9) throws Throwable { return return_L(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
+        protected int    invoke_I(Object a0, Object a1, Object a2, Object a3, long   a4, long   a5, long   a6, long   a7, long   a8, long   a9) throws Throwable { return return_I(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
+        protected long   invoke_J(Object a0, Object a1, Object a2, Object a3, long   a4, long   a5, long   a6, long   a7, long   a8, long   a9) throws Throwable { return return_J(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
+        protected Object invoke_L(Object a0, Object a1, Object a2, long   a3, long   a4, long   a5, long   a6, long   a7, long   a8, long   a9) throws Throwable { return return_L(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
+        protected int    invoke_I(Object a0, Object a1, Object a2, long   a3, long   a4, long   a5, long   a6, long   a7, long   a8, long   a9) throws Throwable { return return_I(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
+        protected long   invoke_J(Object a0, Object a1, Object a2, long   a3, long   a4, long   a5, long   a6, long   a7, long   a8, long   a9) throws Throwable { return return_J(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
+        protected Object invoke_L(Object a0, Object a1, long   a2, long   a3, long   a4, long   a5, long   a6, long   a7, long   a8, long   a9) throws Throwable { return return_L(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
+        protected int    invoke_I(Object a0, Object a1, long   a2, long   a3, long   a4, long   a5, long   a6, long   a7, long   a8, long   a9) throws Throwable { return return_I(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
+        protected long   invoke_J(Object a0, Object a1, long   a2, long   a3, long   a4, long   a5, long   a6, long   a7, long   a8, long   a9) throws Throwable { return return_J(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
+        protected Object invoke_L(Object a0, long   a1, long   a2, long   a3, long   a4, long   a5, long   a6, long   a7, long   a8, long   a9) throws Throwable { return return_L(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
+        protected int    invoke_I(Object a0, long   a1, long   a2, long   a3, long   a4, long   a5, long   a6, long   a7, long   a8, long   a9) throws Throwable { return return_I(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
+        protected long   invoke_J(Object a0, long   a1, long   a2, long   a3, long   a4, long   a5, long   a6, long   a7, long   a8, long   a9) throws Throwable { return return_J(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
+        protected Object invoke_L(long   a0, long   a1, long   a2, long   a3, long   a4, long   a5, long   a6, long   a7, long   a8, long   a9) throws Throwable { return return_L(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
+        protected int    invoke_I(long   a0, long   a1, long   a2, long   a3, long   a4, long   a5, long   a6, long   a7, long   a8, long   a9) throws Throwable { return return_I(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
+        protected long   invoke_J(long   a0, long   a1, long   a2, long   a3, long   a4, long   a5, long   a6, long   a7, long   a8, long   a9) throws Throwable { return return_J(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
     }
 }
--- a/jdk/src/share/classes/sun/dyn/empty/Empty.java	Thu Dec 17 14:10:20 2009 -0800
+++ b/jdk/src/share/classes/sun/dyn/empty/Empty.java	Wed Jul 05 17:04:56 2017 +0200
@@ -29,6 +29,10 @@
  * An empty class in an empty package.
  * Used as a proxy for unprivileged code, since making access checks
  * against it will only succeed against public methods in public types.
+ * <p>
+ * This class also stands (internally to sun.dyn) for the type of a
+ * value that cannot be produced, because the expression of this type
+ * always returns abnormally.  (Cf. Nothing in the closures proposal.)
  * @author jrose
  */
 public class Empty {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/sun/dyn/util/BytecodeDescriptor.java	Wed Jul 05 17:04:56 2017 +0200
@@ -0,0 +1,137 @@
+/*
+ * Copyright 2008-2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * 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.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package sun.dyn.util;
+
+import java.dyn.MethodType;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Utility routines for dealing with bytecode-level signatures.
+ * @author jrose
+ */
+public class BytecodeDescriptor {
+
+    private BytecodeDescriptor() { }  // cannot instantiate
+
+    public static List<Class<?>> parseMethod(String bytecodeSignature, ClassLoader loader) {
+        return parseMethod(bytecodeSignature, 0, bytecodeSignature.length(), loader);
+    }
+
+    static List<Class<?>> parseMethod(String bytecodeSignature,
+            int start, int end, ClassLoader loader) {
+        if (loader == null)
+            loader = ClassLoader.getSystemClassLoader();
+        String str = bytecodeSignature;
+        int[] i = {start};
+        ArrayList<Class<?>> ptypes = new ArrayList<Class<?>>();
+        if (i[0] < end && str.charAt(i[0]) == '(') {
+            ++i[0];  // skip '('
+            while (i[0] < end && str.charAt(i[0]) != ')') {
+                Class<?> pt = parseSig(str, i, end, loader);
+                if (pt == null || pt == void.class)
+                    parseError(str, "bad argument type");
+                ptypes.add(pt);
+            }
+            ++i[0];  // skip ')'
+        } else {
+            parseError(str, "not a method type");
+        }
+        Class<?> rtype = parseSig(str, i, end, loader);
+        if (rtype == null || i[0] != end)
+            parseError(str, "bad return type");
+        ptypes.add(rtype);
+        return ptypes;
+    }
+
+    static private void parseError(String str, String msg) {
+        throw new IllegalArgumentException("bad signature: "+str+": "+msg);
+    }
+
+    static private Class<?> parseSig(String str, int[] i, int end, ClassLoader loader) {
+        if (i[0] == end)  return null;
+        char c = str.charAt(i[0]++);
+        if (c == 'L') {
+            int begc = i[0], endc = str.indexOf(';', begc);
+            if (endc < 0)  return null;
+            i[0] = endc+1;
+            String name = str.substring(begc, endc).replace('/', '.');
+            try {
+                return loader.loadClass(name);
+            } catch (ClassNotFoundException ex) {
+                throw new TypeNotPresentException(name, ex);
+            }
+        } else if (c == '[') {
+            Class<?> t = parseSig(str, i, end, loader);
+            if (t != null)
+                t = java.lang.reflect.Array.newInstance(t, 0).getClass();
+            return t;
+        } else {
+            return Wrapper.forBasicType(c).primitiveType();
+        }
+    }
+
+    public static String unparse(Class<?> type) {
+        StringBuilder sb = new StringBuilder();
+        unparseSig(type, sb);
+        return sb.toString();
+    }
+
+    public static String unparse(MethodType type) {
+        return unparseMethod(type.returnType(), type.parameterList());
+    }
+
+    public static String unparse(Object type) {
+        if (type instanceof Class<?>)
+            return unparse((Class<?>) type);
+        if (type instanceof MethodType)
+            return unparse((MethodType) type);
+        return (String) type;
+    }
+
+    public static String unparseMethod(Class<?> rtype, List<Class<?>> ptypes) {
+        StringBuilder sb = new StringBuilder();
+        sb.append('(');
+        for (Class<?> pt : ptypes)
+            unparseSig(pt, sb);
+        sb.append(')');
+        unparseSig(rtype, sb);
+        return sb.toString();
+    }
+
+    static private void unparseSig(Class<?> t, StringBuilder sb) {
+        char c = Wrapper.forBasicType(t).basicTypeChar();
+        if (c != 'L') {
+            sb.append(c);
+        } else {
+            boolean lsemi = (!t.isArray());
+            if (lsemi)  sb.append('L');
+            sb.append(t.getName().replace('.', '/'));
+            if (lsemi)  sb.append(';');
+        }
+    }
+
+}
--- a/jdk/src/share/classes/sun/dyn/util/BytecodeName.java	Thu Dec 17 14:10:20 2009 -0800
+++ b/jdk/src/share/classes/sun/dyn/util/BytecodeName.java	Wed Jul 05 17:04:56 2017 +0200
@@ -298,6 +298,8 @@
      * The name {@code &lt;init&gt;} will be parsed into { '&lt;', "init", '&gt;'}}
      * The name {@code foo/bar$:baz} will be parsed into
      * {@code {"foo", '/', "bar", '$', ':', "baz"}}.
+     * The name {@code ::\=:foo:\=bar\!baz} will be parsed into
+     * {@code {':', ':', "", ':', "foo", ':', "bar:baz"}}.
      */
     public static Object[] parseBytecodeName(String s) {
         int slen = s.length();
@@ -315,7 +317,7 @@
                 if (lasti < i) {
                     // normal component
                     if (pass != 0)
-                        res[fillp] = s.substring(lasti, i);
+                        res[fillp] = toSourceName(s.substring(lasti, i));
                     fillp++;
                     lasti = i+1;
                 }
@@ -323,13 +325,14 @@
                     if (pass != 0)
                         res[fillp] = DANGEROUS_CHARS_CA[whichDC];
                     fillp++;
+                    lasti = i+1;
                 }
             }
             if (pass != 0)  break;
             // between passes, build the result array
-            res = new String[fillp];
-            if (fillp <= 1) {
-                if (fillp != 0)  res[0] = s;
+            res = new Object[fillp];
+            if (fillp <= 1 && lasti == 0) {
+                if (fillp != 0)  res[0] = toSourceName(s);
                 break;
             }
         }
@@ -348,9 +351,19 @@
      * @throws NullPointerException if any component is null
      */
     public static String unparseBytecodeName(Object[] components) {
-        for (Object c : components) {
-            if (c instanceof String)
-                checkSafeBytecodeName((String) c);  // may fail
+        Object[] components0 = components;
+        for (int i = 0; i < components.length; i++) {
+            Object c = components[i];
+            if (c instanceof String) {
+                String mc = toBytecodeName((String) c);
+                if (i == 0 && components.length == 1)
+                    return mc;  // usual case
+                if ((Object)mc != c) {
+                    if (components == components0)
+                        components = components.clone();
+                    components[i] = c = mc;
+                }
+            }
         }
         return appendAll(components);
     }
@@ -381,6 +394,14 @@
      * If the bytecode name contains dangerous characters,
      * assume that they are being used as punctuation,
      * and pass them through unchanged.
+     * Non-empty runs of non-dangerous characters are demangled
+     * if necessary, and the resulting names are quoted if
+     * they are not already valid Java identifiers, or if
+     * they contain a dangerous character (i.e., dollar sign "$").
+     * Single quotes are used when quoting.
+     * Within quoted names, embedded single quotes and backslashes
+     * are further escaped by prepended backslashes.
+     *
      * @param s the original bytecode name (which may be qualified)
      * @return a human-readable presentation
      */
@@ -389,10 +410,10 @@
         for (int i = 0; i < components.length; i++) {
             if (!(components[i] instanceof String))
                 continue;
-            String c = (String) components[i];
-            // pretty up the name by demangling it
-            String sn = toSourceName(c);
-            if ((Object)sn != c || !isJavaIdent(sn)) {
+            String sn = (String) components[i];
+            // note that the name is already demangled!
+            //sn = toSourceName(sn);
+            if (!isJavaIdent(sn) || sn.indexOf('$') >=0 ) {
                 components[i] = quoteDisplay(sn);
             }
         }
@@ -401,10 +422,10 @@
     private static boolean isJavaIdent(String s) {
         int slen = s.length();
         if (slen == 0)  return false;
-        if (!Character.isUnicodeIdentifierStart(s.charAt(0)))
+        if (!Character.isJavaIdentifierStart(s.charAt(0)))
             return false;
         for (int i = 1; i < slen; i++) {
-            if (!Character.isUnicodeIdentifierPart(s.charAt(0)))
+            if (!Character.isJavaIdentifierPart(s.charAt(i)))
                 return false;
         }
         return true;
@@ -602,110 +623,5 @@
         return -1;
     }
 
-    // test driver
-    static void main(String[] av) {
-        // If verbose is enabled, quietly check everything.
-        // Otherwise, print the output for the user to check.
-        boolean verbose = false;
 
-        int maxlen = 0;
-
-        while (av.length > 0 && av[0].startsWith("-")) {
-            String flag = av[0].intern();
-            av = java.util.Arrays.copyOfRange(av, 1, av.length); // Java 1.6 or later
-            if (flag == "-" || flag == "--")  break;
-            else if (flag == "-q")
-                verbose = false;
-            else if (flag == "-v")
-                verbose = true;
-            else if (flag.startsWith("-l"))
-                maxlen = Integer.valueOf(flag.substring(2));
-            else
-                throw new Error("Illegal flag argument: "+flag);
-        }
-
-        if (maxlen == 0)
-            maxlen = (verbose ? 2 : 4);
-        if (verbose)  System.out.println("Note: maxlen = "+maxlen);
-
-        switch (av.length) {
-        case 0: av = new String[] {
-                    DANGEROUS_CHARS.substring(0) +
-                    REPLACEMENT_CHARS.substring(0, 1) +
-                    NULL_ESCAPE + "x"
-                }; // and fall through:
-        case 1:
-            char[] cv = av[0].toCharArray();
-            av = new String[cv.length];
-            int avp = 0;
-            for (char c : cv) {
-                String s = String.valueOf(c);
-                if (c == 'x')  s = "foo";  // tradition...
-                av[avp++] = s;
-            }
-        }
-        if (verbose)
-            System.out.println("Note: Verbose output mode enabled.  Use '-q' to suppress.");
-        Tester t = new Tester();
-        t.maxlen = maxlen;
-        t.verbose = verbose;
-        t.tokens = av;
-        t.test("", 0);
-    }
-
-    static class Tester {
-        boolean verbose;
-        int maxlen;
-        java.util.Map<String,String> map = new java.util.HashMap<String,String>();
-        String[] tokens;
-
-        void test(String stringSoFar, int tokensSoFar) {
-            test(stringSoFar);
-            if (tokensSoFar <= maxlen) {
-                for (String token : tokens) {
-                    if (token.length() == 0)  continue;  // skip empty tokens
-                    if (stringSoFar.indexOf(token) != stringSoFar.lastIndexOf(token))
-                        continue;   // there are already two occs. of this token
-                    if (token.charAt(0) == ESCAPE_C && token.length() == 1 && maxlen < 4)
-                        test(stringSoFar+token, tokensSoFar);  // want lots of \'s
-                    else if (tokensSoFar < maxlen)
-                        test(stringSoFar+token, tokensSoFar+1);
-                }
-            }
-        }
-
-        void test(String s) {
-            // for small batches, do not test the null string
-            if (s.length() == 0 && maxlen >=1 && maxlen <= 2)  return;
-            String bn = testSourceName(s);
-            if (bn == null)  return;
-            if (bn == s) {
-                //if (verbose)  System.out.println(s+" == id");
-            } else {
-                if (verbose)  System.out.println(s+" => "+bn+" "+toDisplayName(bn));
-                String bnbn = testSourceName(bn);
-                if (bnbn == null)  return;
-                if (verbose)  System.out.println(bn+" => "+bnbn+" "+toDisplayName(bnbn));
-                /*
-                String bn3 = testSourceName(bnbn);
-                if (bn3 == null)  return;
-                if (verbose)  System.out.println(bnbn+" => "+bn3);
-                */
-            }
-        }
-
-        String testSourceName(String s) {
-            if (map.containsKey(s))  return null;
-            String bn = toBytecodeName(s);
-            map.put(s, bn);
-            String sn = toSourceName(bn);
-            if (!sn.equals(s)) {
-                String bad = (s+" => "+bn+" != "+sn);
-                if (!verbose)  throw new Error("Bad mangling: "+bad);
-                System.out.println("*** "+bad);
-                return null;
-            }
-            return bn;
-        }
-    }
 }
--- a/jdk/src/share/classes/sun/dyn/util/BytecodeSignature.java	Thu Dec 17 14:10:20 2009 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,137 +0,0 @@
-/*
- * Copyright 2008-2009 Sun Microsystems, Inc.  All Rights Reserved.
- * 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.  Sun designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
- * CA 95054 USA or visit www.sun.com if you need additional information or
- * have any questions.
- */
-
-package sun.dyn.util;
-
-import java.dyn.MethodType;
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Utility routines for dealing with bytecode-level signatures.
- * @author jrose
- */
-public class BytecodeSignature {
-
-    private BytecodeSignature() { }  // cannot instantiate
-
-    public static List<Class<?>> parseMethod(String bytecodeSignature, ClassLoader loader) {
-        return parseMethod(bytecodeSignature, 0, bytecodeSignature.length(), loader);
-    }
-
-    static List<Class<?>> parseMethod(String bytecodeSignature,
-            int start, int end, ClassLoader loader) {
-        if (loader == null)
-            loader = ClassLoader.getSystemClassLoader();
-        String str = bytecodeSignature;
-        int[] i = {start};
-        ArrayList<Class<?>> ptypes = new ArrayList<Class<?>>();
-        if (i[0] < end && str.charAt(i[0]) == '(') {
-            ++i[0];  // skip '('
-            while (i[0] < end && str.charAt(i[0]) != ')') {
-                Class<?> pt = parseSig(str, i, end, loader);
-                if (pt == null || pt == void.class)
-                    parseError(str, "bad argument type");
-                ptypes.add(pt);
-            }
-            ++i[0];  // skip ')'
-        } else {
-            parseError(str, "not a method type");
-        }
-        Class<?> rtype = parseSig(str, i, end, loader);
-        if (rtype == null || i[0] != end)
-            parseError(str, "bad return type");
-        ptypes.add(rtype);
-        return ptypes;
-    }
-
-    static private void parseError(String str, String msg) {
-        throw new IllegalArgumentException("bad signature: "+str+": "+msg);
-    }
-
-    static private Class<?> parseSig(String str, int[] i, int end, ClassLoader loader) {
-        if (i[0] == end)  return null;
-        char c = str.charAt(i[0]++);
-        if (c == 'L') {
-            int begc = i[0], endc = str.indexOf(';', begc);
-            if (endc < 0)  return null;
-            i[0] = endc+1;
-            String name = str.substring(begc, endc).replace('/', '.');
-            try {
-                return loader.loadClass(name);
-            } catch (ClassNotFoundException ex) {
-                throw new TypeNotPresentException(name, ex);
-            }
-        } else if (c == '[') {
-            Class<?> t = parseSig(str, i, end, loader);
-            if (t != null)
-                t = java.lang.reflect.Array.newInstance(t, 0).getClass();
-            return t;
-        } else {
-            return Wrapper.forBasicType(c).primitiveType();
-        }
-    }
-
-    public static String unparse(Class<?> type) {
-        StringBuilder sb = new StringBuilder();
-        unparseSig(type, sb);
-        return sb.toString();
-    }
-
-    public static String unparse(MethodType type) {
-        return unparseMethod(type.returnType(), type.parameterList());
-    }
-
-    public static String unparse(Object type) {
-        if (type instanceof Class<?>)
-            return unparse((Class<?>) type);
-        if (type instanceof MethodType)
-            return unparse((MethodType) type);
-        return (String) type;
-    }
-
-    public static String unparseMethod(Class<?> rtype, List<Class<?>> ptypes) {
-        StringBuilder sb = new StringBuilder();
-        sb.append('(');
-        for (Class<?> pt : ptypes)
-            unparseSig(pt, sb);
-        sb.append(')');
-        unparseSig(rtype, sb);
-        return sb.toString();
-    }
-
-    static private void unparseSig(Class<?> t, StringBuilder sb) {
-        char c = Wrapper.forBasicType(t).basicTypeChar();
-        if (c != 'L') {
-            sb.append(c);
-        } else {
-            boolean lsemi = (!t.isArray());
-            if (lsemi)  sb.append('L');
-            sb.append(t.getName().replace('.', '/'));
-            if (lsemi)  sb.append(';');
-        }
-    }
-
-}
--- a/jdk/src/share/classes/sun/dyn/util/ValueConversions.java	Thu Dec 17 14:10:20 2009 -0800
+++ b/jdk/src/share/classes/sun/dyn/util/ValueConversions.java	Wed Jul 05 17:04:56 2017 +0200
@@ -27,7 +27,10 @@
 
 import java.dyn.*;
 import java.dyn.MethodHandles.Lookup;
+import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.EnumMap;
+import java.util.List;
 import sun.dyn.Access;
 import sun.dyn.AdapterMethodHandle;
 import sun.dyn.MethodHandleImpl;
@@ -37,6 +40,7 @@
     private static final Lookup IMPL_LOOKUP = MethodHandleImpl.getLookup(IMPL_TOKEN);
 
     private static EnumMap<Wrapper, MethodHandle>[] newWrapperCaches(int n) {
+        @SuppressWarnings("unchecked")
         EnumMap<Wrapper, MethodHandle>[] caches
                 = (EnumMap<Wrapper, MethodHandle>[]) new EnumMap[n];  // unchecked warning expected here
         for (int i = 0; i < n; i++)
@@ -114,7 +118,7 @@
     }
 
     private static MethodType unboxType(Wrapper wrap, boolean raw) {
-        return MethodType.make(rawWrapper(wrap, raw).primitiveType(), wrap.wrapperType());
+        return MethodType.methodType(rawWrapper(wrap, raw).primitiveType(), wrap.wrapperType());
     }
 
     private static final EnumMap<Wrapper, MethodHandle>[]
@@ -240,7 +244,7 @@
     private static MethodType boxType(Wrapper wrap, boolean raw) {
         // be exact, since return casts are hard to compose
         Class<?> boxType = wrap.wrapperType();
-        return MethodType.make(boxType, rawWrapper(wrap, raw).primitiveType());
+        return MethodType.methodType(boxType, rawWrapper(wrap, raw).primitiveType());
     }
 
     private static Wrapper rawWrapper(Wrapper wrap, boolean raw) {
@@ -305,29 +309,47 @@
 
     /// Kludges for when raw values get accidentally boxed.
 
+    static int unboxRawInteger(Object x) {
+        if (x instanceof Integer)
+            return unboxInteger(x);
+        else
+            return (int) unboxLong(x);
+    }
+
+    static Integer reboxRawInteger(Object x) {
+        if (x instanceof Integer)
+            return (Integer) x;
+        else
+            return (int) unboxLong(x);
+    }
+
     static Byte reboxRawByte(Object x) {
         if (x instanceof Byte)  return (Byte) x;
-        return boxByteRaw(unboxInteger(x));
+        return boxByteRaw(unboxRawInteger(x));
     }
 
     static Short reboxRawShort(Object x) {
         if (x instanceof Short)  return (Short) x;
-        return boxShortRaw(unboxInteger(x));
+        return boxShortRaw(unboxRawInteger(x));
     }
 
     static Boolean reboxRawBoolean(Object x) {
         if (x instanceof Boolean)  return (Boolean) x;
-        return boxBooleanRaw(unboxInteger(x));
+        return boxBooleanRaw(unboxRawInteger(x));
     }
 
     static Character reboxRawCharacter(Object x) {
         if (x instanceof Character)  return (Character) x;
-        return boxCharacterRaw(unboxInteger(x));
+        return boxCharacterRaw(unboxRawInteger(x));
     }
 
     static Float reboxRawFloat(Object x) {
         if (x instanceof Float)  return (Float) x;
-        return boxFloatRaw(unboxInteger(x));
+        return boxFloatRaw(unboxRawInteger(x));
+    }
+
+    static Long reboxRawLong(Object x) {
+        return (Long) x;  //never a rebox
     }
 
     static Double reboxRawDouble(Object x) {
@@ -337,12 +359,21 @@
 
     private static MethodType reboxType(Wrapper wrap) {
         Class<?> boxType = wrap.wrapperType();
-        return MethodType.make(boxType, Object.class);
+        return MethodType.methodType(boxType, Object.class);
     }
 
     private static final EnumMap<Wrapper, MethodHandle>[]
             REBOX_CONVERSIONS = newWrapperCaches(2);
 
+    /**
+     * Becase we normalize primitive types to reduce the number of signatures,
+     * primitives are sometimes manipulated under an "erased" type,
+     * either int (for types other than long/double) or long (for all types).
+     * When the erased primitive value is then boxed into an Integer or Long,
+     * the final boxed primitive is sometimes required.  This transformation
+     * is called a "rebox".  It takes an Integer or Long and produces some
+     * other boxed value.
+     */
     public static MethodHandle rebox(Wrapper wrap, boolean exact) {
         EnumMap<Wrapper, MethodHandle> cache = REBOX_CONVERSIONS[exact?1:0];
         MethodHandle mh = cache.get(wrap);
@@ -355,9 +386,6 @@
                 mh = IDENTITY; break;
             case VOID:
                 throw new IllegalArgumentException("cannot rebox a void");
-            case INT: case LONG:
-                mh = cast(wrap.wrapperType(), exact);
-                break;
         }
         if (mh != null) {
             cache.put(wrap, mh);
@@ -384,13 +412,21 @@
     /// Width-changing conversions between int and long.
 
     static long widenInt(int x) {
-        return x;
+        return (long) x;
+    }
+
+    static Long widenBoxedInt(Integer x) {
+        return (long)(int)x;
     }
 
     static int narrowLong(long x) {
         return (int) x;
     }
 
+    static Integer narrowBoxedLong(Long x) {
+        return (int)(long) x;
+    }
+
     /// Constant functions
 
     static void ignore(Object x) {
@@ -432,7 +468,7 @@
             return mh;
         }
         // slow path
-        MethodType type = MethodType.make(wrap.primitiveType());
+        MethodType type = MethodType.methodType(wrap.primitiveType());
         switch (wrap) {
             case VOID:
                 mh = EMPTY;
@@ -500,11 +536,11 @@
     private static final MethodHandle IDENTITY, CAST_REFERENCE, ALWAYS_NULL, ALWAYS_ZERO, ZERO_OBJECT, IGNORE, EMPTY;
     static {
         try {
-            MethodType idType = MethodType.makeGeneric(1);
-            MethodType castType = idType.insertParameterType(0, Class.class);
+            MethodType idType = MethodType.genericMethodType(1);
+            MethodType castType = idType.insertParameterTypes(0, Class.class);
             MethodType alwaysZeroType = idType.changeReturnType(int.class);
             MethodType ignoreType = idType.changeReturnType(void.class);
-            MethodType zeroObjectType = MethodType.makeGeneric(0);
+            MethodType zeroObjectType = MethodType.genericMethodType(0);
             IDENTITY = IMPL_LOOKUP.findStatic(ValueConversions.class, "identity", idType);
             //CAST_REFERENCE = IMPL_LOOKUP.findVirtual(Class.class, "cast", idType);
             CAST_REFERENCE = IMPL_LOOKUP.findStatic(ValueConversions.class, "castReference", castType);
@@ -512,7 +548,7 @@
             ALWAYS_ZERO = IMPL_LOOKUP.findStatic(ValueConversions.class, "alwaysZero", alwaysZeroType);
             ZERO_OBJECT = IMPL_LOOKUP.findStatic(ValueConversions.class, "zeroObject", zeroObjectType);
             IGNORE = IMPL_LOOKUP.findStatic(ValueConversions.class, "ignore", ignoreType);
-            EMPTY = IMPL_LOOKUP.findStatic(ValueConversions.class, "empty", ignoreType.dropParameterType(0));
+            EMPTY = IMPL_LOOKUP.findStatic(ValueConversions.class, "empty", ignoreType.dropParameterTypes(0, 1));
         } catch (RuntimeException ex) {
             throw ex;
         }
@@ -543,10 +579,10 @@
         else if (VerifyType.isNullType(type))
             mh = ALWAYS_NULL;
         else
-            mh = MethodHandles.insertArgument(CAST_REFERENCE, 0, type);
+            mh = MethodHandles.insertArguments(CAST_REFERENCE, 0, type);
         if (exact) {
-            MethodType xmt = MethodType.make(type, Object.class);
-            mh = AdapterMethodHandle.makeRawRetypeOnly(IMPL_TOKEN, xmt, mh);
+            MethodType xmt = MethodType.methodType(type, Object.class);
+            mh = AdapterMethodHandle.makeRetypeRaw(IMPL_TOKEN, xmt, mh);
         }
         if (cache != null)
             cache.put(wrap, mh);
@@ -560,4 +596,127 @@
     private static MethodHandle retype(MethodType type, MethodHandle mh) {
         return AdapterMethodHandle.makeRetypeOnly(IMPL_TOKEN, type, mh);
     }
+
+    private static final Object[] NO_ARGS_ARRAY = {};
+    private static Object[] makeArray(Object... args) { return args; }
+    private static Object[] array() { return NO_ARGS_ARRAY; }
+    private static Object[] array(Object a0)
+                { return makeArray(a0); }
+    private static Object[] array(Object a0, Object a1)
+                { return makeArray(a0, a1); }
+    private static Object[] array(Object a0, Object a1, Object a2)
+                { return makeArray(a0, a1, a2); }
+    private static Object[] array(Object a0, Object a1, Object a2, Object a3)
+                { return makeArray(a0, a1, a2, a3); }
+    private static Object[] array(Object a0, Object a1, Object a2, Object a3,
+                                  Object a4)
+                { return makeArray(a0, a1, a2, a3, a4); }
+    private static Object[] array(Object a0, Object a1, Object a2, Object a3,
+                                  Object a4, Object a5)
+                { return makeArray(a0, a1, a2, a3, a4, a5); }
+    private static Object[] array(Object a0, Object a1, Object a2, Object a3,
+                                  Object a4, Object a5, Object a6)
+                { return makeArray(a0, a1, a2, a3, a4, a5, a6); }
+    private static Object[] array(Object a0, Object a1, Object a2, Object a3,
+                                  Object a4, Object a5, Object a6, Object a7)
+                { return makeArray(a0, a1, a2, a3, a4, a5, a6, a7); }
+    private static Object[] array(Object a0, Object a1, Object a2, Object a3,
+                                  Object a4, Object a5, Object a6, Object a7,
+                                  Object a8)
+                { return makeArray(a0, a1, a2, a3, a4, a5, a6, a7, a8); }
+    private static Object[] array(Object a0, Object a1, Object a2, Object a3,
+                                  Object a4, Object a5, Object a6, Object a7,
+                                  Object a8, Object a9)
+                { return makeArray(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
+    static MethodHandle[] makeArrays() {
+        ArrayList<MethodHandle> arrays = new ArrayList<MethodHandle>();
+        MethodHandles.Lookup lookup = IMPL_LOOKUP;
+        for (;;) {
+            int nargs = arrays.size();
+            MethodType type = MethodType.genericMethodType(nargs).changeReturnType(Object[].class);
+            String name = "array";
+            MethodHandle array = null;
+            try {
+                array = lookup.findStatic(ValueConversions.class, name, type);
+            } catch (NoAccessException ex) {
+            }
+            if (array == null)  break;
+            arrays.add(array);
+        }
+        assert(arrays.size() == 11);  // current number of methods
+        return arrays.toArray(new MethodHandle[0]);
+    }
+    static final MethodHandle[] ARRAYS = makeArrays();
+
+    /** Return a method handle that takes the indicated number of Object
+     *  arguments and returns an Object array of them, as if for varargs.
+     */
+    public static MethodHandle varargsArray(int nargs) {
+        if (nargs < ARRAYS.length)
+            return ARRAYS[nargs];
+        // else need to spin bytecode or do something else fancy
+        throw new UnsupportedOperationException("NYI");
+    }
+
+    private static final List<Object> NO_ARGS_LIST = Arrays.asList(NO_ARGS_ARRAY);
+    private static List<Object> makeList(Object... args) { return Arrays.asList(args); }
+    private static List<Object> list() { return NO_ARGS_LIST; }
+    private static List<Object> list(Object a0)
+                { return makeList(a0); }
+    private static List<Object> list(Object a0, Object a1)
+                { return makeList(a0, a1); }
+    private static List<Object> list(Object a0, Object a1, Object a2)
+                { return makeList(a0, a1, a2); }
+    private static List<Object> list(Object a0, Object a1, Object a2, Object a3)
+                { return makeList(a0, a1, a2, a3); }
+    private static List<Object> list(Object a0, Object a1, Object a2, Object a3,
+                                     Object a4)
+                { return makeList(a0, a1, a2, a3, a4); }
+    private static List<Object> list(Object a0, Object a1, Object a2, Object a3,
+                                     Object a4, Object a5)
+                { return makeList(a0, a1, a2, a3, a4, a5); }
+    private static List<Object> list(Object a0, Object a1, Object a2, Object a3,
+                                     Object a4, Object a5, Object a6)
+                { return makeList(a0, a1, a2, a3, a4, a5, a6); }
+    private static List<Object> list(Object a0, Object a1, Object a2, Object a3,
+                                     Object a4, Object a5, Object a6, Object a7)
+                { return makeList(a0, a1, a2, a3, a4, a5, a6, a7); }
+    private static List<Object> list(Object a0, Object a1, Object a2, Object a3,
+                                     Object a4, Object a5, Object a6, Object a7,
+                                     Object a8)
+                { return makeList(a0, a1, a2, a3, a4, a5, a6, a7, a8); }
+    private static List<Object> list(Object a0, Object a1, Object a2, Object a3,
+                                     Object a4, Object a5, Object a6, Object a7,
+                                     Object a8, Object a9)
+                { return makeList(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
+    static MethodHandle[] makeLists() {
+        ArrayList<MethodHandle> arrays = new ArrayList<MethodHandle>();
+        MethodHandles.Lookup lookup = IMPL_LOOKUP;
+        for (;;) {
+            int nargs = arrays.size();
+            MethodType type = MethodType.genericMethodType(nargs).changeReturnType(List.class);
+            String name = "list";
+            MethodHandle array = null;
+            try {
+                array = lookup.findStatic(ValueConversions.class, name, type);
+            } catch (NoAccessException ex) {
+            }
+            if (array == null)  break;
+            arrays.add(array);
+        }
+        assert(arrays.size() == 11);  // current number of methods
+        return arrays.toArray(new MethodHandle[0]);
+    }
+    static final MethodHandle[] LISTS = makeLists();
+
+    /** Return a method handle that takes the indicated number of Object
+     *  arguments and returns List.
+     */
+    public static MethodHandle varargsList(int nargs) {
+        if (nargs < LISTS.length)
+            return LISTS[nargs];
+        // else need to spin bytecode or do something else fancy
+        throw new UnsupportedOperationException("NYI");
+    }
 }
+
--- a/jdk/src/share/classes/sun/dyn/util/VerifyAccess.java	Thu Dec 17 14:10:20 2009 -0800
+++ b/jdk/src/share/classes/sun/dyn/util/VerifyAccess.java	Wed Jul 05 17:04:56 2017 +0200
@@ -26,8 +26,12 @@
 package sun.dyn.util;
 
 import java.dyn.LinkagePermission;
+import java.dyn.MethodHandles.Lookup;
+import java.dyn.NoAccessException;
 import java.lang.reflect.Modifier;
-import sun.dyn.Access;
+import sun.dyn.MemberName;
+import sun.dyn.MethodHandleImpl;
+import sun.dyn.empty.Empty;
 
 /**
  * This class centralizes information about the JVM's linkage access control.
@@ -45,21 +49,21 @@
      * <p>
      * Some circumstances require an additional check on the
      * leading parameter (the receiver) of the method, if it is non-static.
-     * In the case of {@code invokespecial} ({@code doDispatch} is false),
+     * In the case of {@code invokespecial} ({@code isSpecialInvoke} is true),
      * the leading parameter must be the accessing class or a subclass.
      * In the case of a call to a {@code protected} method outside the same
      * package, the same constraint applies.
      * @param m the proposed callee
-     * @param doDispatch if false, a non-static m will be invoked as if by {@code invokespecial}
+     * @param isSpecialInvoke if true, a non-static method m is checked as if for {@code invokespecial}
      * @param lookupClass the class for which the access check is being made
      * @return null if the method is not accessible, else a receiver type constraint, else {@code Object.class}
      */
     public static Class<?> isAccessible(Class<?> defc, int mods,
-            boolean doDispatch, Class<?> lookupClass) {
+            Class<?> lookupClass, boolean isSpecialInvoke) {
         if (!isAccessible(defc, lookupClass))
             return null;
         Class<?> constraint = Object.class;
-        if (!doDispatch && !Modifier.isStatic(mods)) {
+        if (isSpecialInvoke && !Modifier.isStatic(mods)) {
             constraint = lookupClass;
         }
         if (Modifier.isPublic(mods))
@@ -166,4 +170,38 @@
         if (isSamePackage(requestingClass, subjectClass))  return;
         security.checkPermission(new LinkagePermission(permissionName, requestingClass));
     }
+
+    private static RuntimeException checkNameFailed(MemberName self, Lookup lookup, String comment) {
+        return new NoAccessException("cannot access from "+lookup+": "+self.toString()+": "+comment);
+    }
+    public static void checkName(MemberName self, Lookup lookup) {
+        Class<?> lc = lookup.lookupClass();
+        if (lc == null)  return;  // lookup is privileged
+        Class<?> dc = self.getDeclaringClass();
+        int samepkg = 0;
+        // First check the containing class.  Must be public or local.
+        if (!Modifier.isPublic(dc.getModifiers())) {
+            if (lc != Empty.class)
+                samepkg = (isSamePackage(dc, lc) ? 1 : -1);
+            if (samepkg <= 0)
+                throw checkNameFailed(self, lookup, "class is not public");
+        }
+        // At this point dc is known to be accessible.
+        if (self.isPublic()) {
+            return;
+        } else if (lc == Empty.class) {
+            throw checkNameFailed(self, lookup, "member is not public");
+        } else if (self.isProtected()) {
+            if (dc.isAssignableFrom(lc))  return;
+        } else if (self.isPrivate()) {
+            if (isSamePackageMember(dc, lc))  return;
+            throw checkNameFailed(self, lookup, "member is private");
+        }
+        // Fall-through handles the package-private and protected cases.
+        if (samepkg == 0)
+            samepkg = (isSamePackage(dc, lc) ? 1 : -1);
+        if (samepkg > 0)  return;
+        throw checkNameFailed(self, lookup,
+                self.isProtected() ? "member is protected" : "member is private to package");
+    }
 }
--- a/jdk/src/share/classes/sun/dyn/util/VerifyType.java	Thu Dec 17 14:10:20 2009 -0800
+++ b/jdk/src/share/classes/sun/dyn/util/VerifyType.java	Wed Jul 05 17:04:56 2017 +0200
@@ -26,6 +26,7 @@
 package sun.dyn.util;
 
 import java.dyn.MethodType;
+import sun.dyn.empty.Empty;
 
 /**
  * This class centralizes information about the JVM verifier
@@ -73,29 +74,28 @@
     }
 
     /**
-     * Is the given type either java.lang.Void or java.lang.Null?
-     * These types serve as markers for bare nulls and therefore
-     * may be promoted to any type.  This is secure, since
+     * Is the given type java.lang.Null or an equivalent null-only type?
      */
     public static boolean isNullType(Class<?> type) {
         if (type == null)  return false;
-        return type == NULL_CLASS_1 || type == NULL_CLASS_2;
+        return type == NULL_CLASS
+            // This one may also be used as a null type.
+            // TO DO: Decide if we really want to legitimize it here.
+            // Probably we do, unless java.lang.Null really makes it into Java 7
+            //|| type == Void.class
+            // Locally known null-only class:
+            || type == Empty.class
+            ;
     }
-    private static final Class<?> NULL_CLASS_1, NULL_CLASS_2;
+    private static final Class<?> NULL_CLASS;
     static {
-        Class<?> nullClass1 = null, nullClass2 = null;
+        Class<?> nullClass = null;
         try {
-            nullClass1 = Class.forName("java.lang.Null");
+            nullClass = Class.forName("java.lang.Null");
         } catch (ClassNotFoundException ex) {
             // OK, we'll cope
         }
-        NULL_CLASS_1 = nullClass1;
-
-        // This one may also be used as a null type.
-        // TO DO: Decide if we really want to legitimize it here.
-        // Probably we do, unless java.lang.Null really makes it into Java 7
-        nullClass2 = Void.class;
-        NULL_CLASS_2 = nullClass2;
+        NULL_CLASS = nullClass;
     }
 
     /**
@@ -191,6 +191,11 @@
                 // to be captured as a garbage int.
                 // Caller promises that the actual value will be disregarded.
                 return dst == int.class ? 1 : 0;
+            if (isNullType(src))
+                // Special permission for raw conversions: allow a null
+                // to be reinterpreted as anything.  For objects, it is safe,
+                // and for primitives you get a garbage value (probably zero).
+                return 1;
             if (!src.isPrimitive())
                 return 0;
             Wrapper sw = Wrapper.forPrimitiveType(src);
--- a/jdk/src/share/classes/sun/dyn/util/Wrapper.java	Thu Dec 17 14:10:20 2009 -0800
+++ b/jdk/src/share/classes/sun/dyn/util/Wrapper.java	Wed Jul 05 17:04:56 2017 +0200
@@ -141,13 +141,19 @@
      *  @throws IllegalArgumentException for unexpected types
      */
     public static Wrapper forPrimitiveType(Class<?> type) {
+        Wrapper w = findPrimitiveType(type);
+        if (w != null)  return w;
+        if (type.isPrimitive())
+            throw new InternalError(); // redo hash function
+        throw newIllegalArgumentException("not primitive: "+type);
+    }
+
+    static Wrapper findPrimitiveType(Class<?> type) {
         Wrapper w = FROM_PRIM[hashPrim(type)];
         if (w != null && w.primitiveType == type) {
             return w;
         }
-        if (type.isPrimitive())
-            throw new InternalError(); // redo hash function
-        throw newIllegalArgumentException("not primitive: "+type);
+        return null;
     }
 
     /** Return the wrapper that wraps values into the given wrapper type.
@@ -160,7 +166,7 @@
         Wrapper w = findWrapperType(type);
         if (w != null)  return w;
         for (Wrapper x : values())
-            if (w.wrapperType == type)
+            if (x.wrapperType == type)
                 throw new InternalError(); // redo hash function
         throw newIllegalArgumentException("not wrapper: "+type);
     }
@@ -244,8 +250,10 @@
     public Class<?> wrapperType() { return wrapperType; }
 
     /** What is the wrapper type for this wrapper?
-     * The example type must be the wrapper type,
+     * Otherwise, the example type must be the wrapper type,
      * or the corresponding primitive type.
+     * (For {@code OBJECT}, the example type can be any non-primitive,
+     * and is normalized to {@code Object.class}.)
      * The resulting class type has the same type parameter.
      */
     public <T> Class<T> wrapperType(Class<T> exampleType) {
@@ -290,6 +298,16 @@
         return type.isPrimitive();
     }
 
+    /** What is the bytecode signature character for this type?
+     *  All non-primitives, including array types, report as 'L', the signature character for references.
+     */
+    public static char basicTypeChar(Class<?> type) {
+        if (!type.isPrimitive())
+            return 'L';
+        else
+            return forPrimitiveType(type).basicTypeChar();
+    }
+
     /** What is the bytecode signature character for this wrapper's
      *  primitive type?
      */
@@ -309,7 +327,7 @@
     /** Cast a wrapped value to the given type, which may be either a primitive or wrapper type.
      *  Performs standard primitive conversions, including truncation and float conversions.
      *  The given type must be compatible with this wrapper.  That is, it must either
-     *  be the wrapper type (or a subtype, in the case of {@code OBJECT} or else
+     *  be the wrapper type (or a subtype, in the case of {@code OBJECT}) or else
      *  it must be the wrapper's primitive type.
      *  @throws ClassCastException if the given type is not compatible with this wrapper
      */
@@ -326,9 +344,17 @@
      * If the target type is a primitive, change it to a wrapper.
      */
     static <T> Class<T> forceType(Class<?> type, Class<T> exampleType) {
+        boolean z = (type == exampleType ||
+               type.isPrimitive() && forPrimitiveType(type) == findWrapperType(exampleType) ||
+               exampleType.isPrimitive() && forPrimitiveType(exampleType) == findWrapperType(type) ||
+               type == Object.class && !exampleType.isPrimitive());
+        if (!z)
+            System.out.println(type+" <= "+exampleType);
         assert(type == exampleType ||
-               type == asWrapperType(exampleType) ||
-               type == Object.class && exampleType.isInterface());
+               type.isPrimitive() && forPrimitiveType(type) == findWrapperType(exampleType) ||
+               exampleType.isPrimitive() && forPrimitiveType(exampleType) == findWrapperType(type) ||
+               type == Object.class && !exampleType.isPrimitive());
+        @SuppressWarnings("unchecked")
         Class<T> result = (Class<T>) type;  // unchecked warning is expected here
         return result;
     }
--- a/jdk/src/share/classes/sun/security/jgss/GSSManagerImpl.java	Thu Dec 17 14:10:20 2009 -0800
+++ b/jdk/src/share/classes/sun/security/jgss/GSSManagerImpl.java	Wed Jul 05 17:04:56 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2000-2010 Sun Microsystems, Inc.  All Rights Reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -89,6 +89,11 @@
         Oid[] retVal = new Oid[mechs.length];
         int pos = 0;
 
+        // Compatibility with RFC 2853 old NT_HOSTBASED_SERVICE value.
+        if (nameType.equals(GSSNameImpl.oldHostbasedServiceName)) {
+            nameType = GSSName.NT_HOSTBASED_SERVICE;
+        }
+
         // Iterate thru all mechs in GSS
         for (int i = 0; i < mechs.length; i++) {
             // what nametypes does this mech support?
--- a/jdk/src/share/classes/sun/security/jgss/GSSNameImpl.java	Thu Dec 17 14:10:20 2009 -0800
+++ b/jdk/src/share/classes/sun/security/jgss/GSSNameImpl.java	Wed Jul 05 17:04:56 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2000-2010 Sun Microsystems, Inc.  All Rights Reserved.
  * 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,6 +81,29 @@
 
 public class GSSNameImpl implements GSSName {
 
+    /**
+     * The old Oid used in RFC 2853. Now supported as
+     * input parameters in:
+     *
+     * 1. The four overloaded GSSManager.createName(*) methods
+     * 2. GSSManager.getMechsForName(Oid)
+     *
+     * Note that even if a GSSName is created with this old Oid,
+     * its internal name type and getStringNameType() output are
+     * always the new value.
+     */
+    final static Oid oldHostbasedServiceName;
+
+    static {
+        Oid tmp = null;
+        try {
+            tmp = new Oid("1.3.6.1.5.6.2");
+        } catch (Exception e) {
+            // should never happen
+        }
+        oldHostbasedServiceName = tmp;
+    }
+
     private GSSManagerImpl gssManager = null;
 
     /*
@@ -134,6 +157,9 @@
                         Oid mech)
         throws GSSException {
 
+        if (oldHostbasedServiceName.equals(appNameType)) {
+            appNameType = GSSName.NT_HOSTBASED_SERVICE;
+        }
         if (appName == null)
             throw new GSSExceptionImpl(GSSException.BAD_NAME,
                                    "Cannot import null name");
--- a/jdk/src/share/classes/sun/security/jgss/GSSUtil.java	Thu Dec 17 14:10:20 2009 -0800
+++ b/jdk/src/share/classes/sun/security/jgss/GSSUtil.java	Wed Jul 05 17:04:56 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2000-2010 Sun Microsystems, Inc.  All Rights Reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -66,9 +66,6 @@
     public static final Oid NT_GSS_KRB5_PRINCIPAL =
                 GSSUtil.createOid("1.2.840.113554.1.2.2.1");
 
-    public static final Oid NT_HOSTBASED_SERVICE2 =
-                GSSUtil.createOid("1.2.840.113554.1.2.1.4");
-
     private static final String DEFAULT_HANDLER =
             "auth.login.defaultCallbackHandler";
 
--- a/jdk/src/share/classes/sun/security/jgss/wrapper/GSSNameElement.java	Thu Dec 17 14:10:20 2009 -0800
+++ b/jdk/src/share/classes/sun/security/jgss/wrapper/GSSNameElement.java	Wed Jul 05 17:04:56 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright 2005-2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2005-2010 Sun Microsystems, Inc.  All Rights Reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -55,8 +55,7 @@
     static final GSSNameElement DEF_ACCEPTOR = new GSSNameElement();
 
     private static Oid getNativeNameType(Oid nameType, GSSLibStub stub) {
-        if (GSSUtil.NT_GSS_KRB5_PRINCIPAL.equals(nameType) ||
-            GSSName.NT_HOSTBASED_SERVICE.equals(nameType)) {
+        if (GSSUtil.NT_GSS_KRB5_PRINCIPAL.equals(nameType)) {
             Oid[] supportedNTs = null;
             try {
                 supportedNTs = stub.inquireNamesForMech();
@@ -83,15 +82,9 @@
                     if (supportedNTs[i].equals(nameType)) return nameType;
                 }
                 // Special handling the specified name type
-                if (GSSUtil.NT_GSS_KRB5_PRINCIPAL.equals(nameType)) {
-                    SunNativeProvider.debug("Override " + nameType +
-                        " with mechanism default(null)");
-                    return null; // Use mechanism specific default
-                } else {
-                    SunNativeProvider.debug("Override " + nameType +
-                        " with " + GSSUtil.NT_HOSTBASED_SERVICE2);
-                    return GSSUtil.NT_HOSTBASED_SERVICE2;
-                }
+                SunNativeProvider.debug("Override " + nameType +
+                    " with mechanism default(null)");
+                return null; // Use mechanism specific default
             }
         }
         return nameType;
--- a/jdk/src/share/classes/sun/security/krb5/Config.java	Thu Dec 17 14:10:20 2009 -0800
+++ b/jdk/src/share/classes/sun/security/krb5/Config.java	Wed Jul 05 17:04:56 2017 +0200
@@ -109,6 +109,7 @@
     public static synchronized void refresh() throws KrbException {
         singleton = new Config();
         KeyTab.refresh();
+        KrbKdcReq.KdcAccessibility.reset();
     }
 
 
--- a/jdk/src/share/classes/sun/security/krb5/EncryptionKey.java	Thu Dec 17 14:10:20 2009 -0800
+++ b/jdk/src/share/classes/sun/security/krb5/EncryptionKey.java	Wed Jul 05 17:04:56 2017 +0200
@@ -512,6 +512,23 @@
     }
 
     /**
+     * Determines if a kvno matches another kvno. Used in the method
+     * findKey(type, kvno, keys). Always returns true if either input
+     * is null or zero, in case any side does not have kvno info available.
+     *
+     * Note: zero is included because N/A is not a legal value for kvno
+     * in javax.security.auth.kerberos.KerberosKey. Therefore, the info
+     * that the kvno is N/A might be lost when converting between this
+     * class and KerberosKey.
+     */
+    private static boolean versionMatches(Integer v1, Integer v2) {
+        if (v1 == null || v1 == 0 || v2 == null || v2 == 0) {
+            return true;
+        }
+        return v1.equals(v2);
+    }
+
+    /**
      * Find a key with given etype and kvno
      * @param kvno if null, return any (first?) key
      */
@@ -525,15 +542,20 @@
         }
 
         int ktype;
+        boolean etypeFound = false;
         for (int i = 0; i < keys.length; i++) {
             ktype = keys[i].getEType();
             if (EType.isSupported(ktype)) {
                 Integer kv = keys[i].getKeyVersionNumber();
-                if (etype == ktype && (kvno == null || kvno.equals(kv))) {
-                    return keys[i];
+                if (etype == ktype) {
+                    etypeFound = true;
+                    if (versionMatches(kvno, kv)) {
+                        return keys[i];
+                    }
                 }
             }
         }
+
         // Key not found.
         // allow DES key to be used for the DES etypes
         if ((etype == EncryptedData.ETYPE_DES_CBC_CRC ||
@@ -543,12 +565,16 @@
                 if (ktype == EncryptedData.ETYPE_DES_CBC_CRC ||
                         ktype == EncryptedData.ETYPE_DES_CBC_MD5) {
                     Integer kv = keys[i].getKeyVersionNumber();
-                    if (kvno == null || kvno.equals(kv)) {
+                    etypeFound = true;
+                    if (versionMatches(kvno, kv)) {
                         return new EncryptionKey(etype, keys[i].getBytes());
                     }
                 }
             }
         }
+        if (etypeFound) {
+            throw new KrbException(Krb5.KRB_AP_ERR_BADKEYVER);
+        }
         return null;
     }
 }
--- a/jdk/src/share/classes/sun/security/krb5/KrbKdcReq.java	Thu Dec 17 14:10:20 2009 -0800
+++ b/jdk/src/share/classes/sun/security/krb5/KrbKdcReq.java	Wed Jul 05 17:04:56 2017 +0200
@@ -31,25 +31,26 @@
 
 package sun.security.krb5;
 
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.security.Security;
+import java.util.Locale;
 import sun.security.krb5.internal.Krb5;
 import sun.security.krb5.internal.UDPClient;
 import sun.security.krb5.internal.TCPClient;
 import java.io.IOException;
-import java.io.InterruptedIOException;
 import java.net.SocketTimeoutException;
-import java.net.UnknownHostException;
 import java.util.StringTokenizer;
 import java.security.AccessController;
 import java.security.PrivilegedExceptionAction;
 import java.security.PrivilegedActionException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+import java.util.HashSet;
 
 public abstract class KrbKdcReq {
 
-    /**
-     * Default port for a KDC.
-     */
-    private static final int DEFAULT_KDC_PORT = Krb5.KDC_INET_DEFAULT_PORT;
-
     // Currently there is no option to specify retries
     // in the kerberos configuration file
 
@@ -66,7 +67,48 @@
 
     private static int udpPrefLimit = -1;
 
+    private static final String BAD_POLICY_KEY = "krb5.kdc.bad.policy";
+
+    /**
+     * What to do when a KDC is unavailable, specified in the
+     * java.security file with key krb5.kdc.bad.policy.
+     * Possible values can be TRY_LAST or TRY_LESS
+     */
+    private enum BpType {
+        NONE, TRY_LAST, TRY_LESS
+    }
+    private static int tryLessMaxRetries = 1;
+    private static int tryLessTimeout = 5000;
+
+    private static final BpType badPolicy;
+
     static {
+        String value = AccessController.doPrivileged(
+        new PrivilegedAction<String>() {
+            public String run() {
+                return Security.getProperty(BAD_POLICY_KEY);
+            }
+        });
+        if (value != null) {
+            value = value.toLowerCase(Locale.ENGLISH);
+            String[] ss = value.split(":");
+            if ("tryless".equals(ss[0])) {
+                if (ss.length > 1) {
+                    String[] params = ss[1].split(",");
+                    tryLessMaxRetries = Integer.parseInt(params[0]);
+                    if (params.length > 1) {
+                        tryLessTimeout = Integer.parseInt(params[1]);
+                    }
+                }
+                badPolicy = BpType.TRY_LESS;
+            } else if ("trylast".equals(ss[0])) {
+                badPolicy = BpType.TRY_LAST;
+            } else {
+                badPolicy = BpType.NONE;
+            }
+        } else {
+            badPolicy = BpType.NONE;
+        }
 
         /*
          * Get default timeout.
@@ -131,22 +173,16 @@
             }
         }
 
-        /*
-         * Get timeout.
-         */
-
-        int timeout = getKdcTimeout(realm);
-
         String kdcList = cfg.getKDCList(realm);
         if (kdcList == null) {
             throw new KrbException("Cannot get kdc for realm " + realm);
         }
         String tempKdc = null; // may include the port number also
-        StringTokenizer st = new StringTokenizer(kdcList);
-        while (st.hasMoreTokens()) {
-            tempKdc = st.nextToken();
+        for (String tmp: KdcAccessibility.list(kdcList)) {
+            tempKdc = tmp;
             try {
                 send(realm,tempKdc,useTCP);
+                KdcAccessibility.removeBad(tempKdc);
                 break;
             } catch (Exception e) {
                 if (DEBUG) {
@@ -154,6 +190,7 @@
                             tempKdc);
                     e.printStackTrace(System.out);
                 }
+                KdcAccessibility.addBad(tempKdc);
                 savedException = e;
             }
         }
@@ -174,16 +211,21 @@
 
         if (obuf == null)
             return;
-        PrivilegedActionException savedException = null;
+
         int port = Krb5.KDC_INET_DEFAULT_PORT;
+        int retries = DEFAULT_KDC_RETRY_LIMIT;
+        int timeout = getKdcTimeout(realm);
 
-        /*
-         * Get timeout.
-         */
-        int timeout = getKdcTimeout(realm);
-        /*
-         * Get port number for this KDC.
-         */
+        if (badPolicy == BpType.TRY_LESS &&
+                KdcAccessibility.isBad(tempKdc)) {
+            if (retries > tryLessMaxRetries) {
+                retries = tryLessMaxRetries; // less retries
+            }
+            if (timeout > tryLessTimeout) {
+                timeout = tryLessTimeout; // less time
+            }
+        }
+
         String kdc = null;
         String portStr = null;
 
@@ -225,12 +267,12 @@
                                +  port +  ", timeout="
                                + timeout
                                + ", number of retries ="
-                               + DEFAULT_KDC_RETRY_LIMIT
+                               + retries
                                + ", #bytes=" + obuf.length);
         }
 
         KdcCommunication kdcCommunication =
-            new KdcCommunication(kdc, port, useTCP, timeout, obuf);
+            new KdcCommunication(kdc, port, useTCP, timeout, retries, obuf);
         try {
             ibuf = AccessController.doPrivileged(kdcCommunication);
             if (DEBUG) {
@@ -258,14 +300,16 @@
         private int port;
         private boolean useTCP;
         private int timeout;
+        private int retries;
         private byte[] obuf;
 
         public KdcCommunication(String kdc, int port, boolean useTCP,
-                                int timeout, byte[] obuf) {
+                                int timeout, int retries, byte[] obuf) {
             this.kdc = kdc;
             this.port = port;
             this.useTCP = useTCP;
             this.timeout = timeout;
+            this.retries = retries;
             this.obuf = obuf;
         }
 
@@ -294,7 +338,7 @@
             } else {
                 // For each KDC we try DEFAULT_KDC_RETRY_LIMIT (3) times to
                 // get the response
-                for (int i=1; i <= DEFAULT_KDC_RETRY_LIMIT; i++) {
+                for (int i=1; i <= retries; i++) {
                     UDPClient kdcClient = new UDPClient(kdc, port, timeout);
 
                     if (DEBUG) {
@@ -310,7 +354,7 @@
                          * Send the data to the kdc.
                          */
 
-                    kdcClient.send(obuf);
+                        kdcClient.send(obuf);
 
                         /*
                          * And get a response.
@@ -323,7 +367,7 @@
                                 System.out.println ("SocketTimeOutException with " +
                                                     "attempt: " + i);
                             }
-                            if (i == DEFAULT_KDC_RETRY_LIMIT) {
+                            if (i == retries) {
                                 ibuf = null;
                                 throw se;
                             }
@@ -385,4 +429,67 @@
 
         return -1;
     }
+
+    /**
+     * Maintains a KDC accessible list. Unavailable KDCs are put into a
+     * blacklist, when a KDC in the blacklist is available, it's removed
+     * from there. No insertion order in the blacklist.
+     *
+     * There are two methods to deal with KDCs in the blacklist. 1. Only try
+     * them when there's no KDC not on the blacklist. 2. Still try them, but
+     * with lesser number of retries and smaller timeout value.
+     */
+    static class KdcAccessibility {
+        // Known bad KDCs
+        private static Set<String> bads = new HashSet<String>();
+
+        private static synchronized void addBad(String kdc) {
+            if (DEBUG) {
+                System.out.println(">>> KdcAccessibility: add " + kdc);
+            }
+            bads.add(kdc);
+        }
+
+        private static synchronized void removeBad(String kdc) {
+            if (DEBUG) {
+                System.out.println(">>> KdcAccessibility: remove " + kdc);
+            }
+            bads.remove(kdc);
+        }
+
+        private static synchronized boolean isBad(String kdc) {
+            return bads.contains(kdc);
+        }
+
+        public static synchronized void reset() {
+            if (DEBUG) {
+                System.out.println(">>> KdcAccessibility: reset");
+            }
+            bads.clear();
+        }
+
+        // Returns a preferred KDC list by putting the bad ones at the end
+        private static synchronized String[] list(String kdcList) {
+            StringTokenizer st = new StringTokenizer(kdcList);
+            List<String> list = new ArrayList<String>();
+            if (badPolicy == BpType.TRY_LAST) {
+                List<String> badkdcs = new ArrayList<String>();
+                while (st.hasMoreTokens()) {
+                    String t = st.nextToken();
+                    if (bads.contains(t)) badkdcs.add(t);
+                    else list.add(t);
+                }
+                // Bad KDCs are put at last
+                list.addAll(badkdcs);
+            } else {
+                // All KDCs are returned in their original order,
+                // This include TRY_LESS and NONE
+                while (st.hasMoreTokens()) {
+                    list.add(st.nextToken());
+                }
+            }
+            return list.toArray(new String[list.size()]);
+        }
+    }
 }
+
--- a/jdk/src/share/classes/sun/security/ssl/krb5/KerberosClientKeyExchangeImpl.java	Thu Dec 17 14:10:20 2009 -0800
+++ b/jdk/src/share/classes/sun/security/ssl/krb5/KerberosClientKeyExchangeImpl.java	Wed Jul 05 17:04:56 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright 2003-2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2003-2010 Sun Microsystems, Inc.  All Rights Reserved.
  * 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,11 +50,12 @@
 import sun.security.krb5.internal.crypto.KeyUsage;
 
 import sun.security.jgss.krb5.Krb5Util;
+import sun.security.krb5.KrbException;
+import sun.security.krb5.internal.Krb5;
 
 import sun.security.ssl.Debug;
 import sun.security.ssl.HandshakeInStream;
 import sun.security.ssl.HandshakeOutStream;
-import sun.security.ssl.KerberosClientKeyExchange;
 import sun.security.ssl.ProtocolVersion;
 
 /**
@@ -188,7 +189,14 @@
             // See if we have the right key to decrypt the ticket to get
             // the session key.
             int encPartKeyType = encPart.getEType();
-            KerberosKey dkey = findKey(encPartKeyType, serverKeys);
+            Integer encPartKeyVersion = encPart.getKeyVersionNumber();
+            KerberosKey dkey = null;
+            try {
+                dkey = findKey(encPartKeyType, encPartKeyVersion, serverKeys);
+            } catch (KrbException ke) { // a kvno mismatch
+                throw new IOException(
+                        "Cannot find key matching version number", ke);
+            }
             if (dkey == null) {
                 // %%% Should print string repr of etype
                 throw new IOException(
@@ -355,12 +363,34 @@
         return localPrincipal;
     }
 
-    private static KerberosKey findKey(int etype, KerberosKey[] keys) {
+    /**
+     * Determines if a kvno matches another kvno. Used in the method
+     * findKey(etype, version, keys). Always returns true if either input
+     * is null or zero, in case any side does not have kvno info available.
+     *
+     * Note: zero is included because N/A is not a legal value for kvno
+     * in javax.security.auth.kerberos.KerberosKey. Therefore, the info
+     * that the kvno is N/A might be lost when converting between
+     * EncryptionKey and KerberosKey.
+     */
+    private static boolean versionMatches(Integer v1, int v2) {
+        if (v1 == null || v1 == 0 || v2 == 0) {
+            return true;
+        }
+        return v1.equals(v2);
+    }
+
+    private static KerberosKey findKey(int etype, Integer version,
+            KerberosKey[] keys) throws KrbException {
         int ktype;
+        boolean etypeFound = false;
         for (int i = 0; i < keys.length; i++) {
             ktype = keys[i].getKeyType();
             if (etype == ktype) {
-                return keys[i];
+                etypeFound = true;
+                if (versionMatches(version, keys[i].getVersionNumber())) {
+                    return keys[i];
+                }
             }
         }
         // Key not found.
@@ -370,14 +400,20 @@
             for (int i = 0; i < keys.length; i++) {
                 ktype = keys[i].getKeyType();
                 if (ktype == EncryptedData.ETYPE_DES_CBC_CRC ||
-                    ktype == EncryptedData.ETYPE_DES_CBC_MD5) {
-                    return new KerberosKey(keys[i].getPrincipal(),
-                        keys[i].getEncoded(),
-                        etype,
-                        keys[i].getVersionNumber());
+                        ktype == EncryptedData.ETYPE_DES_CBC_MD5) {
+                    etypeFound = true;
+                    if (versionMatches(version, keys[i].getVersionNumber())) {
+                        return new KerberosKey(keys[i].getPrincipal(),
+                            keys[i].getEncoded(),
+                            etype,
+                            keys[i].getVersionNumber());
+                    }
                 }
             }
         }
+        if (etypeFound) {
+            throw new KrbException(Krb5.KRB_AP_ERR_BADKEYVER);
+        }
         return null;
     }
 }
--- a/jdk/src/share/lib/security/java.security	Thu Dec 17 14:10:20 2009 -0800
+++ b/jdk/src/share/lib/security/java.security	Wed Jul 05 17:04:56 2017 +0200
@@ -55,10 +55,10 @@
 
 #
 # Select the source of seed data for SecureRandom. By default an
-# attempt is made to use the entropy gathering device specified by 
+# attempt is made to use the entropy gathering device specified by
 # the securerandom.source property. If an exception occurs when
-# accessing the URL then the traditional system/thread activity 
-# algorithm is used. 
+# accessing the URL then the traditional system/thread activity
+# algorithm is used.
 #
 # On Solaris and Linux systems, if file:/dev/urandom is specified and it
 # exists, a special SecureRandom implementation is activated by default.
@@ -72,7 +72,7 @@
 # The entropy gathering device is described as a URL and can also
 # be specified with the system property "java.security.egd". For example,
 #   -Djava.security.egd=file:/dev/urandom
-# Specifying this system property will override the securerandom.source 
+# Specifying this system property will override the securerandom.source
 # setting.
 
 #
@@ -149,7 +149,7 @@
 security.overridePropertiesFile=true
 
 #
-# Determines the default key and trust manager factory algorithms for 
+# Determines the default key and trust manager factory algorithms for
 # the javax.net.ssl package.
 #
 ssl.KeyManagerFactory.algorithm=SunX509
@@ -168,10 +168,10 @@
 # is to cache for 30 seconds.
 #
 # NOTE: setting this to anything other than the default value can have
-#       serious security implications. Do not set it unless 
+#       serious security implications. Do not set it unless
 #       you are sure you are not exposed to DNS spoofing attack.
 #
-#networkaddress.cache.ttl=-1 
+#networkaddress.cache.ttl=-1
 
 # The Java-level namelookup cache policy for failed lookups:
 #
@@ -183,7 +183,7 @@
 # the WINS name service in addition to DNS, name service lookups
 # that fail may take a noticeably long time to return (approx. 5 seconds).
 # For this reason the default caching policy is to maintain these
-# results for 10 seconds. 
+# results for 10 seconds.
 #
 #
 networkaddress.cache.negative.ttl=10
@@ -192,7 +192,7 @@
 # Properties to configure OCSP for certificate revocation checking
 #
 
-# Enable OCSP 
+# Enable OCSP
 #
 # By default, OCSP is not used for certificate revocation checking.
 # This property enables the use of OCSP when set to the value "true".
@@ -201,7 +201,7 @@
 #
 # Example,
 #   ocsp.enable=true
- 
+
 #
 # Location of the OCSP responder
 #
@@ -213,15 +213,15 @@
 #
 # Example,
 #   ocsp.responderURL=http://ocsp.example.net:80
- 
+
 #
 # Subject name of the OCSP responder's certificate
 #
 # By default, the certificate of the OCSP responder is that of the issuer
 # of the certificate being validated. This property identifies the certificate
-# of the OCSP responder when the default does not apply. Its value is a string 
-# distinguished name (defined in RFC 2253) which identifies a certificate in 
-# the set of certificates supplied during cert path validation. In cases where 
+# of the OCSP responder when the default does not apply. Its value is a string
+# distinguished name (defined in RFC 2253) which identifies a certificate in
+# the set of certificates supplied during cert path validation. In cases where
 # the subject name alone is not sufficient to uniquely identify the certificate
 # then both the "ocsp.responderCertIssuerName" and
 # "ocsp.responderCertSerialNumber" properties must be used instead. When this
@@ -237,14 +237,14 @@
 # of the certificate being validated. This property identifies the certificate
 # of the OCSP responder when the default does not apply. Its value is a string
 # distinguished name (defined in RFC 2253) which identifies a certificate in
-# the set of certificates supplied during cert path validation. When this 
-# property is set then the "ocsp.responderCertSerialNumber" property must also 
-# be set. When the "ocsp.responderCertSubjectName" property is set then this 
+# the set of certificates supplied during cert path validation. When this
+# property is set then the "ocsp.responderCertSerialNumber" property must also
+# be set. When the "ocsp.responderCertSubjectName" property is set then this
 # property is ignored.
 #
 # Example,
 #   ocsp.responderCertIssuerName="CN=Enterprise CA, O=XYZ Corp"
- 
+
 #
 # Serial number of the OCSP responder's certificate
 #
@@ -259,4 +259,31 @@
 #
 # Example,
 #   ocsp.responderCertSerialNumber=2A:FF:00
- 
+
+#
+# Policy for failed Kerberos KDC lookups:
+#
+# When a KDC is unavailable (network error, service failure, etc), it is
+# put inside a blacklist and accessed less often for future requests. The
+# value (case-insensitive) for this policy can be:
+#
+# tryLast
+#    KDCs in the blacklist are always tried after those not on the list.
+#
+# tryLess[:max_retries,timeout]
+#    KDCs in the blacklist are still tried by their order in the configuration,
+#    but with smaller max_retries and timeout values. max_retries and timeout
+#    are optional numerical parameters (default 1 and 5000, which means once
+#    and 5 seconds). Please notes that if any of the values defined here is
+#    more than what is defined in krb5.conf, it will be ignored.
+#
+# Whenever a KDC is detected as available, it is removed from the blacklist.
+# The blacklist is reset when krb5.conf is reloaded. You can add
+# refreshKrb5Config=true to a JAAS configuration file so that krb5.conf is
+# reloaded whenever a JAAS authentication is attempted.
+#
+# Example,
+#   krb5.kdc.bad.policy = tryLast
+#   krb5.kdc.bad.policy = tryLess:2,2000
+krb5.kdc.bad.policy = tryLast
+
--- a/jdk/src/share/native/java/lang/StrictMath.c	Thu Dec 17 14:10:20 2009 -0800
+++ b/jdk/src/share/native/java/lang/StrictMath.c	Wed Jul 05 17:04:56 2017 +0200
@@ -95,18 +95,6 @@
 }
 
 JNIEXPORT jdouble JNICALL
-Java_java_lang_StrictMath_ceil(JNIEnv *env, jclass unused, jdouble d)
-{
-    return (jdouble) jceil((double)d);
-}
-
-JNIEXPORT jdouble JNICALL
-Java_java_lang_StrictMath_floor(JNIEnv *env, jclass unused, jdouble d)
-{
-    return (jdouble) jfloor((double)d);
-}
-
-JNIEXPORT jdouble JNICALL
 Java_java_lang_StrictMath_atan2(JNIEnv *env, jclass unused, jdouble d1, jdouble d2)
 {
     return (jdouble) jatan2((double)d1, (double)d2);
--- a/jdk/src/windows/native/java/net/SocketInputStream.c	Thu Dec 17 14:10:20 2009 -0800
+++ b/jdk/src/windows/native/java/net/SocketInputStream.c	Wed Jul 05 17:04:56 2017 +0200
@@ -121,6 +121,9 @@
             newfd = (*env)->GetIntField(env, fdObj, IO_fd_fdID);
             if (newfd == -1) {
                 NET_ThrowSocketException(env, "Socket Closed");
+                if (bufP != BUF) {
+                    free(bufP);
+                }
                 return -1;
             }
         }
--- a/jdk/test/Makefile	Thu Dec 17 14:10:20 2009 -0800
+++ b/jdk/test/Makefile	Wed Jul 05 17:04:56 2017 +0200
@@ -291,7 +291,7 @@
   fi ; \
   testExitCode=`$(CAT) $(EXITCODE)`; \
   $(ECHO) "EXIT CODE: $${testExitCode}"; \
-  exit ${testExitCode}
+  exit $${testExitCode}
 
 BUNDLE_UP_AND_EXIT = \
 ( \
@@ -300,7 +300,7 @@
   $(RM) -f $(STATS_TXT) $(RUNLIST) $(PASSLIST) $(FAILLIST) $(EXITCODE); \
   $(ECHO) "$${jtregExitCode}" > $(EXITCODE); \
   if [ -r "$${_summary}" ] ; then \
-    $(ECHO) "Summary: $${_summary}" > $(STATS_TXT); \
+    $(ECHO) "Summary: $(UNIQUE_DIR)" > $(STATS_TXT); \
     $(EXPAND) $${_summary} | $(EGREP) -v ' Not run\.' > $(RUNLIST); \
     $(EGREP) ' Passed\.' $(RUNLIST) \
       | $(EGREP) -v ' Error\.' \
@@ -370,7 +370,8 @@
 endif
 # With samevm, you cannot use -javaoptions?
 ifeq ($(USE_JTREG_SAMEVM),true)
-  EXTRA_JTREG_OPTIONS += -samevm $(JAVA_ARGS) $(JAVA_ARGS:%=-vmoption:%)
+  JTREG_SAMEVM_OPTION = -samevm
+  EXTRA_JTREG_OPTIONS += $(JTREG_SAMEVM_OPTION) $(JAVA_ARGS) $(JAVA_ARGS:%=-vmoption:%)
   JTREG_TEST_OPTIONS = $(JAVA_VM_ARGS:%=-vmoption:%)
 else
   JTREG_TEST_OPTIONS = $(JAVA_ARGS:%=-javaoptions:%) $(JAVA_VM_ARGS:%=-vmoption:%)
@@ -418,8 +419,9 @@
 $(MAKE) TESTDIRS="$(call TestDirs, $?)" USE_JTREG_SAMEVM=false UNIQUE_DIR=$@ jtreg_tests
 endef
 define SummaryInfo
-$(ECHO) "Summary for: $?"
+$(ECHO) "########################################################"
 $(CAT) $(?:%=$(ABS_TEST_OUTPUT_DIR)/%/$(STATS_TXT_NAME))
+$(ECHO) "########################################################"
 endef
 
 # ------------------------------------------------------------------
@@ -446,10 +448,14 @@
 jdk_beans2: java/beans/Beans java/beans/EventHandler java/beans/XMLDecoder \
             java/beans/PropertyEditor
 	$(call RunOthervmBatch)
+
+# Stable othervm testruns (minus items from PROBLEM_LIST)
+#   Using samevm has serious problems with these tests
 JDK_ALL_TARGETS += jdk_beans3
 jdk_beans3: java/beans/XMLEncoder
 	$(call RunOthervmBatch)
 
+# All beans tests
 jdk_beans: jdk_beans1 jdk_beans2 jdk_beans3
 	@$(SummaryInfo)
 
@@ -475,6 +481,7 @@
 jdk_management2: com/sun/jmx com/sun/management sun/management
 	$(call RunOthervmBatch)
 
+# All management tests
 jdk_management: jdk_management1 jdk_management2
 	@$(SummaryInfo)
 
@@ -506,10 +513,14 @@
 jdk_nio2: java/nio/Buffer java/nio/ByteOrder \
           java/nio/channels java/nio/BufferPoolMXBean java/nio/MappedByteBuffer
 	$(call RunOthervmBatch)
+
+# Stable othervm testruns (minus items from PROBLEM_LIST)
+#   Using samevm has serious problems with these tests
 JDK_ALL_TARGETS += jdk_nio3
 jdk_nio3: com/sun/nio sun/nio
 	$(call RunOthervmBatch)
 
+# All nio tests
 jdk_nio: jdk_nio1 jdk_nio2 jdk_nio3
 	@$(SummaryInfo)
 
@@ -529,10 +540,14 @@
 JDK_ALL_TARGETS += jdk_security2
 jdk_security2: javax/crypto com/sun/crypto
 	$(call RunOthervmBatch)
+
+# Stable othervm testruns (minus items from PROBLEM_LIST)
+#   Using samevm has serious problems with these tests
 JDK_ALL_TARGETS += jdk_security3
 jdk_security3: com/sun/security lib/security javax/security sun/security
 	$(call RunOthervmBatch)
 
+# All security tests
 jdk_security: jdk_security1 jdk_security2 jdk_security3
 	@$(SummaryInfo)
 
@@ -547,15 +562,18 @@
 jdk_text: java/text sun/text
 	$(call RunSamevmBatch)
 
-# Stable othervm testruns (minus items from PROBLEM_LIST)
-#   Using samevm has serious problems with these tests
+# Stable samevm testruns (minus items from PROBLEM_LIST)
 JDK_ALL_TARGETS += jdk_tools1
 jdk_tools1: com/sun/jdi
 	$(call RunSamevmBatch)
+
+# Stable othervm testruns (minus items from PROBLEM_LIST)
+#   Using samevm has serious problems with these tests
 JDK_ALL_TARGETS += jdk_tools2
 jdk_tools2: com/sun/tools sun/jvmstat sun/tools tools vm com/sun/servicetag com/sun/tracing
 	$(call RunOthervmBatch)
 
+# All tools tests
 jdk_tools: jdk_tools1 jdk_tools2
 	@$(SummaryInfo)
 
@@ -567,7 +585,9 @@
 # ------------------------------------------------------------------
 
 # Run all tests
-jdk_all: $(filter-out jdk_awt jdk_rmi jdk_swing, $(JDK_ALL_TARGETS))
+FILTER_OUT_LIST=jdk_awt jdk_rmi jdk_swing
+JDK_ALL_STABLE_TARGETS := $(filter-out $(FILTER_OUT_LIST), $(JDK_ALL_TARGETS))
+jdk_all: $(JDK_ALL_STABLE_TARGETS)
 	@$(SummaryInfo)
 
 # These are all phony targets
@@ -581,16 +601,22 @@
 JTREG_BASIC_OPTIONS += $(EXTRA_JTREG_OPTIONS)
 # Only run automatic tests
 JTREG_BASIC_OPTIONS += -a
+# Always turn on assertions
+JTREG_ASSERT_OPTION = -ea -esa
+JTREG_BASIC_OPTIONS += $(JTREG_ASSERT_OPTION)
 # Report details on all failed or error tests, times too
 JTREG_BASIC_OPTIONS += -v:fail,error,time
 # Retain all files for failing tests
 JTREG_BASIC_OPTIONS += -retain:fail,error
 # Ignore tests are not run and completely silent about it
-JTREG_BASIC_OPTIONS += -ignore:quiet
-# Multiple by 2 the timeout numbers
-JTREG_BASIC_OPTIONS += -timeoutFactor:2
+JTREG_IGNORE_OPTION = -ignore:quiet
+JTREG_BASIC_OPTIONS += $(JTREG_IGNORE_OPTION)
+# Multiple by 4 the timeout numbers
+JTREG_TIMEOUT_OPTION =  -timeoutFactor:4
+JTREG_BASIC_OPTIONS += $(JTREG_TIMEOUT_OPTION)
 # Boost the max memory for jtreg to avoid gc thrashing
-JTREG_BASIC_OPTIONS += -J-Xmx512m
+JTREG_MEMORY_OPTION = -J-Xmx512m
+JTREG_BASIC_OPTIONS += $(JTREG_MEMORY_OPTION)
 
 # Make sure jtreg exists
 $(JTREG): $(JT_HOME)
--- a/jdk/test/ProblemList.txt	Thu Dec 17 14:10:20 2009 -0800
+++ b/jdk/test/ProblemList.txt	Wed Jul 05 17:04:56 2017 +0200
@@ -431,6 +431,11 @@
 
 # jdk_management
 
+# Fails on Windows 2000, Test failed for iiop java.lang.NullPointerException
+#  at org.omg.stub.javax.management.remote.rmi._RMIConnectionImpl_Tie._invoke(Unknown Source)
+#  at com.sun.corba.se.impl.protocol.CorbaServerRequestDispatcherImpl.dispatchToServant(CorbaServerRequestDispatcherImpl.java:653)
+javax/management/remote/mandatory/connection/ReconnectTest.java generic-all
+
 # Solaris 10 sparc, NPE from org.omg.stub.javax.management.remote.rmi._RMIConnectionImpl_Tie._invoke
 javax/management/remote/mandatory/threads/ExecutorTest.java 	generic-all
 
@@ -494,10 +499,6 @@
 # Problems with rounding add failures on solaris-sparcv9 and -server
 java/math/BigDecimal/AddTests.java			 	solaris-sparcv9
 
-# Problems on windows with samevm, missing inputstream close()?
-# Also times out on solaris-sparcv9 -server
-java/math/BigInteger/BigIntegerTest.java		 	generic-all
-
 # Should be samevm? But seems problematic with samevm on windows
 java/math/BigInteger/ModPow65537.java			 	generic-all
 
@@ -581,6 +582,14 @@
 # Suspect many of these tests auffer from using fixed ports, no concrete 
 #   evidence.
 
+# Dies on Solaris 10 sparc and sparcv9, Linux  -ea -esa with 
+#   Interrupted or IO exception, maybe writing to non-unique named file?
+com/sun/net/httpserver/bugs/B6373555.java			generic-all
+
+# Dies on pretty much all platforms when run with -ea -esa, Assertion error
+java/net/CookieHandler/TestHttpCookie.java			generic-all
+java/net/URLClassLoader/closetest/CloseTest.java		generic-all
+
 # Fails on OpenSolaris, BindException unexpected 
 java/net/BindException/Test.java				generic-all
 
@@ -717,6 +726,9 @@
 # Connection refused, windows samevm
 sun/net/www/protocol/http/DigestTest.java			generic-all
 
+# Fails on Fedora 9 32bit & 64bit & Solaris 10, wrong proxy for http://localhost/index.html
+java/net/ProxySelector/B6737819.java				generic-all
+
 ############################################################################
 
 # jdk_nio
@@ -724,6 +736,33 @@
 # Suspect many of these tests auffer from using fixed ports, no concrete 
 #   evidence.
 
+# Fails with -ea -esa, Assertion error, but only on Solaris 10 machines?
+com/sun/nio/sctp/SctpChannel/Send.java				generic-all
+com/sun/nio/sctp/SctpChannel/Shutdown.java			generic-all
+
+# Fails on Windows 2000, Can't delete test directory .\x.SetLastModified.dir
+#    at SetLastModified.main(SetLastModified.java:107)
+java/io/File/SetLastModified.java                               generic-all
+
+# Fails on Solaris 10 x64, address already in use
+java/nio/channels/DatagramChannel/SRTest.java			generic-all
+
+# Fails on Solaris 10 x86, times out
+java/nio/channels/DatagramChannel/Sender.java			generic-all
+
+# Fails on Fedora 9 x86, address in use
+java/nio/channels/Selector/SelectWrite.java			generic-all
+
+# Fails on Fedora 9 32bit times out
+java/nio/channels/DatagramChannel/EmptyBuffer.java		generic-all
+
+# Fails on Windows 2000, ExceptionInInitializerError
+#   in WindowsAsynchronousServerSocketChannelImpl.java:316
+java/nio/channels/AsynchronousChannelGroup/Unbounded.java	generic-all
+
+# Fails on Windows 2000,  times out
+java/nio/channels/FileChannel/Transfer.java			generic-all
+
 # Fails on OpenSolaris, IllegalStateException: Cannot add or remove addresses 
 #    from a channel that is bound to the wildcard address
 com/sun/nio/sctp/SctpChannel/Bind.java				generic-all
@@ -893,6 +932,48 @@
 
 # jdk_security
 
+# Fails with -ea -esa, but only on Solaris sparc? Suspect it is timing out
+sun/security/tools/keytool/standard.sh				generic-all
+
+# Fails on Solaris 10 X64, address already in use
+sun/security/krb5/auto/HttpNegotiateServer.java			generic-all
+
+# Fails on almost all platforms
+#   java.lang.UnsupportedClassVersionError: SerialTest : 
+#      Unsupported major.minor version 51.0
+#    at java.lang.ClassLoader.defineClass1(Native Method)
+sun/security/util/Oid/S11N.sh					generic-all
+
+# Fails on Fedora 9 32bit
+#  GSSException: Failure unspecified at GSS-API level (Mechanism level: 
+#    Invalid argument (400) - Cannot find key of appropriate type to decrypt 
+#    AP REP - DES CBC mode with MD5)
+#  at sun.security.jgss.krb5.Krb5Context.acceptSecContext(Krb5Context.java:778)
+sun/security/krb5/auto/NonMutualSpnego.java			generic-all
+
+# Fails on Solaris 10 sparc, GSSException: Failure unspecified at GSS-API level
+#   Also fails on Windows 2000 similar way
+sun/security/krb5/auto/ok-as-delegate.sh			generic-all
+
+# Fails on Windows 2000, GSSException: Failure unspecified at GSS-API level
+#    (Mechanism level: Request is a replay (34))
+sun/security/krb5/auto/ok-as-delegate-xrealm.sh			generic-all
+
+# Fails on Windows 2000, ExceptionInInitializerError
+sun/security/mscapi/AccessKeyStore.sh				generic-all
+
+# Fails on Windows 2000, UnsatisfiedLinkError: libnspr4.dll: Access is denied
+sun/security/pkcs11/KeyAgreement/TestDH.java			generic-all
+
+# Fails on Windows 2000, UnsatisfiedLinkError: libnspr4.dll: Access is denied
+sun/security/pkcs11/fips/ClientJSSEServerJSSE.java		generic-all
+
+# Fails on Solaris 10, KrbException: Additional pre-authentication required (25)
+sun/security/krb5/auto/basic.sh					generic-all
+
+# Fails on Fedora 9 64bit, PKCS11Exception: CKR_DEVICE_ERROR
+sun/security/pkcs11/KeyAgreement/TestDH.java			generic-all
+
 # Run too slow on Solaris 10 sparc
 sun/security/ssl/com/sun/net/ssl/internal/ssl/InputRecord/SSLSocketTimeoutNulls.java solaris-sparc
 sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLSocketImpl/ClientTimeout.java solaris-sparc
@@ -1088,6 +1169,16 @@
 #  So most if not all tools tests are now being run with "othervm" mode.
 #  Some of these tools tests have a tendency to use fixed ports, bad idea.
 
+# Fails with -ea -esa on Solaris, Assertion error (Solaris specific test)
+com/sun/tracing/BasicFunctionality.java				generic-all
+
+# Fails on Fedora 9 32bit, jps output differs problem
+sun/tools/jstatd/jstatdDefaults.sh				generic-all
+
+# Fails on Linux Fedora 9 32bit, Could not read data for remote JVM 16133
+#       jstat output differs from expected output
+sun/tools/jstatd/jstatdExternalRegistry.sh			generic-all
+
 # Output of jps differs from expected output.
 #   Invalid argument count on solaris-sparc and x64
 sun/tools/jstatd/jstatdPort.sh					generic-all
@@ -1099,6 +1190,11 @@
 sun/tools/jps/jps-Vvml_2.sh					generic-all
 sun/tools/jps/jps-m_2.sh					generic-all
 
+# Fails on Solaris 10 sparcv9, shell exits with 1
+#  Turning off use of shared archive because of choice of garbage collector or large pages 
+#  Could not synchronize with target
+sun/tools/jps/jps-v_1.sh					generic-all
+
 # Fails on OpenSolaris "Could not synchronize with target"
 sun/tools/jps/jps-Defaults.sh					generic-all
 sun/tools/jps/jps-V_2.sh					generic-all
@@ -1160,6 +1256,12 @@
 
 # jdk_util
 
+# Fails with -ea -esa on all platforms with Assertion error
+java/util/ResourceBundle/Test4300693.java			generic-all
+
+# Failing on all -client 32bit platforms starting with b77? See 6908348.
+java/util/concurrent/BlockingQueue/CancelledProducerConsumerLoops.java generic-all
+
 # Assert error, failures, on Linux Fedora 9 -server
 #   Windows samevm failure, assert error "Passed = 134, failed = 2"
 java/util/Arrays/ArrayObjectMethods.java			generic-all
--- a/jdk/test/com/sun/jdi/NoLaunchOptionTest.java	Thu Dec 17 14:10:20 2009 -0800
+++ b/jdk/test/com/sun/jdi/NoLaunchOptionTest.java	Wed Jul 05 17:04:56 2017 +0200
@@ -31,6 +31,9 @@
  *  @build VMConnection
  *  @run main/othervm NoLaunchOptionTest
  */
+
+import java.net.ServerSocket;
+
 public class NoLaunchOptionTest extends Object {
     private Process subprocess;
     private int subprocessStatus;
@@ -121,12 +124,19 @@
     }
 
     public static void main(String[] args) throws Exception {
+        // find a free port
+        ServerSocket ss = new ServerSocket(0);
+        int port = ss.getLocalPort();
+        ss.close();
+        String address = String.valueOf(port);
+
         String javaExe = System.getProperty("java.home") +
             java.io.File.separator + "bin" +
             java.io.File.separator + "java";
         String targetClass = "NotAClass";
         String cmds [] = {javaExe,
-                          "-agentlib:jdwp=transport=dt_socket,address=8000," +
+                          "-agentlib:jdwp=transport=dt_socket,address=" +
+                          address + "," +
                           "onthrow=java.lang.ClassNotFoundException,suspend=n",
                           targetClass};
         NoLaunchOptionTest myTest = new NoLaunchOptionTest();
--- a/jdk/test/com/sun/jdi/OptionTest.java	Thu Dec 17 14:10:20 2009 -0800
+++ b/jdk/test/com/sun/jdi/OptionTest.java	Wed Jul 05 17:04:56 2017 +0200
@@ -32,6 +32,9 @@
  *  @run compile -g VMConnection.java
  *  @run main/othervm OptionTest
  */
+
+import java.net.ServerSocket;
+
 public class OptionTest extends Object {
     private Process subprocess;
     private int subprocessStatus;
@@ -122,12 +125,18 @@
     }
 
     public static void main(String[] args) throws Exception {
+        // find a free port
+        ServerSocket ss = new ServerSocket(0);
+        int port = ss.getLocalPort();
+        ss.close();
+        String address = String.valueOf(port);
+
         String javaExe = System.getProperty("java.home") +
             java.io.File.separator + "bin" +
             java.io.File.separator + "java";
         String targetClass = "HelloWorld";
         String baseOptions = "transport=dt_socket" +
-                              ",address=8000" +
+                              ",address=" + address +
                               ",server=y" +
                               ",suspend=n";
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/dyn/MethodHandlesTest.java	Wed Jul 05 17:04:56 2017 +0200
@@ -0,0 +1,1839 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * 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.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/* @test
+ * @summary unit tests for java.dyn.MethodHandles
+ * @compile -XDinvokedynamic MethodHandlesTest.java
+ * @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableInvokeDynamic jdk.java.dyn.MethodHandlesTest
+ */
+
+package jdk.java.dyn;
+
+import java.dyn.*;
+import java.dyn.MethodHandles.Lookup;
+import java.lang.reflect.*;
+import java.util.*;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import org.junit.*;
+import static org.junit.Assert.*;
+
+
+/**
+ *
+ * @author jrose
+ */
+public class MethodHandlesTest {
+    // How much output?
+    static int verbosity = 1;
+
+    // Set this true during development if you want to fast-forward to
+    // a particular new, non-working test.  Tests which are known to
+    // work (or have recently worked) test this flag and return on true.
+    static boolean CAN_SKIP_WORKING = false;
+    //static { CAN_SKIP_WORKING = true; }
+
+    // Set true to test more calls.  If false, some tests are just
+    // lookups, without exercising the actual method handle.
+    static boolean DO_MORE_CALLS = false;
+
+
+    @Test
+    public void testFirst() throws Throwable {
+        verbosity += 9; try {
+            // left blank for debugging
+        } finally { verbosity -= 9; }
+    }
+
+    // current failures
+    @Test @Ignore("failure in call to makeRawRetypeOnly in ToGeneric")
+    public void testFail_1() throws Throwable {
+        testSpreadArguments(int.class, 0, 6);
+    }
+    @Test @Ignore("failure in JVM when expanding the stack")
+    public void testFail_2() throws Throwable {
+        // if CONV_OP_IMPLEMENTED_MASK includes OP_SPREAD_ARGS, this crashes:
+        testSpreadArguments(Object.class, 0, 2);
+    }
+    @Test @Ignore("IllArgEx failure in call to ToGeneric.make")
+    public void testFail_3() throws Throwable {
+        testSpreadArguments(int.class, 1, 2);
+    }
+    @Test @Ignore("IllArgEx failure in call to ToGeneric.make")
+    public void testFail_4() throws Throwable {
+        testCollectArguments(int.class, 1, 2);
+    }
+    @Test @Ignore("cannot collect leading primitive types")
+    public void testFail_5() throws Throwable {
+        testInvokers(MethodType.genericMethodType(2).changeParameterType(0, int.class));
+    }
+    @Test @Ignore("should not insert arguments beyond MethodHandlePushLimit")
+    public void testFail_6() throws Throwable {
+        testInsertArguments(0, 0, MAX_ARG_INCREASE+1);
+    }
+    static final int MAX_ARG_INCREASE = 3;
+
+    public MethodHandlesTest() {
+    }
+
+    String testName;
+    int posTests, negTests;
+    @After
+    public void printCounts() {
+        if (verbosity >= 1 && (posTests | negTests) != 0) {
+            System.out.println();
+            if (posTests != 0)  System.out.println("=== "+testName+": "+posTests+" positive test cases run");
+            if (negTests != 0)  System.out.println("=== "+testName+": "+negTests+" negative test cases run");
+        }
+    }
+    void countTest(boolean positive) {
+        if (positive) ++posTests;
+        else          ++negTests;
+    }
+    void countTest() { countTest(true); }
+    void startTest(String name) {
+        if (testName != null)  printCounts();
+        if (verbosity >= 0)
+            System.out.println(name);
+        posTests = negTests = 0;
+        testName = name;
+    }
+
+    @BeforeClass
+    public static void setUpClass() throws Exception {
+        calledLog.clear();
+        calledLog.add(null);
+        nextArg = 1000000;
+    }
+
+    @AfterClass
+    public static void tearDownClass() throws Exception {
+    }
+
+    static List<Object> calledLog = new ArrayList<Object>();
+    static Object logEntry(String name, Object... args) {
+        return Arrays.asList(name, Arrays.asList(args));
+    }
+    static Object called(String name, Object... args) {
+        Object entry = logEntry(name, args);
+        calledLog.add(entry);
+        return entry;
+    }
+    static void assertCalled(String name, Object... args) {
+        Object expected = logEntry(name, args);
+        Object actual   = calledLog.get(calledLog.size() - 1);
+        if (expected.equals(actual))  return;
+        System.out.println("assertCalled "+name+":");
+        System.out.println("expected:   "+expected);
+        System.out.println("actual:     "+actual);
+        System.out.println("ex. types:  "+getClasses(expected));
+        System.out.println("act. types: "+getClasses(actual));
+        assertEquals("previous method call types", expected, actual);
+        assertEquals("previous method call", expected, actual);
+    }
+    static void printCalled(MethodHandle target, String name, Object... args) {
+        if (verbosity >= 2)
+            System.out.println("calling "+logEntry(name, args)+" on "+target);
+    }
+
+    static Object castToWrapper(Object value, Class<?> dst) {
+        Object wrap = null;
+        if (value instanceof Number)
+            wrap = castToWrapperOrNull(((Number)value).longValue(), dst);
+        if (value instanceof Character)
+            wrap = castToWrapperOrNull((char)(Character)value, dst);
+        if (wrap != null)  return wrap;
+        return dst.cast(value);
+    }
+
+    static Object castToWrapperOrNull(long value, Class<?> dst) {
+        if (dst == int.class || dst == Integer.class)
+            return (int)(value);
+        if (dst == long.class || dst == Long.class)
+            return (long)(value);
+        if (dst == char.class || dst == Character.class)
+            return (char)(value);
+        if (dst == short.class || dst == Short.class)
+            return (short)(value);
+        if (dst == float.class || dst == Float.class)
+            return (float)(value);
+        if (dst == double.class || dst == Double.class)
+            return (double)(value);
+        if (dst == byte.class || dst == Byte.class)
+            return (byte)(value);
+        if (dst == boolean.class || dst == boolean.class)
+            return ((value % 29) & 1) == 0;
+        return null;
+    }
+
+    static int nextArg;
+    static Object randomArg(Class<?> param) {
+        Object wrap = castToWrapperOrNull(nextArg, param);
+        if (wrap != null) {
+            nextArg++;
+            return wrap;
+        }
+//        import sun.dyn.util.Wrapper;
+//        Wrapper wrap = Wrapper.forBasicType(dst);
+//        if (wrap == Wrapper.OBJECT && Wrapper.isWrapperType(dst))
+//            wrap = Wrapper.forWrapperType(dst);
+//        if (wrap != Wrapper.OBJECT)
+//            return wrap.wrap(nextArg++);
+        if (param.isInterface() || param.isAssignableFrom(String.class))
+            return "#"+(nextArg++);
+        else
+            try {
+                return param.newInstance();
+            } catch (InstantiationException ex) {
+            } catch (IllegalAccessException ex) {
+            }
+        return null;  // random class not Object, String, Integer, etc.
+    }
+    static Object[] randomArgs(Class<?>... params) {
+        Object[] args = new Object[params.length];
+        for (int i = 0; i < args.length; i++)
+            args[i] = randomArg(params[i]);
+        return args;
+    }
+    static Object[] randomArgs(int nargs, Class<?> param) {
+        Object[] args = new Object[nargs];
+        for (int i = 0; i < args.length; i++)
+            args[i] = randomArg(param);
+        return args;
+    }
+
+    static <T, E extends T> T[] array(Class<T[]> atype, E... a) {
+        return Arrays.copyOf(a, a.length, atype);
+    }
+    static <T> T[] cat(T[] a, T... b) {
+        int alen = a.length, blen = b.length;
+        if (blen == 0)  return a;
+        T[] c = Arrays.copyOf(a, alen + blen);
+        System.arraycopy(b, 0, c, alen, blen);
+        return c;
+    }
+    static Integer[] boxAll(int... vx) {
+        Integer[] res = new Integer[vx.length];
+        for (int i = 0; i < res.length; i++) {
+            res[i] = vx[i];
+        }
+        return res;
+    }
+    static Object getClasses(Object x) {
+        if (x == null)  return x;
+        if (x instanceof String)  return x;  // keep the name
+        if (x instanceof List) {
+            // recursively report classes of the list elements
+            Object[] xa = ((List)x).toArray();
+            for (int i = 0; i < xa.length; i++)
+                xa[i] = getClasses(xa[i]);
+            return Arrays.asList(xa);
+        }
+        return x.getClass().getSimpleName();
+    }
+
+    static MethodHandle changeArgTypes(MethodHandle target, Class<?> argType) {
+        return changeArgTypes(target, 0, 999, argType);
+    }
+    static MethodHandle changeArgTypes(MethodHandle target,
+            int beg, int end, Class<?> argType) {
+        MethodType targetType = target.type();
+        end = Math.min(end, targetType.parameterCount());
+        ArrayList<Class<?>> argTypes = new ArrayList<Class<?>>(targetType.parameterList());
+        Collections.fill(argTypes.subList(beg, end), argType);
+        MethodType ttype2 = MethodType.methodType(targetType.returnType(), argTypes);
+        return MethodHandles.convertArguments(target, ttype2);
+    }
+
+    // This lookup is good for all members in and under MethodHandlesTest.
+    static final Lookup PRIVATE = MethodHandles.lookup();
+    // This lookup is good for package-private members but not private ones.
+    static final Lookup PACKAGE = PackageSibling.lookup();
+    // This lookup is good only for public members.
+    static final Lookup PUBLIC  = MethodHandles.publicLookup();
+
+    // Subject methods...
+    static class Example implements IntExample {
+        final String name;
+        public Example() { name = "Example#"+(nextArg++); }
+        protected Example(String name) { this.name = name; }
+        protected Example(int x) { this(); called("protected <init>", this, x); }
+        @Override public String toString() { return name; }
+
+        public void            v0()     { called("v0", this); }
+        void                   pkg_v0() { called("pkg_v0", this); }
+        private void           pri_v0() { called("pri_v0", this); }
+        public static void     s0()     { called("s0"); }
+        static void            pkg_s0() { called("pkg_s0"); }
+        private static void    pri_s0() { called("pri_s0"); }
+
+        public Object          v1(Object x) { return called("v1", this, x); }
+        public Object          v2(Object x, Object y) { return called("v2", this, x, y); }
+        public Object          v2(Object x, int    y) { return called("v2", this, x, y); }
+        public Object          v2(int    x, Object y) { return called("v2", this, x, y); }
+        public Object          v2(int    x, int    y) { return called("v2", this, x, y); }
+        public static Object   s1(Object x) { return called("s1", x); }
+        public static Object   s2(int x)    { return called("s2", x); }
+        public static Object   s3(long x)   { return called("s3", x); }
+        public static Object   s4(int x, int y) { return called("s4", x, y); }
+        public static Object   s5(long x, int y) { return called("s5", x, y); }
+        public static Object   s6(int x, long y) { return called("s6", x, y); }
+        public static Object   s7(float x, double y) { return called("s7", x, y); }
+    }
+    public static class PubExample extends Example {
+    }
+    static class SubExample extends Example {
+        @Override public void  v0()     { called("Sub/v0", this); }
+        @Override void         pkg_v0() { called("Sub/pkg_v0", this); }
+        private      SubExample(int x)  { called("<init>", this, x); }
+        public SubExample() { super("SubExample#"+(nextArg++)); }
+    }
+    public static interface IntExample {
+        public void            v0();
+        static class Impl implements IntExample {
+            public void        v0()     { called("Int/v0", this); }
+            final String name;
+            public Impl() { name = "Example#"+(nextArg++); }
+        }
+    }
+
+    static final Object[][][] ACCESS_CASES = {
+        { { false, PUBLIC }, { false, PACKAGE }, { false, PRIVATE } },
+        { { false, PUBLIC }, { false, PACKAGE }, { true,  PRIVATE } },
+        { { false, PUBLIC }, { true,  PACKAGE }, { true,  PRIVATE } },
+        { { true,  PUBLIC }, { true,  PACKAGE }, { true,  PRIVATE } },
+    };
+
+    static Object[][] accessCases(Class<?> defc, String name) {
+        if (name.contains("pri_")) {
+            return ACCESS_CASES[1]; // PRIVATE only
+        } else if (name.contains("pkg_")) {
+            return ACCESS_CASES[2]; // not PUBLIC
+        } else {
+            assertTrue(name.indexOf('_') < 0);
+            boolean pubc = Modifier.isPublic(defc.getModifiers());
+            if (pubc)
+                return ACCESS_CASES[3]; // all access levels
+            return ACCESS_CASES[2]; // PACKAGE but not PUBLIC
+        }
+    }
+
+    @Test
+    public void testFindStatic() throws Throwable {
+        if (CAN_SKIP_WORKING)  return;
+        startTest("findStatic");
+        testFindStatic(PubExample.class, void.class, "s0");
+        testFindStatic(Example.class, void.class, "s0");
+        testFindStatic(Example.class, void.class, "pkg_s0");
+        testFindStatic(Example.class, void.class, "pri_s0");
+
+        testFindStatic(Example.class, Object.class, "s1", Object.class);
+        testFindStatic(Example.class, Object.class, "s2", int.class);
+        testFindStatic(Example.class, Object.class, "s3", long.class);
+        testFindStatic(Example.class, Object.class, "s4", int.class, int.class);
+        testFindStatic(Example.class, Object.class, "s5", long.class, int.class);
+        testFindStatic(Example.class, Object.class, "s6", int.class, long.class);
+        testFindStatic(Example.class, Object.class, "s7", float.class, double.class);
+
+        testFindStatic(false, PRIVATE, Example.class, void.class, "bogus");
+    }
+
+    void testFindStatic(Class<?> defc, Class<?> ret, String name, Class<?>... params) throws Throwable {
+        for (Object[] ac : accessCases(defc, name)) {
+            testFindStatic((Boolean)ac[0], (Lookup)ac[1], defc, ret, name, params);
+        }
+    }
+    void testFindStatic(Lookup lookup, Class<?> defc, Class<?> ret, String name, Class<?>... params) throws Throwable {
+        testFindStatic(true, lookup, defc, ret, name, params);
+    }
+    void testFindStatic(boolean positive, Lookup lookup, Class<?> defc, Class<?> ret, String name, Class<?>... params) throws Throwable {
+        countTest(positive);
+        MethodType type = MethodType.methodType(ret, params);
+        MethodHandle target = null;
+        RuntimeException noAccess = null;
+        try {
+            target = lookup.findStatic(defc, name, type);
+        } catch (NoAccessException ex) {
+            noAccess = ex;
+        }
+        if (verbosity >= 2)
+            System.out.println("findStatic "+lookup+": "+defc+"."+name+"/"+type+" => "+target
+                    +(noAccess == null ? "" : " !! "+noAccess));
+        if (positive && noAccess != null)  throw noAccess;
+        assertEquals(positive ? "positive test" : "negative test erroneously passed", positive, target != null);
+        if (!positive)  return; // negative test failed as expected
+        assertEquals(type, target.type());
+        assertTrue(target.toString().contains(name));  // rough check
+        if (!DO_MORE_CALLS && lookup != PRIVATE)  return;
+        Object[] args = randomArgs(params);
+        printCalled(target, name, args);
+        target.invokeVarargs(args);
+        assertCalled(name, args);
+        System.out.print(':');
+    }
+
+    @Test
+    public void testFindVirtual() throws Throwable {
+        if (CAN_SKIP_WORKING)  return;
+        startTest("findVirtual");
+        testFindVirtual(Example.class, void.class, "v0");
+        testFindVirtual(Example.class, void.class, "pkg_v0");
+        testFindVirtual(Example.class, void.class, "pri_v0");
+        testFindVirtual(Example.class, Object.class, "v1", Object.class);
+        testFindVirtual(Example.class, Object.class, "v2", Object.class, Object.class);
+        testFindVirtual(Example.class, Object.class, "v2", Object.class, int.class);
+        testFindVirtual(Example.class, Object.class, "v2", int.class, Object.class);
+        testFindVirtual(Example.class, Object.class, "v2", int.class, int.class);
+        testFindVirtual(false, PRIVATE, Example.class, Example.class, void.class, "bogus");
+        // test dispatch
+        testFindVirtual(SubExample.class,      SubExample.class, void.class, "Sub/v0");
+        testFindVirtual(SubExample.class,         Example.class, void.class, "Sub/v0");
+        testFindVirtual(SubExample.class,      IntExample.class, void.class, "Sub/v0");
+        testFindVirtual(SubExample.class,      SubExample.class, void.class, "Sub/pkg_v0");
+        testFindVirtual(SubExample.class,         Example.class, void.class, "Sub/pkg_v0");
+        testFindVirtual(Example.class,         IntExample.class, void.class, "v0");
+        testFindVirtual(IntExample.Impl.class, IntExample.class, void.class, "Int/v0");
+    }
+
+    void testFindVirtual(Class<?> defc, Class<?> ret, String name, Class<?>... params) throws Throwable {
+        Class<?> rcvc = defc;
+        testFindVirtual(rcvc, defc, ret, name, params);
+    }
+    void testFindVirtual(Class<?> rcvc, Class<?> defc, Class<?> ret, String name, Class<?>... params) throws Throwable {
+        for (Object[] ac : accessCases(defc, name)) {
+            testFindVirtual((Boolean)ac[0], (Lookup)ac[1], rcvc, defc, ret, name, params);
+        }
+    }
+    void testFindVirtual(Lookup lookup, Class<?> rcvc, Class<?> defc, Class<?> ret, String name, Class<?>... params) throws Throwable {
+        testFindVirtual(true, lookup, rcvc, defc, ret, name, params);
+    }
+    void testFindVirtual(boolean positive, Lookup lookup, Class<?> rcvc, Class<?> defc, Class<?> ret, String name, Class<?>... params) throws Throwable {
+        countTest(positive);
+        String methodName = name.substring(1 + name.indexOf('/'));  // foo/bar => foo
+        MethodType type = MethodType.methodType(ret, params);
+        MethodHandle target = null;
+        RuntimeException noAccess = null;
+        try {
+            target = lookup.findVirtual(defc, methodName, type);
+        } catch (NoAccessException ex) {
+            noAccess = ex;
+        }
+        if (verbosity >= 2)
+            System.out.println("findVirtual "+lookup+": "+defc+"."+name+"/"+type+" => "+target
+                    +(noAccess == null ? "" : " !! "+noAccess));
+        if (positive && noAccess != null)  throw noAccess;
+        assertEquals(positive ? "positive test" : "negative test erroneously passed", positive, target != null);
+        if (!positive)  return; // negative test failed as expected
+        Class<?>[] paramsWithSelf = cat(array(Class[].class, (Class)defc), params);
+        MethodType typeWithSelf = MethodType.methodType(ret, paramsWithSelf);
+        MethodType ttype = target.type();
+        ttype = ttype.changeParameterType(0, defc); // FIXME: test this
+        assertEquals(typeWithSelf, ttype);
+        assertTrue(target.toString().contains(methodName));  // rough check
+        if (!DO_MORE_CALLS && lookup != PRIVATE)  return;
+        Object[] argsWithSelf = randomArgs(paramsWithSelf);
+        if (rcvc != defc)  argsWithSelf[0] = randomArg(rcvc);
+        printCalled(target, name, argsWithSelf);
+        target.invokeVarargs(argsWithSelf);
+        assertCalled(name, argsWithSelf);
+        System.out.print(':');
+    }
+
+    @Test
+    public void testFindSpecial() throws Throwable {
+        if (CAN_SKIP_WORKING)  return;
+        startTest("findSpecial");
+        testFindSpecial(Example.class, void.class, "v0");
+        testFindSpecial(Example.class, void.class, "pkg_v0");
+        testFindSpecial(false, PRIVATE, Example.class, void.class, "<init>", int.class);
+        testFindSpecial(false, PRIVATE, Example.class, void.class, "bogus");
+    }
+
+    void testFindSpecial(Class<?> defc, Class<?> ret, String name, Class<?>... params) throws Throwable {
+        testFindSpecial(true,  PRIVATE, defc, ret, name, params);
+        testFindSpecial(false, PACKAGE, defc, ret, name, params);
+        testFindSpecial(false, PUBLIC,  defc, ret, name, params);
+    }
+    void testFindSpecial(boolean positive, Lookup lookup, Class<?> defc, Class<?> ret, String name, Class<?>... params) throws Throwable {
+        countTest(positive);
+        MethodType type = MethodType.methodType(ret, params);
+        MethodHandle target = null;
+        RuntimeException noAccess = null;
+        try {
+            target = lookup.findSpecial(defc, name, type, defc);
+        } catch (NoAccessException ex) {
+            noAccess = ex;
+        }
+        if (verbosity >= 2)
+            System.out.println("findSpecial "+defc+"."+name+"/"+type+" => "+target
+                    +(noAccess == null ? "" : " !! "+noAccess));
+        if (positive && noAccess != null)  throw noAccess;
+        assertEquals(positive ? "positive test" : "negative test erroneously passed", positive, target != null);
+        if (!positive)  return; // negative test failed as expected
+        Class<?>[] paramsWithSelf = cat(array(Class[].class, (Class)defc), params);
+        MethodType typeWithSelf = MethodType.methodType(ret, paramsWithSelf);
+        MethodType ttype = target.type();
+        ttype = ttype.changeParameterType(0, defc); // FIXME: test this
+        assertEquals(typeWithSelf, ttype);
+        assertTrue(target.toString().contains(name));  // rough check
+        if (!DO_MORE_CALLS && lookup != PRIVATE)  return;
+        Object[] args = randomArgs(paramsWithSelf);
+        printCalled(target, name, args);
+        target.invokeVarargs(args);
+        assertCalled(name, args);
+        System.out.print(':');
+    }
+
+    @Test
+    public void testBind() throws Throwable {
+        if (CAN_SKIP_WORKING)  return;
+        startTest("bind");
+        testBind(Example.class, void.class, "v0");
+        testBind(Example.class, void.class, "pkg_v0");
+        testBind(Example.class, void.class, "pri_v0");
+        testBind(Example.class, Object.class, "v1", Object.class);
+        testBind(Example.class, Object.class, "v2", Object.class, Object.class);
+        testBind(Example.class, Object.class, "v2", Object.class, int.class);
+        testBind(Example.class, Object.class, "v2", int.class, Object.class);
+        testBind(Example.class, Object.class, "v2", int.class, int.class);
+        testBind(false, PRIVATE, Example.class, void.class, "bogus");
+        testBind(SubExample.class, void.class, "Sub/v0");
+        testBind(SubExample.class, void.class, "Sub/pkg_v0");
+        testBind(IntExample.Impl.class, void.class, "Int/v0");
+    }
+
+    void testBind(Class<?> defc, Class<?> ret, String name, Class<?>... params) throws Throwable {
+        for (Object[] ac : accessCases(defc, name)) {
+            testBind((Boolean)ac[0], (Lookup)ac[1], defc, ret, name, params);
+        }
+    }
+
+    void testBind(boolean positive, Lookup lookup, Class<?> defc, Class<?> ret, String name, Class<?>... params) throws Throwable {
+        countTest(positive);
+        String methodName = name.substring(1 + name.indexOf('/'));  // foo/bar => foo
+        MethodType type = MethodType.methodType(ret, params);
+        Object receiver = randomArg(defc);
+        MethodHandle target = null;
+        RuntimeException noAccess = null;
+        try {
+            target = lookup.bind(receiver, methodName, type);
+        } catch (NoAccessException ex) {
+            noAccess = ex;
+        }
+        if (verbosity >= 2)
+            System.out.println("bind "+receiver+"."+name+"/"+type+" => "+target
+                    +(noAccess == null ? "" : " !! "+noAccess));
+        if (positive && noAccess != null)  throw noAccess;
+        assertEquals(positive ? "positive test" : "negative test erroneously passed", positive, target != null);
+        if (!positive)  return; // negative test failed as expected
+        assertEquals(type, target.type());
+        Object[] args = randomArgs(params);
+        printCalled(target, name, args);
+        target.invokeVarargs(args);
+        Object[] argsWithReceiver = cat(array(Object[].class, receiver), args);
+        assertCalled(name, argsWithReceiver);
+        System.out.print(':');
+    }
+
+    @Test
+    public void testUnreflect() throws Throwable {
+        if (CAN_SKIP_WORKING)  return;
+        startTest("unreflect");
+        testUnreflect(Example.class, true, void.class, "s0");
+        testUnreflect(Example.class, true, void.class, "pkg_s0");
+        testUnreflect(Example.class, true, void.class, "pri_s0");
+
+        testUnreflect(Example.class, true, Object.class, "s1", Object.class);
+        testUnreflect(Example.class, true, Object.class, "s2", int.class);
+        //testUnreflect(Example.class, true, Object.class, "s3", long.class);
+        //testUnreflect(Example.class, true, Object.class, "s4", int.class, int.class);
+        //testUnreflect(Example.class, true, Object.class, "s5", long.class, int.class);
+        //testUnreflect(Example.class, true, Object.class, "s6", int.class, long.class);
+
+        testUnreflect(Example.class, false, void.class, "v0");
+        testUnreflect(Example.class, false, void.class, "pkg_v0");
+        testUnreflect(Example.class, false, void.class, "pri_v0");
+        testUnreflect(Example.class, false, Object.class, "v1", Object.class);
+        testUnreflect(Example.class, false, Object.class, "v2", Object.class, Object.class);
+        testUnreflect(Example.class, false, Object.class, "v2", Object.class, int.class);
+        testUnreflect(Example.class, false, Object.class, "v2", int.class, Object.class);
+        testUnreflect(Example.class, false, Object.class, "v2", int.class, int.class);
+    }
+
+    void testUnreflect(Class<?> defc, boolean isStatic, Class<?> ret, String name, Class<?>... params) throws Throwable {
+        for (Object[] ac : accessCases(defc, name)) {
+            testUnreflect((Boolean)ac[0], (Lookup)ac[1], defc, isStatic, ret, name, params);
+        }
+    }
+    void testUnreflect(boolean positive, Lookup lookup, Class<?> defc, boolean isStatic, Class<?> ret, String name, Class<?>... params) throws Throwable {
+        countTest(positive);
+        MethodType type = MethodType.methodType(ret, params);
+        Method rmethod = null;
+        MethodHandle target = null;
+        RuntimeException noAccess = null;
+        try {
+            rmethod = defc.getDeclaredMethod(name, params);
+        } catch (NoSuchMethodException ex) {
+            throw new NoAccessException(ex);
+        }
+        assertEquals(isStatic, Modifier.isStatic(rmethod.getModifiers()));
+        try {
+            target = lookup.unreflect(rmethod);
+        } catch (NoAccessException ex) {
+            noAccess = ex;
+        }
+        if (verbosity >= 2)
+            System.out.println("unreflect "+defc+"."+name+"/"+type+" => "+target
+                    +(noAccess == null ? "" : " !! "+noAccess));
+        if (positive && noAccess != null)  throw noAccess;
+        assertEquals(positive ? "positive test" : "negative test erroneously passed", positive, target != null);
+        if (!positive)  return; // negative test failed as expected
+        Class<?>[] paramsMaybeWithSelf = params;
+        if (!isStatic) {
+            paramsMaybeWithSelf = cat(array(Class[].class, (Class)defc), params);
+        }
+        MethodType typeMaybeWithSelf = MethodType.methodType(ret, paramsMaybeWithSelf);
+        MethodType ttype = target.type();
+        if (!isStatic)
+            ttype = ttype.changeParameterType(0, defc); // FIXME: test this
+        assertEquals(typeMaybeWithSelf, ttype);
+        Object[] argsMaybeWithSelf = randomArgs(paramsMaybeWithSelf);
+        printCalled(target, name, argsMaybeWithSelf);
+        target.invokeVarargs(argsMaybeWithSelf);
+        assertCalled(name, argsMaybeWithSelf);
+        System.out.print(':');
+    }
+
+    @Test @Ignore("unimplemented")
+    public void testUnreflectSpecial() throws Throwable {
+        Lookup lookup = PRIVATE;  // FIXME: test more lookups than this one
+        startTest("unreflectSpecial");
+        Method m = null;
+        MethodHandle expResult = null;
+        MethodHandle result = lookup.unreflectSpecial(m, Example.class);
+        assertEquals(expResult, result);
+        fail("The test case is a prototype.");
+    }
+
+    public static class HasFields {
+        boolean fZ = false;
+        byte fB = (byte)'B';
+        short fS = (short)'S';
+        char fC = 'C';
+        int fI = 'I';
+        long fJ = 'J';
+        float fF = 'F';
+        double fD = 'D';
+        static boolean sZ = true;
+        static byte sB = 1+(byte)'B';
+        static short sS = 1+(short)'S';
+        static char sC = 1+'C';
+        static int sI = 1+'I';
+        static long sJ = 1+'J';
+        static float sF = 1+'F';
+        static double sD = 1+'D';
+
+        Object fL = 'L';
+        String fR = "R";
+        static Object sL = 'M';
+        static String sR = "S";
+
+        static final Object[][] CASES;
+        static {
+            ArrayList<Object[]> cases = new ArrayList<Object[]>();
+            Object types[][] = {
+                {'L',Object.class}, {'R',String.class},
+                {'I',int.class}, {'J',long.class},
+                {'F',float.class}, {'D',double.class},
+                {'Z',boolean.class}, {'B',byte.class},
+                {'S',short.class}, {'C',char.class},
+            };
+            HasFields fields = new HasFields();
+            for (Object[] t : types) {
+                for (int kind = 0; kind <= 1; kind++) {
+                    boolean isStatic = (kind != 0);
+                    char btc = (Character)t[0];
+                    String name = (isStatic ? "s" : "f") + btc;
+                    Class<?> type = (Class<?>) t[1];
+                    Object value;
+                    Field field;
+                    try {
+                        field = HasFields.class.getDeclaredField(name);
+                    } catch (Exception ex) {
+                        throw new InternalError("no field HasFields."+name);
+                    }
+                    try {
+                        value = field.get(fields);
+                    } catch (Exception ex) {
+                        throw new InternalError("cannot fetch field HasFields."+name);
+                    }
+                    if (type == float.class) {
+                        float v = 'F';
+                        if (isStatic)  v++;
+                        assert(value.equals(v));
+                    }
+                    assert(name.equals(field.getName()));
+                    assert(type.equals(field.getType()));
+                    assert(isStatic == (Modifier.isStatic(field.getModifiers())));
+                    cases.add(new Object[]{ field, value });
+                }
+            }
+            CASES = cases.toArray(new Object[0][]);
+        }
+    }
+
+    @Test
+    public void testUnreflectGetter() throws Throwable {
+        Lookup lookup = PRIVATE;  // FIXME: test more lookups than this one
+        startTest("unreflectGetter");
+        for (Object[] c : HasFields.CASES) {
+            Field f = (Field)c[0];
+            Object value = c[1];
+            Class<?> type = f.getType();
+            if (type.isPrimitive() && type != int.class)
+                continue;  //FIXME
+            testUnreflectGetter(lookup, f, type, value);
+        }
+    }
+    public void testUnreflectGetter(MethodHandles.Lookup lookup,
+            Field f, Class<?> type, Object value) throws Throwable {
+        countTest(true);
+        boolean isStatic = Modifier.isStatic(f.getModifiers());
+        MethodType expType = MethodType.methodType(type, HasFields.class);
+        if (isStatic)  expType = expType.dropParameterTypes(0, 1);
+        MethodHandle mh = lookup.unreflectGetter(f);
+        assertSame(mh.type(), expType);
+        assertEquals(mh.toString(), f.getName());
+        HasFields fields = new HasFields();
+        Object sawValue;
+        Class<?> rtype = type;
+        if (type != int.class)  rtype = Object.class;
+        mh = MethodHandles.convertArguments(mh, mh.type().generic().changeReturnType(rtype));
+        Object expValue = value;
+        for (int i = 0; i <= 1; i++) {
+            if (isStatic) {
+                if (type == int.class)
+                    sawValue = mh.<int>invoke();  // do these exactly
+                else
+                    sawValue = mh.invoke();
+            } else {
+                if (type == int.class)
+                    sawValue = mh.<int>invoke((Object) fields);
+                else
+                    sawValue = mh.invoke((Object) fields);
+            }
+            assertEquals(sawValue, expValue);
+            Object random = randomArg(type);
+            f.set(fields, random);
+            expValue = random;
+        }
+        f.set(fields, value);  // put it back
+    }
+
+
+    @Test
+    public void testUnreflectSetter() throws Throwable {
+        Lookup lookup = PRIVATE;  // FIXME: test more lookups than this one
+        startTest("unreflectSetter");
+        for (Object[] c : HasFields.CASES) {
+            Field f = (Field)c[0];
+            Object value = c[1];
+            Class<?> type = f.getType();
+            if (type.isPrimitive() && type != int.class)
+                continue;  //FIXME
+            testUnreflectSetter(lookup, f, type, value);
+        }
+    }
+    public void testUnreflectSetter(MethodHandles.Lookup lookup,
+            Field f, Class<?> type, Object value) throws Throwable {
+        countTest(true);
+        boolean isStatic = Modifier.isStatic(f.getModifiers());
+        MethodType expType = MethodType.methodType(void.class, HasFields.class, type);
+        if (isStatic)  expType = expType.dropParameterTypes(0, 1);
+        MethodHandle mh = lookup.unreflectSetter(f);
+        assertSame(mh.type(), expType);
+        assertEquals(mh.toString(), f.getName());
+        HasFields fields = new HasFields();
+        Object sawValue;
+        Class<?> vtype = type;
+        if (type != int.class)  vtype = Object.class;
+        int last = mh.type().parameterCount() - 1;
+        mh = MethodHandles.convertArguments(mh, mh.type().generic().changeReturnType(void.class).changeParameterType(last, vtype));
+        assertEquals(f.get(fields), value);  // clean to start with
+        for (int i = 0; i <= 1; i++) {
+            Object putValue = randomArg(type);
+            if (isStatic) {
+                if (type == int.class)
+                    mh.<void>invoke((int)(Integer)putValue);  // do these exactly
+                else
+                    mh.<void>invoke(putValue);
+            } else {
+                if (type == int.class)
+                    mh.<void>invoke((Object) fields, (int)(Integer)putValue);
+                else
+                    mh.<void>invoke((Object) fields, putValue);
+            }
+            assertEquals(f.get(fields), putValue);
+        }
+        f.set(fields, value);  // put it back
+    }
+
+    @Test
+    public void testArrayElementGetter() throws Throwable {
+        startTest("arrayElementGetter");
+        testArrayElementGetterSetter(new Object[10], false);
+        testArrayElementGetterSetter(new String[10], false);
+        testArrayElementGetterSetter(new int[10], false);
+        // FIXME: Do the other primitive types.
+        //testArrayElementGetterSetter(new float[10], false);
+    }
+
+    @Test
+    public void testArrayElementSetter() throws Throwable {
+        startTest("arrayElementSetter");
+        testArrayElementGetterSetter(new Object[10], true);
+        testArrayElementGetterSetter(new String[10], true);
+        testArrayElementGetterSetter(new int[10], true);
+        // FIXME: Do the other primitive types.
+        //testArrayElementGetterSetter(new float[10], true);
+    }
+
+    public void testArrayElementGetterSetter(Object array, boolean testSetter) throws Throwable {
+        countTest(true);
+        Class<?> arrayType = array.getClass();
+        Class<?> elemType = arrayType.getComponentType();
+        MethodType expType = !testSetter
+                ? MethodType.methodType(elemType,   arrayType, int.class)
+                : MethodType.methodType(void.class, arrayType, int.class, elemType);
+        MethodHandle mh = !testSetter
+                ? MethodHandles.arrayElementGetter(arrayType)
+                : MethodHandles.arrayElementSetter(arrayType);
+        assertSame(mh.type(), expType);
+        //assertEquals(mh.toString(), f.getName());
+        Object sawValue, expValue;
+        List<Object> model = array2list(array);
+        int length = Array.getLength(array);
+        for (int i = 0; i < length; i++) {
+            // update array element
+            Object random = randomArg(elemType);
+            model.set(i, random);
+            if (testSetter) {
+                if (elemType == int.class)
+                    mh.<void>invoke((int[]) array, i, (int)(Integer)random);
+                else
+                    mh.invokeGeneric(array, i, random);
+                assertEquals(model, array2list(array));
+            } else {
+                Array.set(array, i, random);
+
+            }
+            // observe array element
+            sawValue = Array.get(array, i);
+            if (!testSetter) {
+                expValue = sawValue;
+                if (elemType == int.class)
+                    sawValue = mh.<int>invoke((int[]) array, i);
+                else
+                    sawValue = mh.invokeGeneric(array, i);
+                assertEquals(sawValue, expValue);
+                assertEquals(model, array2list(array));
+            }
+        }
+    }
+
+    List<Object> array2list(Object array) {
+        int length = Array.getLength(array);
+        ArrayList<Object> model = new ArrayList<Object>(length);
+        for (int i = 0; i < length; i++)
+            model.add(Array.get(array, i));
+        return model;
+    }
+
+    static class Callee {
+        static Object id() { return called("id"); }
+        static Object id(Object x) { return called("id", x); }
+        static Object id(Object x, Object y) { return called("id", x, y); }
+        static Object id(Object x, Object y, Object z) { return called("id", x, y, z); }
+        static Object id(Object... vx) { return called("id", vx); }
+        static MethodHandle ofType(int n) {
+            return ofType(Object.class, n);
+        }
+        static MethodHandle ofType(Class<?> rtype, int n) {
+            if (n == -1)
+                return ofType(MethodType.methodType(rtype, Object[].class));
+            return ofType(MethodType.genericMethodType(n).changeReturnType(rtype));
+        }
+        static MethodHandle ofType(Class<?> rtype, Class<?>... ptypes) {
+            return ofType(MethodType.methodType(rtype, ptypes));
+        }
+        static MethodHandle ofType(MethodType type) {
+            Class<?> rtype = type.returnType();
+            String pfx = "";
+            if (rtype != Object.class)
+                pfx = rtype.getSimpleName().substring(0, 1).toLowerCase();
+            String name = pfx+"id";
+            return PRIVATE.findStatic(Callee.class, name, type);
+        }
+    }
+
+    @Test
+    public void testConvertArguments() throws Throwable {
+        if (CAN_SKIP_WORKING)  return;
+        startTest("convertArguments");
+        testConvert(Callee.ofType(1), null, "id", int.class);
+        testConvert(Callee.ofType(1), null, "id", String.class);
+        testConvert(Callee.ofType(1), null, "id", Integer.class);
+        testConvert(Callee.ofType(1), null, "id", short.class);
+    }
+
+    void testConvert(MethodHandle id, Class<?> rtype, String name, Class<?>... params) throws Throwable {
+        testConvert(true, id, rtype, name, params);
+    }
+
+    void testConvert(boolean positive, MethodHandle id, Class<?> rtype, String name, Class<?>... params) throws Throwable {
+        countTest(positive);
+        MethodType idType = id.type();
+        if (rtype == null)  rtype = idType.returnType();
+        for (int i = 0; i < params.length; i++) {
+            if (params[i] == null)  params[i] = idType.parameterType(i);
+        }
+        // simulate the pairwise conversion
+        MethodType newType = MethodType.methodType(rtype, params);
+        Object[] args = randomArgs(newType.parameterArray());
+        Object[] convArgs = args.clone();
+        for (int i = 0; i < args.length; i++) {
+            Class<?> src = newType.parameterType(i);
+            Class<?> dst = idType.parameterType(i);
+            if (src != dst)
+                convArgs[i] = castToWrapper(convArgs[i], dst);
+        }
+        Object convResult = id.invokeVarargs(convArgs);
+        {
+            Class<?> dst = newType.returnType();
+            Class<?> src = idType.returnType();
+            if (src != dst)
+                convResult = castToWrapper(convResult, dst);
+        }
+        MethodHandle target = null;
+        RuntimeException error = null;
+        try {
+            target = MethodHandles.convertArguments(id, newType);
+        } catch (RuntimeException ex) {
+            error = ex;
+        }
+        if (verbosity >= 2)
+            System.out.println("convert "+id+ " to "+newType+" => "+target
+                    +(error == null ? "" : " !! "+error));
+        if (positive && error != null)  throw error;
+        assertEquals(positive ? "positive test" : "negative test erroneously passed", positive, target != null);
+        if (!positive)  return; // negative test failed as expected
+        assertEquals(newType, target.type());
+        printCalled(target, id.toString(), args);
+        Object result = target.invokeVarargs(args);
+        assertCalled(name, convArgs);
+        assertEquals(convResult, result);
+        System.out.print(':');
+    }
+
+    @Test
+    public void testPermuteArguments() throws Throwable {
+        if (CAN_SKIP_WORKING)  return;
+        startTest("permuteArguments");
+        testPermuteArguments(4, Integer.class,  2, String.class,  0);
+        //testPermuteArguments(6, Integer.class,  0, null,         30);
+        //testPermuteArguments(4, Integer.class,  1, int.class,     6);
+    }
+    public void testPermuteArguments(int max, Class<?> type1, int t2c, Class<?> type2, int dilution) throws Throwable {
+        if (verbosity >= 1)
+            System.out.println("permuteArguments "+max+"*"+type1.getName()
+                    +(t2c==0?"":"/"+t2c+"*"+type2.getName())
+                    +(dilution > 0 ? " with dilution "+dilution : ""));
+        int t2pos = t2c == 0 ? 0 : 1;
+        for (int inargs = t2pos+1; inargs <= max; inargs++) {
+            Class<?>[] types = new Class<?>[inargs];
+            Arrays.fill(types, type1);
+            if (t2c != 0) {
+                // Fill in a middle range with type2:
+                Arrays.fill(types, t2pos, Math.min(t2pos+t2c, inargs), type2);
+            }
+            Object[] args = randomArgs(types);
+            int numcases = 1;
+            for (int outargs = 0; outargs <= max; outargs++) {
+                if (outargs - inargs >= MAX_ARG_INCREASE)  continue;
+                int[] reorder = new int[outargs];
+                int casStep = dilution + 1;
+                // Avoid some common factors:
+                while ((casStep > 2 && casStep % 2 == 0 && inargs % 2 == 0) ||
+                       (casStep > 3 && casStep % 3 == 0 && inargs % 3 == 0))
+                    casStep++;
+                for (int cas = 0; cas < numcases; cas += casStep) {
+                    for (int i = 0, c = cas; i < outargs; i++) {
+                        reorder[i] = c % inargs;
+                        c /= inargs;
+                    }
+                    testPermuteArguments(args, types, reorder);
+                }
+                numcases *= inargs;
+                if (dilution > 10 && outargs >= 4) {
+                    // Do some special patterns, which we probably missed.
+                    // Replication of a single argument or argument pair.
+                    for (int i = 0; i < inargs; i++) {
+                        Arrays.fill(reorder, i);
+                        testPermuteArguments(args, types, reorder);
+                        for (int d = 1; d <= 2; d++) {
+                            if (i + d >= inargs)  continue;
+                            for (int j = 1; j < outargs; j += 2)
+                                reorder[j] += 1;
+                            testPermuteArguments(args, types, reorder);
+                            testPermuteArguments(args, types, reverse(reorder));
+                        }
+                    }
+                    // Repetition of a sequence of 3 or more arguments.
+                    for (int i = 1; i < inargs; i++) {
+                        for (int len = 3; len <= inargs; len++) {
+                            for (int j = 0; j < outargs; j++)
+                                reorder[j] = (i + (j % len)) % inargs;
+                            testPermuteArguments(args, types, reorder);
+                            testPermuteArguments(args, types, reverse(reorder));
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    static int[] reverse(int[] reorder) {
+        reorder = reorder.clone();
+        for (int i = 0, imax = reorder.length / 2; i < imax; i++) {
+            int j = reorder.length - 1 - i;
+            int tem = reorder[i];
+            reorder[i] = reorder[j];
+            reorder[j] = tem;
+        }
+        return reorder;
+    }
+
+    void testPermuteArguments(Object[] args, Class<?>[] types, int[] reorder) throws Throwable {
+        countTest();
+        if (args == null && types == null) {
+            int max = 0;
+            for (int j : reorder) {
+                if (max < j)  max = j;
+            }
+            args = randomArgs(max+1, Integer.class);
+        }
+        if (args == null) {
+            args = randomArgs(types);
+        }
+        if (types == null) {
+            types = new Class<?>[args.length];
+            for (int i = 0; i < args.length; i++)
+                types[i] = args[i].getClass();
+        }
+        int inargs = args.length, outargs = reorder.length;
+        assert(inargs == types.length);
+        if (verbosity >= 2)
+            System.out.println("permuteArguments "+Arrays.toString(reorder));
+        Object[] permArgs = new Object[outargs];
+        Class<?>[] permTypes = new Class<?>[outargs];
+        for (int i = 0; i < outargs; i++) {
+            permArgs[i] = args[reorder[i]];
+            permTypes[i] = types[reorder[i]];
+        }
+        if (verbosity >= 3) {
+            System.out.println("in args:   "+Arrays.asList(args));
+            System.out.println("out args:  "+Arrays.asList(permArgs));
+            System.out.println("in types:  "+Arrays.asList(types));
+            System.out.println("out types: "+Arrays.asList(permTypes));
+        }
+        MethodType inType  = MethodType.methodType(Object.class, types);
+        MethodType outType = MethodType.methodType(Object.class, permTypes);
+        MethodHandle target = MethodHandles.convertArguments(ValueConversions.varargsList(outargs), outType);
+        MethodHandle newTarget = MethodHandles.permuteArguments(target, inType, reorder);
+        Object result = newTarget.invokeVarargs(args);
+        Object expected = Arrays.asList(permArgs);
+        assertEquals(expected, result);
+    }
+
+
+    @Test
+    public void testSpreadArguments() throws Throwable {
+        if (CAN_SKIP_WORKING)  return;
+        startTest("spreadArguments");
+        for (Class<?> argType : new Class[]{Object.class, Integer.class, int.class}) {
+            if (verbosity >= 2)
+                System.out.println("spreadArguments "+argType);
+            for (int nargs = 0; nargs < 10; nargs++) {
+                if (argType == int.class && nargs >= 6)  continue; // FIXME Fail_1
+                for (int pos = 0; pos < nargs; pos++) {
+                    if (argType == int.class && pos > 0)  continue; // FIXME Fail_3
+                    testSpreadArguments(argType, pos, nargs);
+                }
+            }
+        }
+    }
+    public void testSpreadArguments(Class<?> argType, int pos, int nargs) throws Throwable {
+        countTest();
+        MethodHandle target = ValueConversions.varargsArray(nargs);
+        MethodHandle target2 = changeArgTypes(target, argType);
+        if (verbosity >= 2)
+            System.out.println("spread into "+target2+" ["+pos+".."+nargs+"]");
+        Object[] args = randomArgs(target2.type().parameterArray());
+        // make sure the target does what we think it does:
+        if (pos == 0 && nargs < 5) {
+            Object[] check = (Object[]) target.invokeVarargs(args);
+            assertArrayEquals(args, check);
+            switch (nargs) {
+                case 0:
+                    check = target.<Object[]>invoke();
+                    assertArrayEquals(args, check);
+                    break;
+                case 1:
+                    check = target.<Object[]>invoke(args[0]);
+                    assertArrayEquals(args, check);
+                    break;
+                case 2:
+                    check = target.<Object[]>invoke(args[0], args[1]);
+                    assertArrayEquals(args, check);
+                    break;
+            }
+        }
+        List<Class<?>> newParams = new ArrayList<Class<?>>(target2.type().parameterList());
+        {   // modify newParams in place
+            List<Class<?>> spreadParams = newParams.subList(pos, nargs);
+            spreadParams.clear(); spreadParams.add(Object[].class);
+        }
+        MethodType newType = MethodType.methodType(Object.class, newParams);
+        MethodHandle result = MethodHandles.spreadArguments(target2, newType);
+        Object[] returnValue;
+        if (pos == 0) {
+            returnValue = (Object[]) result.invoke(args);
+        } else {
+            Object[] args1 = Arrays.copyOfRange(args, 0, pos+1);
+            args1[pos] = Arrays.copyOfRange(args, pos, args.length);
+            returnValue = (Object[]) result.invokeVarargs(args1);
+        }
+        assertArrayEquals(args, returnValue);
+    }
+
+    @Test
+    public void testCollectArguments() throws Throwable {
+        if (CAN_SKIP_WORKING)  return;
+        startTest("collectArguments");
+        for (Class<?> argType : new Class[]{Object.class, Integer.class, int.class}) {
+            if (verbosity >= 2)
+                System.out.println("collectArguments "+argType);
+            for (int nargs = 0; nargs < 10; nargs++) {
+                for (int pos = 0; pos < nargs; pos++) {
+                    if (argType == int.class)  continue; // FIXME Fail_4
+                    testCollectArguments(argType, pos, nargs);
+                }
+            }
+        }
+    }
+    public void testCollectArguments(Class<?> argType, int pos, int nargs) throws Throwable {
+        countTest();
+        // fake up a MH with the same type as the desired adapter:
+        MethodHandle fake = ValueConversions.varargsArray(nargs);
+        fake = changeArgTypes(fake, argType);
+        MethodType newType = fake.type();
+        Object[] args = randomArgs(newType.parameterArray());
+        // here is what should happen:
+        Object[] collectedArgs = Arrays.copyOfRange(args, 0, pos+1);
+        collectedArgs[pos] = Arrays.copyOfRange(args, pos, args.length);
+        // here is the MH which will witness the collected argument tail:
+        MethodHandle target = ValueConversions.varargsArray(pos+1);
+        target = changeArgTypes(target, 0, pos, argType);
+        target = changeArgTypes(target, pos, pos+1, Object[].class);
+        if (verbosity >= 2)
+            System.out.println("collect from "+Arrays.asList(args)+" ["+pos+".."+nargs+"]");
+        MethodHandle result = MethodHandles.collectArguments(target, newType);
+        Object[] returnValue = (Object[]) result.invokeVarargs(args);
+//        assertTrue(returnValue.length == pos+1 && returnValue[pos] instanceof Object[]);
+//        returnValue[pos] = Arrays.asList((Object[]) returnValue[pos]);
+//        collectedArgs[pos] = Arrays.asList((Object[]) collectedArgs[pos]);
+        assertArrayEquals(collectedArgs, returnValue);
+    }
+
+    @Test
+    public void testInsertArguments() throws Throwable {
+        if (CAN_SKIP_WORKING)  return;
+        startTest("insertArguments");
+        for (int nargs = 0; nargs <= 4; nargs++) {
+            for (int ins = 0; ins <= 4; ins++) {
+                if (ins > MAX_ARG_INCREASE)  continue;  // FIXME Fail_6
+                for (int pos = 0; pos <= nargs; pos++) {
+                    testInsertArguments(nargs, pos, ins);
+                }
+            }
+        }
+    }
+
+    void testInsertArguments(int nargs, int pos, int ins) throws Throwable {
+        countTest();
+        MethodHandle target = ValueConversions.varargsArray(nargs + ins);
+        Object[] args = randomArgs(target.type().parameterArray());
+        List<Object> resList = Arrays.asList(args);
+        List<Object> argsToPass = new ArrayList<Object>(resList);
+        List<Object> argsToInsert = argsToPass.subList(pos, pos + ins);
+        if (verbosity >= 2)
+            System.out.println("insert: "+argsToInsert+" into "+target);
+        MethodHandle target2 = MethodHandles.insertArguments(target, pos,
+                (Object[]) argsToInsert.toArray());
+        argsToInsert.clear();  // remove from argsToInsert
+        Object res2 = target2.invokeVarargs(argsToPass);
+        Object res2List = Arrays.asList((Object[])res2);
+        if (verbosity >= 2)
+            System.out.println("result: "+res2List);
+        //if (!resList.equals(res2List))
+        //    System.out.println("*** fail at n/p/i = "+nargs+"/"+pos+"/"+ins+": "+resList+" => "+res2List);
+        assertEquals(resList, res2List);
+    }
+
+    @Test
+    public void testFilterArguments() throws Throwable {
+        if (CAN_SKIP_WORKING)  return;
+        startTest("filterArguments");
+        for (int nargs = 1; nargs <= 6; nargs++) {
+            for (int pos = 0; pos < nargs; pos++) {
+                testFilterArguments(nargs, pos);
+            }
+        }
+    }
+
+    void testFilterArguments(int nargs, int pos) throws Throwable {
+        countTest();
+        MethodHandle target = ValueConversions.varargsList(nargs);
+        MethodHandle filter = ValueConversions.varargsList(1);
+        filter = MethodHandles.convertArguments(filter, filter.type().generic());
+        Object[] argsToPass = randomArgs(nargs, Object.class);
+        if (verbosity >= 2)
+            System.out.println("filter "+target+" at "+pos+" with "+filter);
+        MethodHandle[] filters = new MethodHandle[pos*2+1];
+        filters[pos] = filter;
+        MethodHandle target2 = MethodHandles.filterArguments(target, filters);
+        // Simulate expected effect of filter on arglist:
+        Object[] filteredArgs = argsToPass.clone();
+        filteredArgs[pos] = filter.invoke(filteredArgs[pos]);
+        List<Object> expected = Arrays.asList(filteredArgs);
+        Object result = target2.invokeVarargs(argsToPass);
+        if (verbosity >= 2)
+            System.out.println("result: "+result);
+        if (!expected.equals(result))
+            System.out.println("*** fail at n/p = "+nargs+"/"+pos+": "+argsToPass+" => "+result);
+        assertEquals(expected, result);
+    }
+
+    @Test
+    public void testFoldArguments() throws Throwable {
+        if (CAN_SKIP_WORKING)  return;
+        startTest("foldArguments");
+        for (int nargs = 0; nargs <= 4; nargs++) {
+            for (int fold = 0; fold <= nargs; fold++) {
+                for (int pos = 0; pos <= nargs; pos++) {
+                    testFoldArguments(nargs, pos, fold);
+                }
+            }
+        }
+    }
+
+    void testFoldArguments(int nargs, int pos, int fold) throws Throwable {
+        if (pos != 0)  return;  // can fold only at pos=0 for now
+        countTest();
+        MethodHandle target = ValueConversions.varargsList(1 + nargs);
+        MethodHandle combine = ValueConversions.varargsList(fold);
+        List<Object> argsToPass = Arrays.asList(randomArgs(nargs, Object.class));
+        if (verbosity >= 2)
+            System.out.println("fold "+target+" with "+combine);
+        MethodHandle target2 = MethodHandles.foldArguments(target, combine);
+        // Simulate expected effect of combiner on arglist:
+        List<Object> expected = new ArrayList<Object>(argsToPass);
+        List<Object> argsToFold = expected.subList(pos, pos + fold);
+        if (verbosity >= 2)
+            System.out.println("fold: "+argsToFold+" into "+target2);
+        Object foldedArgs = combine.invokeVarargs(argsToFold);
+        argsToFold.add(0, foldedArgs);
+        Object result = target2.invokeVarargs(argsToPass);
+        if (verbosity >= 2)
+            System.out.println("result: "+result);
+        if (!expected.equals(result))
+            System.out.println("*** fail at n/p/f = "+nargs+"/"+pos+"/"+fold+": "+argsToPass+" => "+result);
+        assertEquals(expected, result);
+    }
+
+    @Test
+    public void testDropArguments() throws Throwable {
+        if (CAN_SKIP_WORKING)  return;
+        startTest("dropArguments");
+        for (int nargs = 0; nargs <= 4; nargs++) {
+            for (int drop = 1; drop <= 4; drop++) {
+                for (int pos = 0; pos <= nargs; pos++) {
+                    testDropArguments(nargs, pos, drop);
+                }
+            }
+        }
+    }
+
+    void testDropArguments(int nargs, int pos, int drop) throws Throwable {
+        countTest();
+        MethodHandle target = ValueConversions.varargsArray(nargs);
+        Object[] args = randomArgs(target.type().parameterArray());
+        MethodHandle target2 = MethodHandles.dropArguments(target, pos,
+                Collections.nCopies(drop, Object.class).toArray(new Class[0]));
+        List<Object> resList = Arrays.asList(args);
+        List<Object> argsToDrop = new ArrayList<Object>(resList);
+        for (int i = drop; i > 0; i--) {
+            argsToDrop.add(pos, "blort#"+i);
+        }
+        Object res2 = target2.invokeVarargs(argsToDrop);
+        Object res2List = Arrays.asList((Object[])res2);
+        //if (!resList.equals(res2List))
+        //    System.out.println("*** fail at n/p/d = "+nargs+"/"+pos+"/"+drop+": "+argsToDrop+" => "+res2List);
+        assertEquals(resList, res2List);
+    }
+
+    @Test
+    public void testInvokers() throws Throwable {
+        if (CAN_SKIP_WORKING)  return;
+        startTest("exactInvoker, genericInvoker, varargsInvoker, dynamicInvoker");
+        // exactInvoker, genericInvoker, varargsInvoker[0..N], dynamicInvoker
+        Set<MethodType> done = new HashSet<MethodType>();
+        for (int i = 0; i <= 6; i++) {
+            MethodType gtype = MethodType.genericMethodType(i);
+            for (Class<?> argType : new Class[]{Object.class, Integer.class, int.class}) {
+                for (int j = -1; j < i; j++) {
+                    MethodType type = gtype;
+                    if (j < 0)
+                        type = type.changeReturnType(argType);
+                    else if (argType == void.class)
+                        continue;
+                    else
+                        type = type.changeParameterType(j, argType);
+                    if (argType.isPrimitive() && j != i-1)  continue; // FIXME Fail_5
+                    if (done.add(type))
+                        testInvokers(type);
+                    MethodType vtype = type.changeReturnType(void.class);
+                    if (done.add(vtype))
+                        testInvokers(vtype);
+                }
+            }
+        }
+    }
+
+    public void testInvokers(MethodType type) throws Throwable {
+        if (verbosity >= 2)
+            System.out.println("test invokers for "+type);
+        int nargs = type.parameterCount();
+        boolean testRetCode = type.returnType() != void.class;
+        MethodHandle target = PRIVATE.findStatic(MethodHandlesTest.class, "invokee",
+                                MethodType.genericMethodType(0, true));
+        target = MethodHandles.collectArguments(target, type);
+        Object[] args = randomArgs(type.parameterArray());
+        List<Object> targetPlusArgs = new ArrayList<Object>(Arrays.asList(args));
+        targetPlusArgs.add(0, target);
+        int code = (Integer) invokee(args);
+        Object log = logEntry("invokee", args);
+        assertEquals(log.hashCode(), code);
+        assertCalled("invokee", args);
+        MethodHandle inv;
+        Object result;
+        // exact invoker
+        countTest();
+        calledLog.clear();
+        inv = MethodHandles.exactInvoker(type);
+        result = inv.invokeVarargs(targetPlusArgs);
+        if (testRetCode)  assertEquals(code, result);
+        assertCalled("invokee", args);
+        // generic invoker
+        countTest();
+        inv = MethodHandles.genericInvoker(type);
+        if (nargs <= 3) {
+            calledLog.clear();
+            switch (nargs) {
+            case 0:
+                result = inv.invoke(target);
+                break;
+            case 1:
+                result = inv.invoke(target, args[0]);
+                break;
+            case 2:
+                result = inv.invoke(target, args[0], args[1]);
+                break;
+            case 3:
+                result = inv.invoke(target, args[0], args[1], args[2]);
+                break;
+            }
+            if (testRetCode)  assertEquals(code, result);
+            assertCalled("invokee", args);
+        }
+        calledLog.clear();
+        result = inv.invokeVarargs(targetPlusArgs);
+        if (testRetCode)  assertEquals(code, result);
+        assertCalled("invokee", args);
+        // varargs invoker #0
+        calledLog.clear();
+        inv = MethodHandles.varargsInvoker(type, 0);
+        result = inv.invoke(target, args);
+        if (testRetCode)  assertEquals(code, result);
+        assertCalled("invokee", args);
+        if (nargs >= 1) {
+            // varargs invoker #1
+            calledLog.clear();
+            inv = MethodHandles.varargsInvoker(type, 1);
+            result = inv.invoke(target, args[0], Arrays.copyOfRange(args, 1, nargs));
+            if (testRetCode)  assertEquals(code, result);
+            assertCalled("invokee", args);
+        }
+        if (nargs >= 2) {
+            // varargs invoker #2
+            calledLog.clear();
+            inv = MethodHandles.varargsInvoker(type, 2);
+            result = inv.invoke(target, args[0], args[1], Arrays.copyOfRange(args, 2, nargs));
+            if (testRetCode)  assertEquals(code, result);
+            assertCalled("invokee", args);
+        }
+        if (nargs >= 3) {
+            // varargs invoker #3
+            calledLog.clear();
+            inv = MethodHandles.varargsInvoker(type, 3);
+            result = inv.invoke(target, args[0], args[1], args[2], Arrays.copyOfRange(args, 3, nargs));
+            if (testRetCode)  assertEquals(code, result);
+            assertCalled("invokee", args);
+        }
+        for (int k = 0; k <= nargs; k++) {
+            // varargs invoker #0..N
+            countTest();
+            calledLog.clear();
+            inv = MethodHandles.varargsInvoker(type, k);
+            List<Object> targetPlusVarArgs = new ArrayList<Object>(targetPlusArgs);
+            List<Object> tailList = targetPlusVarArgs.subList(1+k, 1+nargs);
+            Object[] tail = tailList.toArray();
+            tailList.clear(); tailList.add(tail);
+            result = inv.invokeVarargs(targetPlusVarArgs);
+            if (testRetCode)  assertEquals(code, result);
+            assertCalled("invokee", args);
+        }
+        // dynamic invoker
+        countTest();
+        CallSite site = new CallSite(MethodHandlesTest.class, "foo", type);
+        inv = MethodHandles.dynamicInvoker(site);
+        site.setTarget(target);
+        calledLog.clear();
+        result = inv.invokeVarargs(args);
+        if (testRetCode)  assertEquals(code, result);
+        assertCalled("invokee", args);
+    }
+
+    static Object invokee(Object... args) {
+        return called("invokee", args).hashCode();
+    }
+
+    private static final String MISSING_ARG = "missingArg";
+    static Object targetIfEquals() {
+        return called("targetIfEquals");
+    }
+    static Object fallbackIfNotEquals() {
+        return called("fallbackIfNotEquals");
+    }
+    static Object targetIfEquals(Object x) {
+        assertEquals(x, MISSING_ARG);
+        return called("targetIfEquals", x);
+    }
+    static Object fallbackIfNotEquals(Object x) {
+        assertFalse(x.toString(), x.equals(MISSING_ARG));
+        return called("fallbackIfNotEquals", x);
+    }
+    static Object targetIfEquals(Object x, Object y) {
+        assertEquals(x, y);
+        return called("targetIfEquals", x, y);
+    }
+    static Object fallbackIfNotEquals(Object x, Object y) {
+        assertFalse(x.toString(), x.equals(y));
+        return called("fallbackIfNotEquals", x, y);
+    }
+    static Object targetIfEquals(Object x, Object y, Object z) {
+        assertEquals(x, y);
+        return called("targetIfEquals", x, y, z);
+    }
+    static Object fallbackIfNotEquals(Object x, Object y, Object z) {
+        assertFalse(x.toString(), x.equals(y));
+        return called("fallbackIfNotEquals", x, y, z);
+    }
+
+    @Test
+    public void testGuardWithTest() throws Throwable {
+        if (CAN_SKIP_WORKING)  return;
+        startTest("guardWithTest");
+        for (int nargs = 0; nargs <= 3; nargs++) {
+            if (nargs != 2)  continue;  // FIXME: test more later
+            testGuardWithTest(nargs, Object.class);
+            testGuardWithTest(nargs, String.class);
+        }
+    }
+    void testGuardWithTest(int nargs, Class<?> argClass) throws Throwable {
+        countTest();
+        MethodHandle test = PRIVATE.findVirtual(Object.class, "equals", MethodType.methodType(boolean.class, Object.class));
+        MethodHandle target = PRIVATE.findStatic(MethodHandlesTest.class, "targetIfEquals", MethodType.genericMethodType(nargs));
+        MethodHandle fallback = PRIVATE.findStatic(MethodHandlesTest.class, "fallbackIfNotEquals", MethodType.genericMethodType(nargs));
+        while (test.type().parameterCount() < nargs)
+            test = MethodHandles.dropArguments(test, test.type().parameterCount()-1, Object.class);
+        while (test.type().parameterCount() > nargs)
+            test = MethodHandles.insertArguments(test, 0, MISSING_ARG);
+        if (argClass != Object.class) {
+            test = changeArgTypes(test, argClass);
+            target = changeArgTypes(target, argClass);
+            fallback = changeArgTypes(fallback, argClass);
+        }
+        MethodHandle mh = MethodHandles.guardWithTest(test, target, fallback);
+        assertEquals(target.type(), mh.type());
+        Object[][] argLists = {
+            { },
+            { "foo" }, { MISSING_ARG },
+            { "foo", "foo" }, { "foo", "bar" },
+            { "foo", "foo", "baz" }, { "foo", "bar", "baz" }
+        };
+        for (Object[] argList : argLists) {
+            if (argList.length != nargs)  continue;
+            boolean equals;
+            switch (nargs) {
+            case 0:   equals = true; break;
+            case 1:   equals = MISSING_ARG.equals(argList[0]); break;
+            default:  equals = argList[0].equals(argList[1]); break;
+            }
+            String willCall = (equals ? "targetIfEquals" : "fallbackIfNotEquals");
+            if (verbosity >= 2)
+                System.out.println(logEntry(willCall, argList));
+            Object result = mh.invokeVarargs(argList);
+            assertCalled(willCall, argList);
+        }
+    }
+
+    @Test
+    public void testCatchException() throws Throwable {
+        if (CAN_SKIP_WORKING)  return;
+        startTest("catchException");
+        for (int nargs = 2; nargs <= 6; nargs++) {
+            for (int ti = 0; ti <= 1; ti++) {
+                boolean throwIt = (ti != 0);
+                testCatchException(int.class, new ClassCastException("testing"), throwIt, nargs);
+                testCatchException(void.class, new java.io.IOException("testing"), throwIt, nargs);
+                testCatchException(String.class, new LinkageError("testing"), throwIt, nargs);
+            }
+        }
+    }
+
+    private static <T extends Throwable>
+    Object throwOrReturn(Object normal, T exception) throws T {
+        if (exception != null)  throw exception;
+        return normal;
+    }
+
+    void testCatchException(Class<?> returnType, Throwable thrown, boolean throwIt, int nargs) throws Throwable {
+        countTest();
+        if (verbosity >= 2)
+            System.out.println("catchException rt="+returnType+" throw="+throwIt+" nargs="+nargs);
+        Class<? extends Throwable> exType = thrown.getClass();
+        MethodHandle throwOrReturn
+                = PRIVATE.findStatic(MethodHandlesTest.class, "throwOrReturn",
+                    MethodType.methodType(Object.class, Object.class, Throwable.class));
+        MethodHandle thrower = throwOrReturn;
+        while (thrower.type().parameterCount() < nargs)
+            thrower = MethodHandles.dropArguments(thrower, thrower.type().parameterCount(), Object.class);
+        MethodHandle target = MethodHandles.catchException(thrower,
+                thrown.getClass(), ValueConversions.varargsList(1+nargs));
+        assertEquals(thrower.type(), target.type());
+        //System.out.println("catching with "+target+" : "+throwOrReturn);
+        Object[] args = randomArgs(nargs, Object.class);
+        args[1] = (throwIt ? thrown : null);
+        Object returned = target.invokeVarargs(args);
+        //System.out.println("return from "+target+" : "+returned);
+        if (!throwIt) {
+            assertSame(args[0], returned);
+        } else {
+            List<Object> catchArgs = new ArrayList<Object>(Arrays.asList(args));
+            catchArgs.add(0, thrown);
+            assertEquals(catchArgs, returned);
+        }
+    }
+
+    @Test
+    public void testThrowException() throws Throwable {
+        if (CAN_SKIP_WORKING)  return;
+        startTest("throwException");
+        testThrowException(int.class, new ClassCastException("testing"));
+        testThrowException(void.class, new java.io.IOException("testing"));
+        testThrowException(String.class, new LinkageError("testing"));
+    }
+
+    void testThrowException(Class<?> returnType, Throwable thrown) throws Throwable {
+        countTest();
+        Class<? extends Throwable> exType = thrown.getClass();
+        MethodHandle target = MethodHandles.throwException(returnType, exType);
+        //System.out.println("throwing with "+target+" : "+thrown);
+        MethodType expectedType = MethodType.methodType(returnType, exType);
+        assertEquals(expectedType, target.type());
+        Throwable caught = null;
+        try {
+            Object res = target.invokeGeneric(thrown);
+            fail("got "+res+" instead of throwing "+thrown);
+        } catch (Throwable ex) {
+            if (ex != thrown) {
+                if (ex instanceof Error)  throw (Error)ex;
+                if (ex instanceof RuntimeException)  throw (RuntimeException)ex;
+            }
+            caught = ex;
+        }
+        assertSame(thrown, caught);
+    }
+
+    @Test
+    public void testCastFailure() throws Throwable {
+        if (CAN_SKIP_WORKING)  return;
+        startTest("testCastFailure");
+        testCastFailure("cast/argument", 11000);
+        testCastFailure("unbox/argument", 11000);
+        testCastFailure("cast/return", 11000);
+        testCastFailure("unbox/return", 11000);
+    }
+
+    static class Surprise extends JavaMethodHandle {
+        Surprise() { super("value"); }
+        Object value(Object x) {
+            trace("value", x);
+            if (boo != null)  return boo;
+            return x;
+        }
+        Object boo;
+        void boo(Object x) { boo = x; }
+
+        static void trace(String x, Object y) {
+            if (verbosity > 8) System.out.println(x+"="+y);
+        }
+        static Object  refIdentity(Object x)  { trace("ref.x", x); return x; }
+        static Integer boxIdentity(Integer x) { trace("box.x", x); return x; }
+        static int     intIdentity(int x)     { trace("int.x", x); return x; }
+        static MethodHandle REF_IDENTITY = PRIVATE.findStatic(
+                Surprise.class, "refIdentity",
+                    MethodType.methodType(Object.class, Object.class));
+        static MethodHandle BOX_IDENTITY = PRIVATE.findStatic(
+                Surprise.class, "boxIdentity",
+                    MethodType.methodType(Integer.class, Integer.class));
+        static MethodHandle INT_IDENTITY = PRIVATE.findStatic(
+                Surprise.class, "intIdentity",
+                    MethodType.methodType(int.class, int.class));
+    }
+
+    void testCastFailure(String mode, int okCount) throws Throwable {
+        countTest(false);
+        if (verbosity > 1)  System.out.println("mode="+mode);
+        Surprise boo = new Surprise();
+        MethodHandle identity = Surprise.REF_IDENTITY, surprise = boo;
+        if (mode.endsWith("/return")) {
+            if (mode.equals("unbox/return")) {
+                // fail on return to ((Integer)surprise).intValue
+                surprise = MethodHandles.convertArguments(surprise, MethodType.methodType(int.class, Object.class));
+                identity = MethodHandles.convertArguments(identity, MethodType.methodType(int.class, Object.class));
+            } else if (mode.equals("cast/return")) {
+                // fail on return to (Integer)surprise
+                surprise = MethodHandles.convertArguments(surprise, MethodType.methodType(Integer.class, Object.class));
+                identity = MethodHandles.convertArguments(identity, MethodType.methodType(Integer.class, Object.class));
+            }
+        } else if (mode.endsWith("/argument")) {
+            MethodHandle callee = null;
+            if (mode.equals("unbox/argument")) {
+                // fail on handing surprise to int argument
+                callee = Surprise.INT_IDENTITY;
+            } else if (mode.equals("cast/argument")) {
+                // fail on handing surprise to Integer argument
+                callee = Surprise.BOX_IDENTITY;
+            }
+            if (callee != null) {
+                callee = MethodHandles.convertArguments(callee, MethodType.genericMethodType(1));
+                surprise = MethodHandles.filterArguments(callee, surprise);
+                identity = MethodHandles.filterArguments(callee, identity);
+            }
+        }
+        assertNotSame(mode, surprise, boo);
+        identity = MethodHandles.convertArguments(identity, MethodType.genericMethodType(1));
+        surprise = MethodHandles.convertArguments(surprise, MethodType.genericMethodType(1));
+        Object x = 42;
+        for (int i = 0; i < okCount; i++) {
+            Object y = identity.invoke(x);
+            assertEquals(x, y);
+            Object z = surprise.invoke(x);
+            assertEquals(x, z);
+        }
+        boo.boo("Boo!");
+        Object y = identity.invoke(x);
+        assertEquals(x, y);
+        try {
+            Object z = surprise.invoke(x);
+            System.out.println("Failed to throw; got z="+z);
+            assertTrue(false);
+        } catch (Exception ex) {
+            if (verbosity > 1)
+                System.out.println("caught "+ex);
+            if (verbosity > 2)
+                ex.printStackTrace();
+            assertTrue(ex instanceof ClassCastException
+                    // FIXME: accept only one of the two for any given unit test
+                    || ex instanceof WrongMethodTypeException
+                    );
+        }
+    }
+
+}
+// Local abbreviated copy of sun.dyn.util.ValueConversions
+class ValueConversions {
+    private static final Lookup IMPL_LOOKUP = MethodHandles.lookup();
+    private static final Object[] NO_ARGS_ARRAY = {};
+    private static Object[] makeArray(Object... args) { return args; }
+    private static Object[] array() { return NO_ARGS_ARRAY; }
+    private static Object[] array(Object a0)
+                { return makeArray(a0); }
+    private static Object[] array(Object a0, Object a1)
+                { return makeArray(a0, a1); }
+    private static Object[] array(Object a0, Object a1, Object a2)
+                { return makeArray(a0, a1, a2); }
+    private static Object[] array(Object a0, Object a1, Object a2, Object a3)
+                { return makeArray(a0, a1, a2, a3); }
+    private static Object[] array(Object a0, Object a1, Object a2, Object a3,
+                                  Object a4)
+                { return makeArray(a0, a1, a2, a3, a4); }
+    private static Object[] array(Object a0, Object a1, Object a2, Object a3,
+                                  Object a4, Object a5)
+                { return makeArray(a0, a1, a2, a3, a4, a5); }
+    private static Object[] array(Object a0, Object a1, Object a2, Object a3,
+                                  Object a4, Object a5, Object a6)
+                { return makeArray(a0, a1, a2, a3, a4, a5, a6); }
+    private static Object[] array(Object a0, Object a1, Object a2, Object a3,
+                                  Object a4, Object a5, Object a6, Object a7)
+                { return makeArray(a0, a1, a2, a3, a4, a5, a6, a7); }
+    private static Object[] array(Object a0, Object a1, Object a2, Object a3,
+                                  Object a4, Object a5, Object a6, Object a7,
+                                  Object a8)
+                { return makeArray(a0, a1, a2, a3, a4, a5, a6, a7, a8); }
+    private static Object[] array(Object a0, Object a1, Object a2, Object a3,
+                                  Object a4, Object a5, Object a6, Object a7,
+                                  Object a8, Object a9)
+                { return makeArray(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
+    static MethodHandle[] makeArrays() {
+        ArrayList<MethodHandle> arrays = new ArrayList<MethodHandle>();
+        MethodHandles.Lookup lookup = IMPL_LOOKUP;
+        for (;;) {
+            int nargs = arrays.size();
+            MethodType type = MethodType.genericMethodType(nargs).changeReturnType(Object[].class);
+            String name = "array";
+            MethodHandle array = null;
+            try {
+                array = lookup.findStatic(ValueConversions.class, name, type);
+            } catch (NoAccessException ex) {
+            }
+            if (array == null)  break;
+            arrays.add(array);
+        }
+        assert(arrays.size() == 11);  // current number of methods
+        return arrays.toArray(new MethodHandle[0]);
+    }
+    static final MethodHandle[] ARRAYS = makeArrays();
+
+    /** Return a method handle that takes the indicated number of Object
+     *  arguments and returns an Object array of them, as if for varargs.
+     */
+    public static MethodHandle varargsArray(int nargs) {
+        if (nargs < ARRAYS.length)
+            return ARRAYS[nargs];
+        // else need to spin bytecode or do something else fancy
+        throw new UnsupportedOperationException("NYI");
+    }
+
+    private static final List<Object> NO_ARGS_LIST = Arrays.asList(NO_ARGS_ARRAY);
+    private static List<Object> makeList(Object... args) { return Arrays.asList(args); }
+    private static List<Object> list() { return NO_ARGS_LIST; }
+    private static List<Object> list(Object a0)
+                { return makeList(a0); }
+    private static List<Object> list(Object a0, Object a1)
+                { return makeList(a0, a1); }
+    private static List<Object> list(Object a0, Object a1, Object a2)
+                { return makeList(a0, a1, a2); }
+    private static List<Object> list(Object a0, Object a1, Object a2, Object a3)
+                { return makeList(a0, a1, a2, a3); }
+    private static List<Object> list(Object a0, Object a1, Object a2, Object a3,
+                                     Object a4)
+                { return makeList(a0, a1, a2, a3, a4); }
+    private static List<Object> list(Object a0, Object a1, Object a2, Object a3,
+                                     Object a4, Object a5)
+                { return makeList(a0, a1, a2, a3, a4, a5); }
+    private static List<Object> list(Object a0, Object a1, Object a2, Object a3,
+                                     Object a4, Object a5, Object a6)
+                { return makeList(a0, a1, a2, a3, a4, a5, a6); }
+    private static List<Object> list(Object a0, Object a1, Object a2, Object a3,
+                                     Object a4, Object a5, Object a6, Object a7)
+                { return makeList(a0, a1, a2, a3, a4, a5, a6, a7); }
+    private static List<Object> list(Object a0, Object a1, Object a2, Object a3,
+                                     Object a4, Object a5, Object a6, Object a7,
+                                     Object a8)
+                { return makeList(a0, a1, a2, a3, a4, a5, a6, a7, a8); }
+    private static List<Object> list(Object a0, Object a1, Object a2, Object a3,
+                                     Object a4, Object a5, Object a6, Object a7,
+                                     Object a8, Object a9)
+                { return makeList(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
+    static MethodHandle[] makeLists() {
+        ArrayList<MethodHandle> arrays = new ArrayList<MethodHandle>();
+        MethodHandles.Lookup lookup = IMPL_LOOKUP;
+        for (;;) {
+            int nargs = arrays.size();
+            MethodType type = MethodType.genericMethodType(nargs).changeReturnType(List.class);
+            String name = "list";
+            MethodHandle array = null;
+            try {
+                array = lookup.findStatic(ValueConversions.class, name, type);
+            } catch (NoAccessException ex) {
+            }
+            if (array == null)  break;
+            arrays.add(array);
+        }
+        assert(arrays.size() == 11);  // current number of methods
+        return arrays.toArray(new MethodHandle[0]);
+    }
+    static final MethodHandle[] LISTS = makeLists();
+
+    /** Return a method handle that takes the indicated number of Object
+     *  arguments and returns List.
+     */
+    public static MethodHandle varargsList(int nargs) {
+        if (nargs < LISTS.length)
+            return LISTS[nargs];
+        // else need to spin bytecode or do something else fancy
+        throw new UnsupportedOperationException("NYI");
+    }
+}
+// This guy tests access from outside the same package member, but inside
+// the package itself.
+class PackageSibling {
+    static Lookup lookup() {
+        return MethodHandles.lookup();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/Math/CeilAndFloorTests.java	Wed Jul 05 17:04:56 2017 +0200
@@ -0,0 +1,201 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6908131
+ * @summary Check for correct implementation of Math.ceil and Math.floor
+ */
+
+import sun.misc.FpUtils;
+import sun.misc.DoubleConsts;
+
+public class CeilAndFloorTests {
+    private static int testCeilCase(double input, double expected) {
+        int failures = 0;
+        failures += Tests.test("Math.ceil",  input, Math.ceil(input),   expected);
+        failures += Tests.test("StrictMath.ceil",  input, StrictMath.ceil(input), expected);
+        return failures;
+    }
+
+    private static int testFloorCase(double input, double expected) {
+        int failures = 0;
+        failures += Tests.test("Math.floor",  input, Math.floor(input),   expected);
+        failures += Tests.test("StrictMath.floor",  input, StrictMath.floor(input), expected);
+        return failures;
+    }
+
+    private static int nearIntegerTests() {
+        int failures = 0;
+
+        double [] fixedPoints = {
+            -0.0,
+             0.0,
+            -1.0,
+             1.0,
+            -0x1.0p52,
+             0x1.0p52,
+            -Double.MAX_VALUE,
+             Double.MAX_VALUE,
+             Double.NEGATIVE_INFINITY,
+             Double.POSITIVE_INFINITY,
+             Double.NaN,
+        };
+
+        for(double fixedPoint : fixedPoints) {
+            failures += testCeilCase(fixedPoint, fixedPoint);
+            failures += testFloorCase(fixedPoint, fixedPoint);
+        }
+
+        for(int i = Double.MIN_EXPONENT; i <= Double.MAX_EXPONENT; i++) {
+            double powerOfTwo   = Math.scalb(1.0, i);
+            double neighborDown = FpUtils.nextDown(powerOfTwo);
+            double neighborUp   = Math.nextUp(powerOfTwo);
+
+            if (i < 0) {
+                failures += testCeilCase( powerOfTwo,  1.0);
+                failures += testCeilCase(-powerOfTwo, -0.0);
+
+                failures += testFloorCase( powerOfTwo,  0.0);
+                failures += testFloorCase(-powerOfTwo, -1.0);
+
+                failures += testCeilCase( neighborDown, 1.0);
+                failures += testCeilCase(-neighborDown, -0.0);
+
+                failures += testFloorCase( neighborUp,  0.0);
+                failures += testFloorCase(-neighborUp, -1.0);
+            } else {
+                failures += testCeilCase(powerOfTwo, powerOfTwo);
+                failures += testFloorCase(powerOfTwo, powerOfTwo);
+
+                if (neighborDown==Math.rint(neighborDown)) {
+                    failures += testCeilCase( neighborDown,  neighborDown);
+                    failures += testCeilCase(-neighborDown, -neighborDown);
+
+                    failures += testFloorCase( neighborDown, neighborDown);
+                    failures += testFloorCase(-neighborDown,-neighborDown);
+                } else {
+                    failures += testCeilCase( neighborDown, powerOfTwo);
+                    failures += testFloorCase(-neighborDown, -powerOfTwo);
+                }
+
+                if (neighborUp==Math.rint(neighborUp)) {
+                    failures += testCeilCase(neighborUp, neighborUp);
+                    failures += testCeilCase(-neighborUp, -neighborUp);
+
+                    failures += testFloorCase(neighborUp, neighborUp);
+                    failures += testFloorCase(-neighborUp, -neighborUp);
+                } else {
+                    failures += testFloorCase(neighborUp, powerOfTwo);
+                    failures += testCeilCase(-neighborUp, -powerOfTwo);
+                }
+            }
+        }
+
+        for(int i = -(0x10000); i <= 0x10000; i++) {
+            double d = (double) i;
+            double neighborDown = FpUtils.nextDown(d);
+            double neighborUp   = Math.nextUp(d);
+
+            failures += testCeilCase( d, d);
+            failures += testCeilCase(-d, -d);
+
+            failures += testFloorCase( d, d);
+            failures += testFloorCase(-d, -d);
+
+            if (Math.abs(d) > 1.0) {
+                failures += testCeilCase( neighborDown, d);
+                failures += testCeilCase(-neighborDown, -d+1);
+
+                failures += testFloorCase( neighborUp, d);
+                failures += testFloorCase(-neighborUp, -d-1);
+            }
+        }
+
+        return failures;
+    }
+
+    public static int roundingTests() {
+        int failures = 0;
+        double [][] testCases = {
+            { Double.MIN_VALUE,                           1.0},
+            {-Double.MIN_VALUE,                          -0.0},
+            { FpUtils.nextDown(DoubleConsts.MIN_NORMAL),  1.0},
+            {-FpUtils.nextDown(DoubleConsts.MIN_NORMAL), -0.0},
+            { DoubleConsts.MIN_NORMAL,                    1.0},
+            {-DoubleConsts.MIN_NORMAL,                   -0.0},
+
+            { 0.1,                                        1.0},
+            {-0.1,                                       -0.0},
+
+            { 0.5,                                        1.0},
+            {-0.5,                                       -0.0},
+
+            { 1.5,                                        2.0},
+            {-1.5,                                       -1.0},
+
+            { 2.5,                                        3.0},
+            {-2.5,                                       -2.0},
+
+            { FpUtils.nextDown(1.0),                      1.0},
+            { FpUtils.nextDown(-1.0),                    -1.0},
+
+            { Math.nextUp(1.0),                           2.0},
+            { Math.nextUp(-1.0),                         -0.0},
+
+            { 0x1.0p51,                                 0x1.0p51},
+            {-0x1.0p51,                                -0x1.0p51},
+
+            { FpUtils.nextDown(0x1.0p51),               0x1.0p51},
+            {-Math.nextUp(0x1.0p51),                   -0x1.0p51},
+
+            { Math.nextUp(0x1.0p51),                    0x1.0p51+1},
+            {-FpUtils.nextDown(0x1.0p51),              -0x1.0p51+1},
+
+            { FpUtils.nextDown(0x1.0p52),               0x1.0p52},
+            {-Math.nextUp(0x1.0p52),                   -0x1.0p52-1.0},
+
+            { Math.nextUp(0x1.0p52),                    0x1.0p52+1.0},
+            {-FpUtils.nextDown(0x1.0p52),              -0x1.0p52+1.0},
+        };
+
+        for(double[] testCase : testCases) {
+            failures += testCeilCase(testCase[0], testCase[1]);
+            failures += testFloorCase(-testCase[0], -testCase[1]);
+        }
+        return failures;
+    }
+
+    public static void main(String... args) {
+        int failures = 0;
+
+        failures += nearIntegerTests();
+        failures += roundingTests();
+
+        if (failures > 0) {
+            System.err.println("Testing {Math, StrictMath}.ceil incurred "
+                               + failures + " failures.");
+            throw new RuntimeException();
+        }
+    }
+}
--- a/jdk/test/java/math/BigInteger/BigIntegerTest.java	Thu Dec 17 14:10:20 2009 -0800
+++ b/jdk/test/java/math/BigInteger/BigIntegerTest.java	Wed Jul 05 17:04:56 2017 +0200
@@ -642,37 +642,71 @@
 
         for(int i = 0; i < bitPatterns.length; i++) {
             BigInteger b1 = new BigInteger(bitPatterns[i], 16);
+            BigInteger b2 = null;
 
             File f = new File("serialtest");
             FileOutputStream fos = new FileOutputStream(f);
-            ObjectOutputStream oos = new ObjectOutputStream(fos);
-            oos.writeObject(b1);
-            oos.flush();
-            oos.close();
-            FileInputStream fis = new FileInputStream(f);
-            ObjectInputStream ois = new ObjectInputStream(fis);
-            BigInteger b2 = (BigInteger)ois.readObject();
+            try {
+                ObjectOutputStream oos = new ObjectOutputStream(fos);
+                try {
+                    oos.writeObject(b1);
+                    oos.flush();
+                } finally {
+                    oos.close();
+                }
 
-            if (!b1.equals(b2) ||
-                !b1.equals(b1.or(b2))) {
-                failCount++;
-                System.err.println("Serialized failed for hex " +
-                                   b1.toString(16));
+                FileInputStream fis = new FileInputStream(f);
+                try {
+                    ObjectInputStream ois = new ObjectInputStream(fis);
+                    try {
+                        b2 = (BigInteger)ois.readObject();
+                    } finally {
+                        ois.close();
+                    }
+                } finally {
+                    fis.close();
+                }
+
+                if (!b1.equals(b2) ||
+                    !b1.equals(b1.or(b2))) {
+                    failCount++;
+                    System.err.println("Serialized failed for hex " +
+                                       b1.toString(16));
+                }
+            } finally {
+                fos.close();
             }
             f.delete();
         }
 
         for(int i=0; i<10; i++) {
             BigInteger b1 = fetchNumber(rnd.nextInt(100));
+            BigInteger b2 = null;
             File f = new File("serialtest");
             FileOutputStream fos = new FileOutputStream(f);
-            ObjectOutputStream oos = new ObjectOutputStream(fos);
-            oos.writeObject(b1);
-            oos.flush();
-            oos.close();
-            FileInputStream fis = new FileInputStream(f);
-            ObjectInputStream ois = new ObjectInputStream(fis);
-            BigInteger b2 = (BigInteger)ois.readObject();
+            try {
+                ObjectOutputStream oos = new ObjectOutputStream(fos);
+                try {
+                    oos.writeObject(b1);
+                    oos.flush();
+                } finally {
+                    oos.close();
+                }
+
+                FileInputStream fis = new FileInputStream(f);
+                try {
+                    ObjectInputStream ois = new ObjectInputStream(fis);
+                    try {
+                        b2 = (BigInteger)ois.readObject();
+                    } finally {
+                        ois.close();
+                    }
+                } finally {
+                    fis.close();
+                }
+            } finally {
+                fos.close();
+            }
 
             if (!b1.equals(b2) ||
                 !b1.equals(b1.or(b2)))
--- a/jdk/test/java/nio/Buffer/Basic-X.java.template	Thu Dec 17 14:10:20 2009 -0800
+++ b/jdk/test/java/nio/Buffer/Basic-X.java.template	Wed Jul 05 17:04:56 2017 +0200
@@ -38,6 +38,26 @@
     extends Basic
 {
 
+    private static final $type$[] VALUES = {
+        $Fulltype$.MIN_VALUE,
+        ($type$) -1,
+        ($type$) 0,
+        ($type$) 1,
+        $Fulltype$.MAX_VALUE,
+#if[float]
+        $Fulltype$.NEGATIVE_INFINITY,
+        $Fulltype$.POSITIVE_INFINITY,
+        $Fulltype$.NaN,
+        ($type$) -0.0,
+#end[float]
+#if[double]
+        $Fulltype$.NEGATIVE_INFINITY,
+        $Fulltype$.POSITIVE_INFINITY,
+        $Fulltype$.NaN,
+        ($type$) -0.0,
+#end[double]
+    };
+
     private static void relGet($Type$Buffer b) {
         int n = b.capacity();
         $type$ v;
@@ -309,6 +329,12 @@
 
 #end[byte]
 
+    private static void fail(String problem,
+                             $Type$Buffer xb, $Type$Buffer yb,
+                             $type$ x, $type$ y) {
+        fail(problem + String.format(": x=%s y=%s", x, y), xb, yb);
+    }
+
     private static void tryCatch(Buffer b, Class ex, Runnable thunk) {
         boolean caught = false;
         try {
@@ -522,6 +548,42 @@
         if (b.compareTo(b2) <= 0)
             fail("Comparison to lesser buffer <= 0", b, b2);
 
+        // Check equals and compareTo with interesting values
+        for ($type$ x : VALUES) {
+            $Type$Buffer xb = $Type$Buffer.wrap(new $type$[] { x });
+            if (xb.compareTo(xb) != 0) {
+                fail("compareTo not reflexive", xb, xb, x, x);
+            }
+            if (! xb.equals(xb)) {
+                fail("equals not reflexive", xb, xb, x, x);
+            }
+            for ($type$ y : VALUES) {
+                $Type$Buffer yb = $Type$Buffer.wrap(new $type$[] { y });
+                if (xb.compareTo(yb) != - yb.compareTo(xb)) {
+                    fail("compareTo not anti-symmetric",
+                         xb, yb, x, y);
+                }
+                if ((xb.compareTo(yb) == 0) != xb.equals(yb)) {
+                    fail("compareTo inconsistent with equals",
+                         xb, yb, x, y);
+                }
+                if (xb.compareTo(yb) != $Fulltype$.compare(x, y)) {
+#if[float]
+                    if (x == 0.0 && y == 0.0) continue;
+#end[float]
+#if[double]
+                    if (x == 0.0 && y == 0.0) continue;
+#end[double]
+                    fail("Incorrect results for $Type$Buffer.compareTo",
+                         xb, yb, x, y);
+                }
+                if (xb.equals(yb) != ((x == y) || ((x != x) && (y != y)))) {
+                    fail("Incorrect results for $Type$Buffer.equals",
+                         xb, yb, x, y);
+                }
+            }
+        }
+
         // Sub, dup
 
         relPut(b);
--- a/jdk/test/java/nio/Buffer/BasicByte.java	Thu Dec 17 14:10:20 2009 -0800
+++ b/jdk/test/java/nio/Buffer/BasicByte.java	Wed Jul 05 17:04:56 2017 +0200
@@ -38,6 +38,26 @@
     extends Basic
 {
 
+    private static final byte[] VALUES = {
+        Byte.MIN_VALUE,
+        (byte) -1,
+        (byte) 0,
+        (byte) 1,
+        Byte.MAX_VALUE,
+
+
+
+
+
+
+
+
+
+
+
+
+    };
+
     private static void relGet(ByteBuffer b) {
         int n = b.capacity();
         byte v;
@@ -309,6 +329,12 @@
 
 
 
+    private static void fail(String problem,
+                             ByteBuffer xb, ByteBuffer yb,
+                             byte x, byte y) {
+        fail(problem + String.format(": x=%s y=%s", x, y), xb, yb);
+    }
+
     private static void tryCatch(Buffer b, Class ex, Runnable thunk) {
         boolean caught = false;
         try {
@@ -522,6 +548,42 @@
         if (b.compareTo(b2) <= 0)
             fail("Comparison to lesser buffer <= 0", b, b2);
 
+        // Check equals and compareTo with interesting values
+        for (byte x : VALUES) {
+            ByteBuffer xb = ByteBuffer.wrap(new byte[] { x });
+            if (xb.compareTo(xb) != 0) {
+                fail("compareTo not reflexive", xb, xb, x, x);
+            }
+            if (! xb.equals(xb)) {
+                fail("equals not reflexive", xb, xb, x, x);
+            }
+            for (byte y : VALUES) {
+                ByteBuffer yb = ByteBuffer.wrap(new byte[] { y });
+                if (xb.compareTo(yb) != - yb.compareTo(xb)) {
+                    fail("compareTo not anti-symmetric",
+                         xb, yb, x, y);
+                }
+                if ((xb.compareTo(yb) == 0) != xb.equals(yb)) {
+                    fail("compareTo inconsistent with equals",
+                         xb, yb, x, y);
+                }
+                if (xb.compareTo(yb) != Byte.compare(x, y)) {
+
+
+
+
+
+
+                    fail("Incorrect results for ByteBuffer.compareTo",
+                         xb, yb, x, y);
+                }
+                if (xb.equals(yb) != ((x == y) || ((x != x) && (y != y)))) {
+                    fail("Incorrect results for ByteBuffer.equals",
+                         xb, yb, x, y);
+                }
+            }
+        }
+
         // Sub, dup
 
         relPut(b);
--- a/jdk/test/java/nio/Buffer/BasicChar.java	Thu Dec 17 14:10:20 2009 -0800
+++ b/jdk/test/java/nio/Buffer/BasicChar.java	Wed Jul 05 17:04:56 2017 +0200
@@ -38,6 +38,26 @@
     extends Basic
 {
 
+    private static final char[] VALUES = {
+        Character.MIN_VALUE,
+        (char) -1,
+        (char) 0,
+        (char) 1,
+        Character.MAX_VALUE,
+
+
+
+
+
+
+
+
+
+
+
+
+    };
+
     private static void relGet(CharBuffer b) {
         int n = b.capacity();
         char v;
@@ -309,6 +329,12 @@
 
 
 
+    private static void fail(String problem,
+                             CharBuffer xb, CharBuffer yb,
+                             char x, char y) {
+        fail(problem + String.format(": x=%s y=%s", x, y), xb, yb);
+    }
+
     private static void tryCatch(Buffer b, Class ex, Runnable thunk) {
         boolean caught = false;
         try {
@@ -522,6 +548,42 @@
         if (b.compareTo(b2) <= 0)
             fail("Comparison to lesser buffer <= 0", b, b2);
 
+        // Check equals and compareTo with interesting values
+        for (char x : VALUES) {
+            CharBuffer xb = CharBuffer.wrap(new char[] { x });
+            if (xb.compareTo(xb) != 0) {
+                fail("compareTo not reflexive", xb, xb, x, x);
+            }
+            if (! xb.equals(xb)) {
+                fail("equals not reflexive", xb, xb, x, x);
+            }
+            for (char y : VALUES) {
+                CharBuffer yb = CharBuffer.wrap(new char[] { y });
+                if (xb.compareTo(yb) != - yb.compareTo(xb)) {
+                    fail("compareTo not anti-symmetric",
+                         xb, yb, x, y);
+                }
+                if ((xb.compareTo(yb) == 0) != xb.equals(yb)) {
+                    fail("compareTo inconsistent with equals",
+                         xb, yb, x, y);
+                }
+                if (xb.compareTo(yb) != Character.compare(x, y)) {
+
+
+
+
+
+
+                    fail("Incorrect results for CharBuffer.compareTo",
+                         xb, yb, x, y);
+                }
+                if (xb.equals(yb) != ((x == y) || ((x != x) && (y != y)))) {
+                    fail("Incorrect results for CharBuffer.equals",
+                         xb, yb, x, y);
+                }
+            }
+        }
+
         // Sub, dup
 
         relPut(b);
--- a/jdk/test/java/nio/Buffer/BasicDouble.java	Thu Dec 17 14:10:20 2009 -0800
+++ b/jdk/test/java/nio/Buffer/BasicDouble.java	Wed Jul 05 17:04:56 2017 +0200
@@ -38,6 +38,26 @@
     extends Basic
 {
 
+    private static final double[] VALUES = {
+        Double.MIN_VALUE,
+        (double) -1,
+        (double) 0,
+        (double) 1,
+        Double.MAX_VALUE,
+
+
+
+
+
+
+
+        Double.NEGATIVE_INFINITY,
+        Double.POSITIVE_INFINITY,
+        Double.NaN,
+        (double) -0.0,
+
+    };
+
     private static void relGet(DoubleBuffer b) {
         int n = b.capacity();
         double v;
@@ -309,6 +329,12 @@
 
 
 
+    private static void fail(String problem,
+                             DoubleBuffer xb, DoubleBuffer yb,
+                             double x, double y) {
+        fail(problem + String.format(": x=%s y=%s", x, y), xb, yb);
+    }
+
     private static void tryCatch(Buffer b, Class ex, Runnable thunk) {
         boolean caught = false;
         try {
@@ -522,6 +548,42 @@
         if (b.compareTo(b2) <= 0)
             fail("Comparison to lesser buffer <= 0", b, b2);
 
+        // Check equals and compareTo with interesting values
+        for (double x : VALUES) {
+            DoubleBuffer xb = DoubleBuffer.wrap(new double[] { x });
+            if (xb.compareTo(xb) != 0) {
+                fail("compareTo not reflexive", xb, xb, x, x);
+            }
+            if (! xb.equals(xb)) {
+                fail("equals not reflexive", xb, xb, x, x);
+            }
+            for (double y : VALUES) {
+                DoubleBuffer yb = DoubleBuffer.wrap(new double[] { y });
+                if (xb.compareTo(yb) != - yb.compareTo(xb)) {
+                    fail("compareTo not anti-symmetric",
+                         xb, yb, x, y);
+                }
+                if ((xb.compareTo(yb) == 0) != xb.equals(yb)) {
+                    fail("compareTo inconsistent with equals",
+                         xb, yb, x, y);
+                }
+                if (xb.compareTo(yb) != Double.compare(x, y)) {
+
+
+
+
+                    if (x == 0.0 && y == 0.0) continue;
+
+                    fail("Incorrect results for DoubleBuffer.compareTo",
+                         xb, yb, x, y);
+                }
+                if (xb.equals(yb) != ((x == y) || ((x != x) && (y != y)))) {
+                    fail("Incorrect results for DoubleBuffer.equals",
+                         xb, yb, x, y);
+                }
+            }
+        }
+
         // Sub, dup
 
         relPut(b);
--- a/jdk/test/java/nio/Buffer/BasicFloat.java	Thu Dec 17 14:10:20 2009 -0800
+++ b/jdk/test/java/nio/Buffer/BasicFloat.java	Wed Jul 05 17:04:56 2017 +0200
@@ -38,6 +38,26 @@
     extends Basic
 {
 
+    private static final float[] VALUES = {
+        Float.MIN_VALUE,
+        (float) -1,
+        (float) 0,
+        (float) 1,
+        Float.MAX_VALUE,
+
+        Float.NEGATIVE_INFINITY,
+        Float.POSITIVE_INFINITY,
+        Float.NaN,
+        (float) -0.0,
+
+
+
+
+
+
+
+    };
+
     private static void relGet(FloatBuffer b) {
         int n = b.capacity();
         float v;
@@ -309,6 +329,12 @@
 
 
 
+    private static void fail(String problem,
+                             FloatBuffer xb, FloatBuffer yb,
+                             float x, float y) {
+        fail(problem + String.format(": x=%s y=%s", x, y), xb, yb);
+    }
+
     private static void tryCatch(Buffer b, Class ex, Runnable thunk) {
         boolean caught = false;
         try {
@@ -522,6 +548,42 @@
         if (b.compareTo(b2) <= 0)
             fail("Comparison to lesser buffer <= 0", b, b2);
 
+        // Check equals and compareTo with interesting values
+        for (float x : VALUES) {
+            FloatBuffer xb = FloatBuffer.wrap(new float[] { x });
+            if (xb.compareTo(xb) != 0) {
+                fail("compareTo not reflexive", xb, xb, x, x);
+            }
+            if (! xb.equals(xb)) {
+                fail("equals not reflexive", xb, xb, x, x);
+            }
+            for (float y : VALUES) {
+                FloatBuffer yb = FloatBuffer.wrap(new float[] { y });
+                if (xb.compareTo(yb) != - yb.compareTo(xb)) {
+                    fail("compareTo not anti-symmetric",
+                         xb, yb, x, y);
+                }
+                if ((xb.compareTo(yb) == 0) != xb.equals(yb)) {
+                    fail("compareTo inconsistent with equals",
+                         xb, yb, x, y);
+                }
+                if (xb.compareTo(yb) != Float.compare(x, y)) {
+
+                    if (x == 0.0 && y == 0.0) continue;
+
+
+
+
+                    fail("Incorrect results for FloatBuffer.compareTo",
+                         xb, yb, x, y);
+                }
+                if (xb.equals(yb) != ((x == y) || ((x != x) && (y != y)))) {
+                    fail("Incorrect results for FloatBuffer.equals",
+                         xb, yb, x, y);
+                }
+            }
+        }
+
         // Sub, dup
 
         relPut(b);
--- a/jdk/test/java/nio/Buffer/BasicInt.java	Thu Dec 17 14:10:20 2009 -0800
+++ b/jdk/test/java/nio/Buffer/BasicInt.java	Wed Jul 05 17:04:56 2017 +0200
@@ -38,6 +38,26 @@
     extends Basic
 {
 
+    private static final int[] VALUES = {
+        Integer.MIN_VALUE,
+        (int) -1,
+        (int) 0,
+        (int) 1,
+        Integer.MAX_VALUE,
+
+
+
+
+
+
+
+
+
+
+
+
+    };
+
     private static void relGet(IntBuffer b) {
         int n = b.capacity();
         int v;
@@ -309,6 +329,12 @@
 
 
 
+    private static void fail(String problem,
+                             IntBuffer xb, IntBuffer yb,
+                             int x, int y) {
+        fail(problem + String.format(": x=%s y=%s", x, y), xb, yb);
+    }
+
     private static void tryCatch(Buffer b, Class ex, Runnable thunk) {
         boolean caught = false;
         try {
@@ -522,6 +548,42 @@
         if (b.compareTo(b2) <= 0)
             fail("Comparison to lesser buffer <= 0", b, b2);
 
+        // Check equals and compareTo with interesting values
+        for (int x : VALUES) {
+            IntBuffer xb = IntBuffer.wrap(new int[] { x });
+            if (xb.compareTo(xb) != 0) {
+                fail("compareTo not reflexive", xb, xb, x, x);
+            }
+            if (! xb.equals(xb)) {
+                fail("equals not reflexive", xb, xb, x, x);
+            }
+            for (int y : VALUES) {
+                IntBuffer yb = IntBuffer.wrap(new int[] { y });
+                if (xb.compareTo(yb) != - yb.compareTo(xb)) {
+                    fail("compareTo not anti-symmetric",
+                         xb, yb, x, y);
+                }
+                if ((xb.compareTo(yb) == 0) != xb.equals(yb)) {
+                    fail("compareTo inconsistent with equals",
+                         xb, yb, x, y);
+                }
+                if (xb.compareTo(yb) != Integer.compare(x, y)) {
+
+
+
+
+
+
+                    fail("Incorrect results for IntBuffer.compareTo",
+                         xb, yb, x, y);
+                }
+                if (xb.equals(yb) != ((x == y) || ((x != x) && (y != y)))) {
+                    fail("Incorrect results for IntBuffer.equals",
+                         xb, yb, x, y);
+                }
+            }
+        }
+
         // Sub, dup
 
         relPut(b);
--- a/jdk/test/java/nio/Buffer/BasicLong.java	Thu Dec 17 14:10:20 2009 -0800
+++ b/jdk/test/java/nio/Buffer/BasicLong.java	Wed Jul 05 17:04:56 2017 +0200
@@ -38,6 +38,26 @@
     extends Basic
 {
 
+    private static final long[] VALUES = {
+        Long.MIN_VALUE,
+        (long) -1,
+        (long) 0,
+        (long) 1,
+        Long.MAX_VALUE,
+
+
+
+
+
+
+
+
+
+
+
+
+    };
+
     private static void relGet(LongBuffer b) {
         int n = b.capacity();
         long v;
@@ -309,6 +329,12 @@
 
 
 
+    private static void fail(String problem,
+                             LongBuffer xb, LongBuffer yb,
+                             long x, long y) {
+        fail(problem + String.format(": x=%s y=%s", x, y), xb, yb);
+    }
+
     private static void tryCatch(Buffer b, Class ex, Runnable thunk) {
         boolean caught = false;
         try {
@@ -522,6 +548,42 @@
         if (b.compareTo(b2) <= 0)
             fail("Comparison to lesser buffer <= 0", b, b2);
 
+        // Check equals and compareTo with interesting values
+        for (long x : VALUES) {
+            LongBuffer xb = LongBuffer.wrap(new long[] { x });
+            if (xb.compareTo(xb) != 0) {
+                fail("compareTo not reflexive", xb, xb, x, x);
+            }
+            if (! xb.equals(xb)) {
+                fail("equals not reflexive", xb, xb, x, x);
+            }
+            for (long y : VALUES) {
+                LongBuffer yb = LongBuffer.wrap(new long[] { y });
+                if (xb.compareTo(yb) != - yb.compareTo(xb)) {
+                    fail("compareTo not anti-symmetric",
+                         xb, yb, x, y);
+                }
+                if ((xb.compareTo(yb) == 0) != xb.equals(yb)) {
+                    fail("compareTo inconsistent with equals",
+                         xb, yb, x, y);
+                }
+                if (xb.compareTo(yb) != Long.compare(x, y)) {
+
+
+
+
+
+
+                    fail("Incorrect results for LongBuffer.compareTo",
+                         xb, yb, x, y);
+                }
+                if (xb.equals(yb) != ((x == y) || ((x != x) && (y != y)))) {
+                    fail("Incorrect results for LongBuffer.equals",
+                         xb, yb, x, y);
+                }
+            }
+        }
+
         // Sub, dup
 
         relPut(b);
--- a/jdk/test/java/nio/Buffer/BasicShort.java	Thu Dec 17 14:10:20 2009 -0800
+++ b/jdk/test/java/nio/Buffer/BasicShort.java	Wed Jul 05 17:04:56 2017 +0200
@@ -38,6 +38,26 @@
     extends Basic
 {
 
+    private static final short[] VALUES = {
+        Short.MIN_VALUE,
+        (short) -1,
+        (short) 0,
+        (short) 1,
+        Short.MAX_VALUE,
+
+
+
+
+
+
+
+
+
+
+
+
+    };
+
     private static void relGet(ShortBuffer b) {
         int n = b.capacity();
         short v;
@@ -309,6 +329,12 @@
 
 
 
+    private static void fail(String problem,
+                             ShortBuffer xb, ShortBuffer yb,
+                             short x, short y) {
+        fail(problem + String.format(": x=%s y=%s", x, y), xb, yb);
+    }
+
     private static void tryCatch(Buffer b, Class ex, Runnable thunk) {
         boolean caught = false;
         try {
@@ -522,6 +548,42 @@
         if (b.compareTo(b2) <= 0)
             fail("Comparison to lesser buffer <= 0", b, b2);
 
+        // Check equals and compareTo with interesting values
+        for (short x : VALUES) {
+            ShortBuffer xb = ShortBuffer.wrap(new short[] { x });
+            if (xb.compareTo(xb) != 0) {
+                fail("compareTo not reflexive", xb, xb, x, x);
+            }
+            if (! xb.equals(xb)) {
+                fail("equals not reflexive", xb, xb, x, x);
+            }
+            for (short y : VALUES) {
+                ShortBuffer yb = ShortBuffer.wrap(new short[] { y });
+                if (xb.compareTo(yb) != - yb.compareTo(xb)) {
+                    fail("compareTo not anti-symmetric",
+                         xb, yb, x, y);
+                }
+                if ((xb.compareTo(yb) == 0) != xb.equals(yb)) {
+                    fail("compareTo inconsistent with equals",
+                         xb, yb, x, y);
+                }
+                if (xb.compareTo(yb) != Short.compare(x, y)) {
+
+
+
+
+
+
+                    fail("Incorrect results for ShortBuffer.compareTo",
+                         xb, yb, x, y);
+                }
+                if (xb.equals(yb) != ((x == y) || ((x != x) && (y != y)))) {
+                    fail("Incorrect results for ShortBuffer.equals",
+                         xb, yb, x, y);
+                }
+            }
+        }
+
         // Sub, dup
 
         relPut(b);
--- a/jdk/test/java/nio/Buffer/genBasic.sh	Thu Dec 17 14:10:20 2009 -0800
+++ b/jdk/test/java/nio/Buffer/genBasic.sh	Wed Jul 05 17:04:56 2017 +0200
@@ -36,5 +36,3 @@
 gen long Long Long
 gen float Float Float
 gen double Double Double
-
-rm -rf build
--- a/jdk/test/java/util/concurrent/BlockingQueue/CancelledProducerConsumerLoops.java	Thu Dec 17 14:10:20 2009 -0800
+++ b/jdk/test/java/util/concurrent/BlockingQueue/CancelledProducerConsumerLoops.java	Wed Jul 05 17:04:56 2017 +0200
@@ -146,13 +146,13 @@
         oneRun(new ArrayBlockingQueue<Integer>(CAPACITY), pairs, iters);
         oneRun(new LinkedBlockingQueue<Integer>(CAPACITY), pairs, iters);
         oneRun(new LinkedBlockingDeque<Integer>(CAPACITY), pairs, iters);
+        oneRun(new SynchronousQueue<Integer>(), pairs, iters / 8);
+
+        /* TODO: unbounded queue implementations are prone to OOME
+        oneRun(new PriorityBlockingQueue<Integer>(iters / 2 * pairs), pairs, iters / 4);
         oneRun(new LinkedTransferQueue<Integer>(), pairs, iters);
         oneRun(new LTQasSQ<Integer>(), pairs, iters);
         oneRun(new HalfSyncLTQ<Integer>(), pairs, iters);
-        oneRun(new SynchronousQueue<Integer>(), pairs, iters / 8);
-
-        /* PriorityBlockingQueue is unbounded
-        oneRun(new PriorityBlockingQueue<Integer>(iters / 2 * pairs), pairs, iters / 4);
         */
     }
 
--- a/jdk/test/java/util/jar/JarFile/TurkCert.java	Thu Dec 17 14:10:20 2009 -0800
+++ b/jdk/test/java/util/jar/JarFile/TurkCert.java	Wed Jul 05 17:04:56 2017 +0200
@@ -26,6 +26,7 @@
  * @bug 4624534
  * @summary Make sure jar certificates work for Turkish locale
  * @author kladko
+ * @run main/othervm TurkCert
  */
 
 import java.util.*;
--- a/jdk/test/javax/xml/crypto/dsig/GenerationTests.java	Thu Dec 17 14:10:20 2009 -0800
+++ b/jdk/test/javax/xml/crypto/dsig/GenerationTests.java	Wed Jul 05 17:04:56 2017 +0200
@@ -23,7 +23,7 @@
 
 /**
  * @test
- * @bug 4635230 6283345 6303830 6824440
+ * @bug 4635230 6283345 6303830 6824440 6867348
  * @summary Basic unit tests for generating XML Signatures with JSR 105
  * @compile -XDignore.symbol.file KeySelectors.java SignatureValidator.java
  *     X509KeySelector.java GenerationTests.java
@@ -126,13 +126,14 @@
         test_create_signature_x509_is();
         test_create_signature_x509_ski();
         test_create_signature_x509_sn();
-//      test_create_signature();
+        test_create_signature();
         test_create_exc_signature();
         test_create_sign_spec();
         test_create_signature_enveloping_sha256_dsa();
         test_create_signature_enveloping_sha384_rsa_sha256();
         test_create_signature_enveloping_sha512_rsa_sha384();
         test_create_signature_enveloping_sha512_rsa_sha512();
+        test_create_signature_reference_dependency();
     }
 
     private static void setup() throws Exception {
@@ -410,6 +411,55 @@
         System.out.println();
     }
 
+    static void test_create_signature_reference_dependency() throws Exception {
+        System.out.println("* Generating signature-reference-dependency.xml");
+        // create references
+        List<Reference> refs = Collections.singletonList
+            (fac.newReference("#object-1", sha1));
+
+        // create SignedInfo
+        SignedInfo si = fac.newSignedInfo(withoutComments, rsaSha1, refs);
+
+        // create objects
+        List<XMLStructure> objs = new ArrayList<XMLStructure>();
+
+        // Object 1
+        List<Reference> manRefs = Collections.singletonList
+            (fac.newReference("#object-2", sha1));
+        objs.add(fac.newXMLObject(Collections.singletonList
+            (fac.newManifest(manRefs, "manifest-1")), "object-1", null, null));
+
+        // Object 2
+        Document doc = db.newDocument();
+        Element nc = doc.createElementNS(null, "NonCommentandus");
+        nc.setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns", "");
+        nc.appendChild(doc.createComment(" Commentandum "));
+        objs.add(fac.newXMLObject(Collections.singletonList
+            (new DOMStructure(nc)), "object-2", null, null));
+
+        // create XMLSignature
+        XMLSignature sig = fac.newXMLSignature(si, rsa, objs, "signature", null);
+        DOMSignContext dsc = new DOMSignContext(getPrivateKey("RSA"), doc);
+
+        sig.sign(dsc);
+
+//      dumpDocument(doc, new PrintWriter(System.out));
+
+        DOMValidateContext dvc = new DOMValidateContext
+            (kvks, doc.getDocumentElement());
+        XMLSignature sig2 = fac.unmarshalXMLSignature(dvc);
+
+        if (sig.equals(sig2) == false) {
+            throw new Exception
+                ("Unmarshalled signature is not equal to generated signature");
+        }
+        if (sig2.validate(dvc) == false) {
+            throw new Exception("Validation of generated signature failed");
+        }
+
+        System.out.println();
+    }
+
     static void test_create_signature() throws Exception {
         System.out.println("* Generating signature.xml");
 
@@ -645,6 +695,7 @@
             envDoc.getElementsByTagName("YoursSincerely").item(0);
 
         DOMSignContext dsc = new DOMSignContext(signingKey, ys);
+        dsc.setURIDereferencer(httpUd);
 
         sig.sign(dsc);
 
@@ -660,6 +711,7 @@
 
         DOMValidateContext dvc = new DOMValidateContext
             (new X509KeySelector(ks), sigElement);
+        dvc.setURIDereferencer(httpUd);
         File f = new File(
             System.getProperty("dir.test.vector.baltimore") +
             System.getProperty("file.separator") +
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/krb5/auto/BadKdc.java	Wed Jul 05 17:04:56 2017 +0200
@@ -0,0 +1,113 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+import java.io.*;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import sun.security.krb5.Config;
+
+public class BadKdc {
+
+    // Matches the krb5 debug output:
+    // >>> KDCCommunication: kdc=kdc.rabbit.hole UDP:14319, timeout=2000,...
+    //                                               ^ kdc#         ^ timeout
+    static final Pattern re = Pattern.compile(
+            ">>> KDCCommunication: kdc=kdc.rabbit.hole UDP:(\\d)...., " +
+            "timeout=(\\d)000,");
+    public static void go(int[]... expected)
+            throws Exception {
+        System.setProperty("sun.security.krb5.debug", "true");
+
+        // Make sure KDCs' ports starts with 1 and 2 and 3,
+        // useful for checking debug output.
+        int p1 = 10000 + new java.util.Random().nextInt(10000);
+        int p2 = 20000 + new java.util.Random().nextInt(10000);
+        int p3 = 30000 + new java.util.Random().nextInt(10000);
+
+        FileWriter fw = new FileWriter("alternative-krb5.conf");
+
+        fw.write("[libdefaults]\n" +
+                "default_realm = " + OneKDC.REALM + "\n" +
+                "kdc_timeout = 2000\n");
+        fw.write("[realms]\n" + OneKDC.REALM + " = {\n" +
+                "kdc = " + OneKDC.KDCHOST + ":" + p1 + "\n" +
+                "kdc = " + OneKDC.KDCHOST + ":" + p2 + "\n" +
+                "kdc = " + OneKDC.KDCHOST + ":" + p3 + "\n" +
+                "}\n");
+
+        fw.close();
+        System.setProperty("java.security.krb5.conf", "alternative-krb5.conf");
+        Config.refresh();
+
+        // Turn on k3 only
+        KDC k3 = on(p3);
+
+        test(expected[0]);
+        test(expected[1]);
+        Config.refresh();
+        test(expected[2]);
+
+        k3.terminate(); // shutdown k3
+        on(p2);         // k2 is on
+        test(expected[3]);
+        on(p1);         // k1 and k2 is on
+        test(expected[4]);
+    }
+
+    private static KDC on(int p) throws Exception {
+        KDC k = new KDC(OneKDC.REALM, OneKDC.KDCHOST, p, true);
+        k.addPrincipal(OneKDC.USER, OneKDC.PASS);
+        k.addPrincipalRandKey("krbtgt/" + OneKDC.REALM);
+        return k;
+    }
+
+    /**
+     * One round of test for max_retries and timeout.
+     * @param timeout the expected timeout
+     * @param expected the expected kdc# timeout kdc# timeout...
+     */
+    private static void test(int... expected) throws Exception {
+        ByteArrayOutputStream bo = new ByteArrayOutputStream();
+        PrintStream oldout = System.out;
+        System.setOut(new PrintStream(bo));
+        Context c = Context.fromUserPass(OneKDC.USER, OneKDC.PASS, false);
+        System.setOut(oldout);
+
+        String[] lines = new String(bo.toByteArray()).split("\n");
+        System.out.println("----------------- TEST -----------------");
+        int count = 0;
+        for (String line: lines) {
+            Matcher m = re.matcher(line);
+            if (m.find()) {
+                System.out.println(line);
+                if (Integer.parseInt(m.group(1)) != expected[count++] ||
+                        Integer.parseInt(m.group(2)) != expected[count++]) {
+                    throw new Exception("Fail here");
+                }
+            }
+        }
+        if (count != expected.length) {
+            throw new Exception("Less rounds");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/krb5/auto/BadKdc1.java	Wed Jul 05 17:04:56 2017 +0200
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6843127
+ * @run main/timeout=300 BadKdc1
+ * @summary krb5 should not try to access unavailable kdc too often
+ */
+
+import java.io.*;
+import java.security.Security;
+
+public class BadKdc1 {
+
+   public static void main(String[] args)
+           throws Exception {
+       Security.setProperty("krb5.kdc.bad.policy", "tryLess");
+       BadKdc.go(
+               new int[]{1,2,1,2,1,2,2,2,2,2,2,2,3,2,1,2,2,2,3,2}, // 1, 2
+               // The above line means try kdc1 for 2 seconds, then kdc1
+               // for 2 seconds,..., finally kdc3 for 2 seconds.
+               new int[]{1,2,2,2,3,2,1,2,2,2,3,2}, // 1, 2
+               // refresh
+               new int[]{1,2,1,2,1,2,2,2,2,2,2,2,3,2,1,2,2,2,3,2}, // 1, 2
+               // k3 off, k2 on
+               new int[]{1,2,2,2,1,2,2,2}, // 1
+               // k1 on
+               new int[]{1,2,1,2}  // empty
+       );
+   }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/krb5/auto/BadKdc2.java	Wed Jul 05 17:04:56 2017 +0200
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6843127
+ * @run main/timeout=300 BadKdc2
+ * @summary krb5 should not try to access unavailable kdc too often
+ */
+
+import java.io.*;
+import java.security.Security;
+
+public class BadKdc2 {
+
+    public static void main(String[] args)
+            throws Exception {
+        Security.setProperty("krb5.kdc.bad.policy", "tryLess:2,1000");
+        BadKdc.go(
+                new int[]{1,2,1,2,1,2,2,2,2,2,2,2,3,2,1,1,1,1,2,1,2,1,3,2}, // 1, 2
+                new int[]{1,1,1,1,2,1,2,1,3,2,1,1,1,1,2,1,2,1,3,2}, // 1, 2
+                // refresh
+                new int[]{1,2,1,2,1,2,2,2,2,2,2,2,3,2,1,1,1,1,2,1,2,1,3,2}, // 1, 2
+                // k3 off, k2 on
+                new int[]{1,1,1,1,2,1,1,1,1,1,2,2}, // 1
+                // k1 on
+                new int[]{1,1,1,2}  // empty
+        );
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/krb5/auto/BadKdc3.java	Wed Jul 05 17:04:56 2017 +0200
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6843127
+ * @run main/timeout=300 BadKdc3
+ * @summary krb5 should not try to access unavailable kdc too often
+ */
+
+import java.io.*;
+import java.security.Security;
+
+public class BadKdc3 {
+
+    public static void main(String[] args)
+            throws Exception {
+        Security.setProperty("krb5.kdc.bad.policy", "tryLast");
+        BadKdc.go(
+                new int[]{1,2,1,2,1,2,2,2,2,2,2,2,3,2,3,2}, // 1, 2
+                new int[]{3,2,3,2}, // 1, 2
+                // refresh
+                new int[]{1,2,1,2,1,2,2,2,2,2,2,2,3,2,3,2}, // 1, 2
+                // k3 off, k2 on
+                new int[]{3,2,3,2,3,2,1,2,1,2,1,2,2,2,2,2}, // 1, 3
+                // k1 on
+                new int[]{2,2,2,2}  // 1, 3
+        );
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/krb5/auto/BadKdc4.java	Wed Jul 05 17:04:56 2017 +0200
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6843127
+ * @run main/timeout=300 BadKdc4
+ * @summary krb5 should not try to access unavailable kdc too often
+ */
+
+import java.io.*;
+import java.security.Security;
+
+public class BadKdc4 {
+
+    public static void main(String[] args)
+            throws Exception {
+        Security.setProperty("krb5.kdc.bad.policy", "");
+        BadKdc.go(
+            new int[]{1,2,1,2,1,2,2,2,2,2,2,2,3,2,1,2,1,2,1,2,2,2,2,2,2,2,3,2},
+            new int[]{1,2,1,2,1,2,2,2,2,2,2,2,3,2,1,2,1,2,1,2,2,2,2,2,2,2,3,2},
+            // refresh
+            new int[]{1,2,1,2,1,2,2,2,2,2,2,2,3,2,1,2,1,2,1,2,2,2,2,2,2,2,3,2},
+            // k3 off, k2 on
+            new int[]{1,2,1,2,1,2,2,2,1,2,1,2,1,2,2,2},
+            // k1 on
+            new int[]{1,2,1,2}
+        );
+    }
+}
--- a/jdk/test/sun/security/krb5/auto/KDC.java	Thu Dec 17 14:10:20 2009 -0800
+++ b/jdk/test/sun/security/krb5/auto/KDC.java	Wed Jul 05 17:04:56 2017 +0200
@@ -141,6 +141,10 @@
     // Options
     private Map<Option,Object> options = new HashMap<Option,Object>();
 
+    private Thread thread1, thread2, thread3;
+    DatagramSocket u1 = null;
+    ServerSocket t1 = null;
+
     /**
      * Option names, to be expanded forever.
      */
@@ -480,8 +484,9 @@
             Method stringToKey = EncryptionKey.class.getDeclaredMethod("stringToKey", char[].class, String.class, byte[].class, Integer.TYPE);
             stringToKey.setAccessible(true);
             Integer kvno = null;
-            // For service whose password ending with a number, use it as kvno
-            if (p.toString().indexOf('/') >= 0) {
+            // For service whose password ending with a number, use it as kvno.
+            // Kvno must be postive.
+            if (p.toString().indexOf('/') > 0) {
                 char[] pass = getPassword(p, server);
                 if (Character.isDigit(pass[pass.length-1])) {
                     kvno = pass[pass.length-1] - '0';
@@ -940,8 +945,6 @@
      * @throws java.io.IOException for any communication error
      */
     protected void startServer(int port, boolean asDaemon) throws IOException {
-        DatagramSocket u1 = null;
-        ServerSocket t1 = null;
         if (port > 0) {
             u1 = new DatagramSocket(port, InetAddress.getByName("127.0.0.1"));
             t1 = new ServerSocket(port);
@@ -966,7 +969,7 @@
         this.port = port;
 
         // The UDP consumer
-        Thread thread = new Thread() {
+        thread1 = new Thread() {
             public void run() {
                 while (true) {
                     try {
@@ -982,11 +985,11 @@
                 }
             }
         };
-        thread.setDaemon(asDaemon);
-        thread.start();
+        thread1.setDaemon(asDaemon);
+        thread1.start();
 
         // The TCP consumer
-        thread = new Thread() {
+        thread2 = new Thread() {
             public void run() {
                 while (true) {
                     try {
@@ -1004,11 +1007,11 @@
                 }
             }
         };
-        thread.setDaemon(asDaemon);
-        thread.start();
+        thread2.setDaemon(asDaemon);
+        thread2.start();
 
         // The dispatcher
-        thread = new Thread() {
+        thread3 = new Thread() {
             public void run() {
                 while (true) {
                     try {
@@ -1018,10 +1021,21 @@
                 }
             }
         };
-        thread.setDaemon(true);
-        thread.start();
+        thread3.setDaemon(true);
+        thread3.start();
     }
 
+    public void terminate() {
+        try {
+            thread1.stop();
+            thread2.stop();
+            thread3.stop();
+            u1.close();
+            t1.close();
+        } catch (Exception e) {
+            // OK
+        }
+    }
     /**
      * Helper class to encapsulate a job in a KDC.
      */
--- a/jdk/test/sun/security/krb5/auto/MoreKvno.java	Thu Dec 17 14:10:20 2009 -0800
+++ b/jdk/test/sun/security/krb5/auto/MoreKvno.java	Wed Jul 05 17:04:56 2017 +0200
@@ -24,15 +24,20 @@
 /*
  * @test
  * @bug 6893158
+ * @bug 6907425
  * @summary AP_REQ check should use key version number
  */
 
+import org.ietf.jgss.GSSException;
 import sun.security.jgss.GSSUtil;
+import sun.security.krb5.KrbException;
 import sun.security.krb5.PrincipalName;
 import sun.security.krb5.internal.ktab.KeyTab;
+import sun.security.krb5.internal.Krb5;
 
 public class MoreKvno {
 
+    static PrincipalName p;
     public static void main(String[] args)
             throws Exception {
 
@@ -41,21 +46,40 @@
 
         // Rewrite keytab, 3 set of keys with different kvno
         KeyTab ktab = KeyTab.create(OneKDC.KTAB);
-        PrincipalName p = new PrincipalName(OneKDC.SERVER+"@"+OneKDC.REALM, PrincipalName.KRB_NT_SRV_HST);
-        ktab.addEntry(p, "pass0".toCharArray(), 0);
+        p = new PrincipalName(
+            OneKDC.SERVER+"@"+OneKDC.REALM, PrincipalName.KRB_NT_SRV_HST);
+        ktab.addEntry(p, "pass1".toCharArray(), 1);
+        ktab.addEntry(p, "pass3".toCharArray(), 3);
         ktab.addEntry(p, "pass2".toCharArray(), 2);
-        ktab.addEntry(p, "pass1".toCharArray(), 1);
         ktab.save();
 
-        kdc.addPrincipal(OneKDC.SERVER, "pass1".toCharArray());
-        go(OneKDC.SERVER, "com.sun.security.jgss.krb5.accept");
-        kdc.addPrincipal(OneKDC.SERVER, "pass2".toCharArray());
+        char[] pass = "pass2".toCharArray();
+        kdc.addPrincipal(OneKDC.SERVER, pass);
+        go(OneKDC.SERVER, "com.sun.security.jgss.krb5.accept", pass);
+
+        pass = "pass3".toCharArray();
+        kdc.addPrincipal(OneKDC.SERVER, pass);
         // "server" initiate also, check pass2 is used at authentication
-        go(OneKDC.SERVER, "server");
+        go(OneKDC.SERVER, "server", pass);
+
+        try {
+            pass = "pass4".toCharArray();
+            kdc.addPrincipal(OneKDC.SERVER, pass);
+            go(OneKDC.SERVER, "com.sun.security.jgss.krb5.accept", pass);
+            throw new Exception("This test should fail");
+        } catch (GSSException gsse) {
+            KrbException ke = (KrbException)gsse.getCause();
+            if (ke.returnCode() != Krb5.KRB_AP_ERR_BADKEYVER) {
+                throw new Exception("Not expected failure code: " +
+                        ke.returnCode());
+            }
+        }
     }
 
-    static void go(String server, String entry) throws Exception {
+    static void go(String server, String entry, char[] pass) throws Exception {
         Context c, s;
+
+        // Part 1: Test keytab
         c = Context.fromUserPass("dummy", "bogus".toCharArray(), false);
         s = Context.fromJAAS(entry);
 
@@ -66,5 +90,17 @@
 
         s.dispose();
         c.dispose();
+
+        // Part 2: Test username/password pair
+        c = Context.fromUserPass("dummy", "bogus".toCharArray(), false);
+        s = Context.fromUserPass(p.getNameString(), pass, true);
+
+        c.startAsClient(server, GSSUtil.GSS_KRB5_MECH_OID);
+        s.startAsServer(GSSUtil.GSS_KRB5_MECH_OID);
+
+        Context.handshake(c, s);
+
+        s.dispose();
+        c.dispose();
     }
 }
--- a/jdk/test/sun/security/krb5/auto/OneKDC.java	Thu Dec 17 14:10:20 2009 -0800
+++ b/jdk/test/sun/security/krb5/auto/OneKDC.java	Wed Jul 05 17:04:56 2017 +0200
@@ -24,8 +24,6 @@
 import java.io.File;
 import java.io.FileOutputStream;
 import java.io.IOException;
-import java.net.InetAddress;
-import java.net.UnknownHostException;
 import java.security.Security;
 import javax.security.auth.callback.Callback;
 import javax.security.auth.callback.CallbackHandler;
--- a/jdk/test/sun/security/krb5/auto/SSL.java	Thu Dec 17 14:10:20 2009 -0800
+++ b/jdk/test/sun/security/krb5/auto/SSL.java	Wed Jul 05 17:04:56 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2009-2010 Sun Microsystems, Inc.  All Rights Reserved.
  * 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 6894643
+ * @bug 6894643 6913636
  * @summary Test JSSE Kerberos ciphersuite
  */
 import java.io.*;
@@ -32,12 +32,13 @@
 import java.security.Principal;
 import java.util.Date;
 import sun.security.jgss.GSSUtil;
+import sun.security.krb5.PrincipalName;
+import sun.security.krb5.internal.ktab.KeyTab;
 
 public class SSL {
 
     private static final String KRB5_CIPHER = "TLS_KRB5_WITH_3DES_EDE_CBC_SHA";
     private static final int LOOP_LIMIT = 1;
-    private static final char[] PASS = "secret".toCharArray();
     private static int loopCount = 0;
     private static volatile String server;
     private static volatile int port;
@@ -54,12 +55,39 @@
 
         kdc.addPrincipal(OneKDC.USER, OneKDC.PASS);
         kdc.addPrincipalRandKey("krbtgt/" + OneKDC.REALM);
-        kdc.addPrincipal("host/" + server, PASS);
         KDC.saveConfig(OneKDC.KRB5_CONF, kdc);
         System.setProperty("java.security.krb5.conf", OneKDC.KRB5_CONF);
 
+        // Add 3 versions of keys into keytab
+        KeyTab ktab = KeyTab.create(OneKDC.KTAB);
+        PrincipalName service = new PrincipalName(
+                "host/" + server, PrincipalName.KRB_NT_SRV_HST);
+        ktab.addEntry(service, "pass1".toCharArray(), 1);
+        ktab.addEntry(service, "pass2".toCharArray(), 2);
+        ktab.addEntry(service, "pass3".toCharArray(), 3);
+        ktab.save();
+
+        // and use the middle one as the real key
+        kdc.addPrincipal("host/" + server, "pass2".toCharArray());
+
+        // JAAS config entry name ssl
+        System.setProperty("java.security.auth.login.config", OneKDC.JAAS_CONF);
+        File f = new File(OneKDC.JAAS_CONF);
+        FileOutputStream fos = new FileOutputStream(f);
+        fos.write((
+                "ssl {\n" +
+                "    com.sun.security.auth.module.Krb5LoginModule required\n" +
+                "    principal=\"host/" + server + "\"\n" +
+                "    useKeyTab=true\n" +
+                "    keyTab=" + OneKDC.KTAB + "\n" +
+                "    isInitiator=false\n" +
+                "    storeKey=true;\n};\n"
+                ).getBytes());
+        fos.close();
+        f.deleteOnExit();
+
         final Context c = Context.fromUserPass(OneKDC.USER, OneKDC.PASS, false);
-        final Context s = Context.fromUserPass("host/" + server, PASS, true);
+        final Context s = Context.fromJAAS("ssl");
 
         c.startAsClient("host/" + server, GSSUtil.GSS_KRB5_MECH_OID);
         s.startAsServer(GSSUtil.GSS_KRB5_MECH_OID);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/krb5/auto/Test5653.java	Wed Jul 05 17:04:56 2017 +0200
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2010 Sun Microsystems, Inc.  All Rights Reserved.
+ * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6895424
+ * @summary RFC 5653
+ */
+
+import org.ietf.jgss.GSSContext;
+import org.ietf.jgss.GSSManager;
+import org.ietf.jgss.GSSName;
+import org.ietf.jgss.Oid;
+import sun.security.jgss.GSSUtil;
+
+public class Test5653 {
+
+    public static void main(String[] args)
+            throws Exception {
+
+        Oid oldOid = new Oid("1.3.6.1.5.6.2");
+        new OneKDC(null).writeJAASConf();
+
+        System.setProperty("javax.security.auth.useSubjectCredsOnly", "false");
+        GSSManager m = GSSManager.getInstance();
+        boolean found = false;
+
+        // Test 1: the getMechsForName() method accepts it.
+        for (Oid tmp: m.getMechsForName(oldOid)) {
+            if (tmp.equals(GSSUtil.GSS_KRB5_MECH_OID)) {
+                found = true;
+                break;
+            }
+        }
+        if (!found) {
+            throw new Exception("Cannot found krb5 mech for old name type");
+        }
+
+        // Test 2: the createName() method accepts it.
+        GSSName name = m.createName("server@host.rabbit.hole", oldOid);
+
+        // Test 3: its getStringNameType() output is correct
+        if (!name.getStringNameType().equals(GSSName.NT_HOSTBASED_SERVICE)) {
+            throw new Exception("GSSName not correct name type");
+        }
+
+        // Test 4: everything still works.
+        GSSContext c1 = m.createContext(
+                name,
+                GSSUtil.GSS_KRB5_MECH_OID,
+                null,
+                GSSContext.DEFAULT_LIFETIME);
+        byte[] token = c1.initSecContext(new byte[0], 0, 0);
+
+        Context s;
+        s = Context.fromJAAS("server");
+        s.startAsServer(GSSUtil.GSS_KRB5_MECH_OID);
+        s.x().acceptSecContext(token, 0, token.length);
+    }
+}
--- a/jdk/test/sun/security/util/Oid/S11N.sh	Thu Dec 17 14:10:20 2009 -0800
+++ b/jdk/test/sun/security/util/Oid/S11N.sh	Wed Jul 05 17:04:56 2017 +0200
@@ -1,5 +1,5 @@
 #
-# Copyright 2004-2005 Sun Microsystems, Inc.  All Rights Reserved.
+# Copyright 2004-2009 Sun Microsystems, Inc.  All Rights Reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
@@ -21,8 +21,8 @@
 # have any questions.
 #
 # @test
-# @bug 4811968
-# @summary Serialization compatibility with old versions
+# @bug 4811968 6908628
+# @summary Serialization compatibility with old versions (and fix)
 # @author Weijun Wang
 #
 # set a few environment variables so that the shell-script can run stand-alone
@@ -99,7 +99,8 @@
 
 # the test code
 
-${TESTJAVA}${FS}bin${FS}javac -d . ${TESTSRC}${FS}SerialTest.java || exit 10
+${TESTJAVA}${FS}bin${FS}javac -target 1.4 -source 1.4 \
+        -d . ${TESTSRC}${FS}SerialTest.java || exit 10
 
 OLDJAVA="
     /java/re/j2se/1.6.0/latest/binaries/${PF}
@@ -161,4 +162,10 @@
 rm -f tmp.oid.serial.old
 rm -f SerialTest.class
 
+for oldj in ${OLDJAVA}; do
+    if [ ! -d ${oldj} ]; then
+        echo WARNING: ${oldj} is missing. Test incomplete! > /dev/stderr
+    fi
+done
+
 exit 0
--- a/jdk/test/sun/tools/jhat/HatRun.java	Thu Dec 17 14:10:20 2009 -0800
+++ b/jdk/test/sun/tools/jhat/HatRun.java	Wed Jul 05 17:04:56 2017 +0200
@@ -166,8 +166,10 @@
                             jre_home );
         String cdir      = System.getProperty("test.classes", ".");
         String os_arch   = System.getProperty("os.arch");
-        boolean d64      = os_arch.equals("sparcv9") ||
-                           os_arch.equals("amd64");
+        String os_name   = System.getProperty("os.name");
+        boolean d64      = os_name.equals("SunOS") && (
+                             os_arch.equals("sparcv9") ||
+                             os_arch.equals("amd64"));
         String isa_dir   = d64?(File.separator+os_arch):"";
         String java      = jre_home
                              + File.separator + "bin" + isa_dir