Merge
authorlana
Fri, 15 Jan 2010 15:36:54 -0800
changeset 4676 4cdcce877ba7
parent 4675 68f287672813 (current diff)
parent 4595 84bc8a58537f (diff)
child 4677 1b6ce3fbc01b
Merge
jdk/src/share/classes/sun/dyn/util/BytecodeSignature.java
langtools/src/share/classes/com/sun/tools/javac/file/CloseableURLClassLoader.java
--- a/.hgtags	Fri Jan 15 16:31:16 2010 +0000
+++ b/.hgtags	Fri Jan 15 15:36:54 2010 -0800
@@ -52,3 +52,4 @@
 946518568340c4e511549318f19f47f06b7f5f9b jdk7-b75
 09e0b33177af2b98a03c9ca19eedf61440bd1cf6 jdk7-b76
 1d0121b741f029dc4b828e4b36ba6fda92907dd7 jdk7-b77
+4061c66ba1af1a2e27c2c839ba887407dd3ce050 jdk7-b78
--- a/.hgtags-top-repo	Fri Jan 15 16:31:16 2010 +0000
+++ b/.hgtags-top-repo	Fri Jan 15 15:36:54 2010 -0800
@@ -52,3 +52,4 @@
 d1516b9f23954b29b8e76e6f4efc467c08c78133 jdk7-b75
 c8b63075403d53a208104a8a6ea5072c1cb66aab jdk7-b76
 1f17ca8353babb13f4908c1f87d11508232518c8 jdk7-b77
+ab4ae8f4514693a9fe17ca2fec0239d8f8450d2c jdk7-b78
--- a/corba/.hgtags	Fri Jan 15 16:31:16 2010 +0000
+++ b/corba/.hgtags	Fri Jan 15 15:36:54 2010 -0800
@@ -52,3 +52,4 @@
 0fb137085952c8e47878e240d1cb40f14de463c4 jdk7-b75
 937144222e2219939101b0129d26a872a7956b13 jdk7-b76
 6881f0383f623394b5ec73f27a5f329ff55d0467 jdk7-b77
+a7f7276b48cd74d8eb1baa83fbf3d1ef4a2603c8 jdk7-b78
--- a/hotspot/.hgtags	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/.hgtags	Fri Jan 15 15:36:54 2010 -0800
@@ -52,3 +52,4 @@
 d8dd291a362acb656026a9c0a9da48501505a1e7 jdk7-b75
 9174bb32e934965288121f75394874eeb1fcb649 jdk7-b76
 455105fc81d941482f8f8056afaa7aa0949c9300 jdk7-b77
+e703499b4b51e3af756ae77c3d5e8b3058a14e4e jdk7-b78
--- a/hotspot/make/hotspot_version	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/make/hotspot_version	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/make/linux/makefiles/debug.make	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/make/linux/makefiles/fastdebug.make	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/make/linux/makefiles/jsig.make	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/make/linux/makefiles/jvmg.make	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/make/linux/makefiles/launcher.make	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/make/linux/makefiles/saproc.make	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/make/linux/makefiles/vm.make	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/make/solaris/makefiles/debug.make	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/make/solaris/makefiles/dtrace.make	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/make/solaris/makefiles/fastdebug.make	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/make/solaris/makefiles/jsig.make	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/make/solaris/makefiles/jvmg.make	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/make/solaris/makefiles/launcher.make	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/make/solaris/makefiles/saproc.make	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/make/solaris/makefiles/sparcWorks.make	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/make/solaris/makefiles/vm.make	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/cpu/sparc/vm/c1_LIRGenerator_sparc.cpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/cpu/sparc/vm/c1_globals_sparc.hpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/cpu/sparc/vm/c2_globals_sparc.hpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/cpu/sparc/vm/globals_sparc.hpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/cpu/sparc/vm/templateInterpreter_sparc.cpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/cpu/x86/vm/assembler_x86.cpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/cpu/x86/vm/assembler_x86.hpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/cpu/x86/vm/c1_LIRGenerator_x86.cpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/cpu/x86/vm/c1_globals_x86.hpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/cpu/x86/vm/c2_globals_x86.hpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/cpu/x86/vm/globals_x86.hpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/cpu/x86/vm/interp_masm_x86_32.cpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/cpu/x86/vm/interp_masm_x86_64.cpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/cpu/x86/vm/interp_masm_x86_64.hpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/cpu/x86/vm/interpreter_x86_64.cpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/cpu/x86/vm/methodHandles_x86.cpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/cpu/x86/vm/templateInterpreter_x86_32.cpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/cpu/x86/vm/templateInterpreter_x86_64.cpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/cpu/x86/vm/templateTable_x86_32.cpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/cpu/x86/vm/templateTable_x86_64.cpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/cpu/x86/vm/templateTable_x86_64.hpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/cpu/x86/vm/vm_version_x86.cpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/cpu/zero/vm/cppInterpreter_zero.cpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/cpu/zero/vm/frame_zero.cpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/cpu/zero/vm/frame_zero.hpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/cpu/zero/vm/globals_zero.hpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/cpu/zero/vm/sharedRuntime_zero.cpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/cpu/zero/vm/sharkFrame_zero.hpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/os/linux/vm/os_linux.cpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/os/solaris/dtrace/libjvm_db.c	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/os/solaris/vm/os_solaris.cpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/os/windows/vm/os_windows.cpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/os_cpu/linux_x86/vm/globals_linux_x86.hpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/os_cpu/solaris_x86/vm/globals_solaris_x86.hpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/os_cpu/windows_x86/vm/globals_windows_x86.hpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/share/vm/c1/c1_LinearScan.cpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/share/vm/ci/bcEscapeAnalyzer.hpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/share/vm/ci/ciEnv.cpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/share/vm/ci/ciEnv.hpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/share/vm/ci/ciInstanceKlass.cpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/share/vm/ci/ciInstanceKlass.hpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/share/vm/ci/ciObjectFactory.cpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/share/vm/classfile/classFileParser.cpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/share/vm/classfile/javaClasses.cpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/share/vm/classfile/javaClasses.hpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/share/vm/classfile/systemDictionary.cpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/share/vm/classfile/systemDictionary.hpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/share/vm/classfile/verifier.cpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/share/vm/classfile/vmSymbols.cpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/share/vm/classfile/vmSymbols.hpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/share/vm/code/dependencies.cpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/share/vm/code/dependencies.hpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/share/vm/code/nmethod.cpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/share/vm/code/nmethod.hpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/share/vm/gc_implementation/g1/collectionSetChooser.cpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentG1Refine.cpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentG1Refine.hpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentG1RefineThread.cpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentG1RefineThread.hpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/share/vm/gc_implementation/g1/dirtyCardQueue.cpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/share/vm/gc_implementation/g1/dirtyCardQueue.hpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1MMUTracker.cpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1MMUTracker.hpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1_globals.hpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/share/vm/gc_implementation/g1/ptrQueue.cpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/share/vm/gc_implementation/g1/ptrQueue.hpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/share/vm/gc_implementation/g1/satbQueue.cpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/share/vm/gc_implementation/g1/satbQueue.hpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/share/vm/gc_implementation/g1/vm_operations_g1.cpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/share/vm/gc_implementation/g1/vm_operations_g1.hpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/share/vm/gc_implementation/includeDB_gc_g1	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psGCAdaptivePolicyCounters.cpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/share/vm/includeDB_compiler2	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/share/vm/includeDB_core	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/share/vm/interpreter/bytecodeTracer.cpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/share/vm/interpreter/interpreter.cpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/share/vm/interpreter/interpreterRuntime.hpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/share/vm/interpreter/linkResolver.cpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/share/vm/interpreter/rewriter.cpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/share/vm/interpreter/rewriter.hpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/share/vm/interpreter/templateInterpreter.cpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/share/vm/interpreter/templateInterpreter.hpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/share/vm/interpreter/templateInterpreterGenerator.hpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/share/vm/memory/barrierSet.cpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/share/vm/memory/barrierSet.hpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/share/vm/memory/barrierSet.inline.hpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/share/vm/memory/cardTableModRefBS.cpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/share/vm/memory/collectorPolicy.cpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/share/vm/memory/heap.cpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/share/vm/memory/referenceProcessor.cpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/share/vm/memory/sharedHeap.hpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/share/vm/memory/universe.cpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/share/vm/memory/universe.hpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/share/vm/oops/constantPoolOop.cpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/share/vm/oops/constantPoolOop.hpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/share/vm/oops/cpCacheOop.cpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/share/vm/oops/cpCacheOop.hpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/share/vm/oops/generateOopMap.cpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/share/vm/oops/instanceKlass.cpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/share/vm/oops/instanceKlass.hpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/share/vm/oops/instanceKlassKlass.cpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/share/vm/oops/instanceRefKlass.cpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/share/vm/oops/objArrayKlass.cpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/share/vm/oops/objArrayOop.hpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/share/vm/oops/oop.hpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/share/vm/opto/c2_globals.cpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/share/vm/opto/c2_globals.hpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/share/vm/opto/callGenerator.cpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/share/vm/opto/callGenerator.hpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/share/vm/opto/callnode.cpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/share/vm/opto/callnode.hpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/share/vm/opto/compile.cpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/share/vm/opto/compile.hpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/share/vm/opto/doCall.cpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/share/vm/opto/escape.cpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/share/vm/opto/escape.hpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/share/vm/opto/graphKit.cpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/share/vm/opto/graphKit.hpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/share/vm/opto/lcm.cpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/share/vm/opto/loopnode.cpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/share/vm/opto/macro.cpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/share/vm/opto/matcher.cpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/share/vm/opto/memnode.cpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/share/vm/opto/memnode.hpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/share/vm/opto/node.hpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/share/vm/opto/parse1.cpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/share/vm/opto/parse3.cpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/share/vm/opto/parseHelper.cpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/share/vm/opto/phase.hpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/share/vm/opto/phaseX.hpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/share/vm/opto/superword.cpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/share/vm/opto/type.hpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/share/vm/prims/jni.cpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/share/vm/prims/jvm.cpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/share/vm/prims/jvmtiEnv.cpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/share/vm/prims/jvmtiEnvBase.cpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/share/vm/prims/jvmtiEnvBase.hpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/share/vm/prims/jvmtiExport.cpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/share/vm/prims/jvmtiExport.hpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/share/vm/prims/jvmtiHpp.xsl	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/share/vm/prims/jvmtiManageCapabilities.cpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/share/vm/prims/methodHandles.cpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/share/vm/runtime/arguments.cpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/share/vm/runtime/arguments.hpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/share/vm/runtime/frame.cpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/share/vm/runtime/globals.cpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/share/vm/runtime/globals.hpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/share/vm/runtime/globals_extension.hpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/share/vm/runtime/os.hpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/share/vm/runtime/thread.cpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/share/vm/runtime/thread.hpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/share/vm/runtime/vmStructs.cpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/share/vm/runtime/vmThread.cpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/share/vm/runtime/vmThread.hpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/share/vm/services/attachListener.cpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/share/vm/services/management.cpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/share/vm/services/memoryManager.cpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/share/vm/services/memoryManager.hpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/share/vm/services/memoryService.cpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/share/vm/services/memoryService.hpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/share/vm/utilities/growableArray.hpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/share/vm/utilities/numberSeq.cpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/share/vm/utilities/numberSeq.hpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/hotspot/src/share/vm/utilities/vmError.cpp	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 15:36:54 2010 -0800
@@ -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/jaxp/.hgtags	Fri Jan 15 16:31:16 2010 +0000
+++ b/jaxp/.hgtags	Fri Jan 15 15:36:54 2010 -0800
@@ -52,3 +52,4 @@
 555fb78ee4cebed082ca7ddabff46d2e5b4c9026 jdk7-b75
 233a4871d3364ec305efd4a58cfd676620a03a90 jdk7-b76
 bfadab8c7b1bf806a49d3e1bc19ec919717f057a jdk7-b77
+7a12d3789e1b07a560fc79568b991818d617ede2 jdk7-b78
--- a/jaxws/.hgtags	Fri Jan 15 16:31:16 2010 +0000
+++ b/jaxws/.hgtags	Fri Jan 15 15:36:54 2010 -0800
@@ -52,3 +52,4 @@
 fcf2b8b5d606641659419f247fcee4b284c45e6e jdk7-b75
 765d2077d1e652e234d27fe85ba58a986b488503 jdk7-b76
 5b4968c110476085225d3a71c4210fad2c1116c1 jdk7-b77
+fc1c72d1dfbb17db7d46bba8db9afc39cbbb9299 jdk7-b78
--- a/jdk/.hgtags	Fri Jan 15 16:31:16 2010 +0000
+++ b/jdk/.hgtags	Fri Jan 15 15:36:54 2010 -0800
@@ -53,3 +53,4 @@
 8fb602395be0f7d5af4e7e93b7df2d960faf9d17 jdk7-b76
 e6a5d095c356a547cf5b3c8885885aca5e91e09b jdk7-b77
 1143e498f813b8223b5e3a696d79da7ff7c25354 jdk7-b78
+918920710d65432a2d54fdf407c1524a5571c4ad jdk7-b79
--- a/jdk/src/share/classes/java/dyn/CallSite.java	Fri Jan 15 16:31:16 2010 +0000
+++ b/jdk/src/share/classes/java/dyn/CallSite.java	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/jdk/src/share/classes/java/dyn/InvokeDynamic.java	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/jdk/src/share/classes/java/dyn/InvokeDynamicBootstrapError.java	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/jdk/src/share/classes/java/dyn/JavaMethodHandle.java	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/jdk/src/share/classes/java/dyn/Linkage.java	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/jdk/src/share/classes/java/dyn/LinkagePermission.java	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/jdk/src/share/classes/java/dyn/MethodHandle.java	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/jdk/src/share/classes/java/dyn/MethodHandles.java	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/jdk/src/share/classes/java/dyn/MethodType.java	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/jdk/src/share/classes/java/dyn/package-info.java	Fri Jan 15 15:36:54 2010 -0800
@@ -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/sun/dyn/AdapterMethodHandle.java	Fri Jan 15 16:31:16 2010 +0000
+++ b/jdk/src/share/classes/sun/dyn/AdapterMethodHandle.java	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/jdk/src/share/classes/sun/dyn/BoundMethodHandle.java	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/jdk/src/share/classes/sun/dyn/CallSiteImpl.java	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/jdk/src/share/classes/sun/dyn/FilterGeneric.java	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/jdk/src/share/classes/sun/dyn/FilterOneArgument.java	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/jdk/src/share/classes/sun/dyn/FromGeneric.java	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/jdk/src/share/classes/sun/dyn/Invokers.java	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/jdk/src/share/classes/sun/dyn/MemberName.java	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/jdk/src/share/classes/sun/dyn/MethodHandleImpl.java	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/jdk/src/share/classes/sun/dyn/MethodHandleNatives.java	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/jdk/src/share/classes/sun/dyn/MethodTypeImpl.java	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/jdk/src/share/classes/sun/dyn/ToGeneric.java	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/jdk/src/share/classes/sun/dyn/empty/Empty.java	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/jdk/src/share/classes/sun/dyn/util/BytecodeName.java	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ /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	Fri Jan 15 16:31:16 2010 +0000
+++ b/jdk/src/share/classes/sun/dyn/util/ValueConversions.java	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/jdk/src/share/classes/sun/dyn/util/VerifyAccess.java	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/jdk/src/share/classes/sun/dyn/util/VerifyType.java	Fri Jan 15 15:36:54 2010 -0800
@@ -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	Fri Jan 15 16:31:16 2010 +0000
+++ b/jdk/src/share/classes/sun/dyn/util/Wrapper.java	Fri Jan 15 15:36:54 2010 -0800
@@ -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/test/ProblemList.txt	Fri Jan 15 16:31:16 2010 +0000
+++ b/jdk/test/ProblemList.txt	Fri Jan 15 15:36:54 2010 -0800
@@ -571,6 +571,7 @@
 javax/print/attribute/GetCopiesSupported.java			generic-all
 javax/print/attribute/SidesPageRangesTest.java			generic-all
 javax/print/attribute/SupportedPrintableAreas.java		generic-all
+javax/print/attribute/AttributeTest.java                        generic-all
 
 # Only print test left, excluding just because all print tests have been
 javax/print/attribute/MediaMappingsTest.java 			generic-all
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/dyn/MethodHandlesTest.java	Fri Jan 15 15:36:54 2010 -0800
@@ -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/javax/print/DialogMargins.java	Fri Jan 15 15:36:54 2010 -0800
@@ -0,0 +1,244 @@
+/*
+ * Copyright 2001-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.  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
+ * @bug 4485755 6361370 6448717 5080051
+ * @summary dialog doesn't have way to specify margins
+ *          for 6361370, verify exception for offline printer in Windows
+ *          for 6448717, faster display of print dialog
+ *          for 6500903, verify status of printer if accepting jobs or not
+ * @author prr
+ * @run main/manual DialogMargins
+ */
+
+import java.awt.*;
+import java.awt.event.*;
+import java.awt.print.*;
+import javax.print.*;
+import javax.print.attribute.*;
+import javax.print.attribute.standard.*;
+
+public class DialogMargins extends Frame {
+
+  public DialogMargins() {
+     super("Dialog Margins Test");
+
+    Button printButton = new Button ("Print ...");
+    add("Center", printButton);
+    printButton.addActionListener(new ActionListener() {
+                public void actionPerformed (ActionEvent e) {
+                     new MarginsPrinter();
+                }
+    });
+
+    addWindowListener (new WindowAdapter() {
+         public void windowClosing (WindowEvent e) {
+            dispose();
+         }
+
+     });
+
+     pack();
+     setVisible (true);
+  }
+
+class MarginsPrinter implements Printable {
+
+  PrinterJob myPrinterJob;
+  PageFormat myPageFormat;
+
+  public MarginsPrinter() {
+      PrintRequestAttributeSet aset = new HashPrintRequestAttributeSet();
+      //aset.add(MediaSizeName.ISO_A4);
+      //aset.add(new MediaPrintableArea(0f,0f,210f,297f,MediaPrintableArea.MM));
+      myPrinterJob = PrinterJob.getPrinterJob();
+      myPageFormat = myPrinterJob.pageDialog(aset);
+      myPrinterJob.setPrintable(this, myPageFormat);
+      //myPrinterJob.setPrintable(this);
+      if (myPrinterJob.printDialog(aset)) {
+          try {
+             //PrintRequestAttributeSet newaset =
+                   //new HashPrintRequestAttributeSet();
+              myPrinterJob.print(aset);
+
+          } catch (PrinterException pe ) {
+              System.out.println("DialogMargins Exception caught:" + pe);
+          }
+      }
+   }
+
+  public int print(Graphics graphics, PageFormat pageFormat, int pageIndex) {
+
+     if (pageIndex > 0) {
+        return Printable.NO_SUCH_PAGE;
+     }
+
+     Graphics2D g2d = (Graphics2D)graphics;
+     g2d.translate(pageFormat.getImageableX(), pageFormat.getImageableY());
+     g2d.drawString("ORIGIN("+pageFormat.getImageableX()+","+
+                             pageFormat.getImageableY()+")", 20, 20);
+     g2d.drawString("X THIS WAY", 200, 50);
+     g2d.drawString("Y THIS WAY", 60 , 200);
+     g2d.drawString("Graphics is " + g2d.getClass().getName(), 100, 100);
+     g2d.drawRect(0,0,(int)pageFormat.getImageableWidth(),
+                      (int)pageFormat.getImageableHeight());
+     g2d.setColor(Color.black);
+     g2d.drawRect(1,1,(int)pageFormat.getImageableWidth()-2,
+                      (int)pageFormat.getImageableHeight()-2);
+
+     return  Printable.PAGE_EXISTS;
+  }
+
+}
+  public static void main( String[] args) {
+
+  String[] instructions =
+        {
+         "You must have a printer available to perform this test",
+         "Specify various pageformats and compare the printed results with the",
+         "request."
+       };
+      Sysout.createDialog( );
+      Sysout.printInstructions( instructions );
+
+     new DialogMargins();
+  }
+}
+
+
+class Sysout {
+   private static TestDialog dialog;
+
+   public static void createDialogWithInstructions( String[] instructions )
+    {
+      dialog = new TestDialog( new Frame(), "Instructions" );
+      dialog.printInstructions( instructions );
+      dialog.show();
+      println( "Any messages for the tester will display here." );
+    }
+
+   public static void createDialog( )
+    {
+      dialog = new TestDialog( new Frame(), "Instructions" );
+      String[] defInstr = { "Instructions will appear here. ", "" } ;
+      dialog.printInstructions( defInstr );
+      dialog.show();
+      println( "Any messages for the tester will display here." );
+    }
+
+
+   public static void printInstructions( String[] instructions )
+    {
+      dialog.printInstructions( instructions );
+    }
+
+
+   public static void println( String messageIn )
+    {
+      dialog.displayMessage( messageIn );
+    }
+
+}// Sysout  class
+
+/**
+  This is part of the standard test machinery.  It provides a place for the
+   test instructions to be displayed, and a place for interactive messages
+   to the user to be displayed.
+  To have the test instructions displayed, see Sysout.
+  To have a message to the user be displayed, see Sysout.
+  Do not call anything in this dialog directly.
+  */
+class TestDialog extends Dialog {
+
+   TextArea instructionsText;
+   TextArea messageText;
+   int maxStringLength = 80;
+
+   //DO NOT call this directly, go through Sysout
+   public TestDialog( Frame frame, String name )
+    {
+      super( frame, name );
+      int scrollBoth = TextArea.SCROLLBARS_BOTH;
+      instructionsText = new TextArea( "", 15, maxStringLength, scrollBoth );
+      add( "North", instructionsText );
+
+      messageText = new TextArea( "", 5, maxStringLength, scrollBoth );
+      add("Center", messageText);
+
+      pack();
+
+      show();
+    }// TestDialog()
+
+   //DO NOT call this directly, go through Sysout
+   public void printInstructions( String[] instructions )
+    {
+      //Clear out any current instructions
+      instructionsText.setText( "" );
+
+      //Go down array of instruction strings
+
+      String printStr, remainingStr;
+      for( int i=0; i < instructions.length; i++ )
+       {
+         //chop up each into pieces maxSringLength long
+         remainingStr = instructions[ i ];
+         while( remainingStr.length() > 0 )
+          {
+            //if longer than max then chop off first max chars to print
+            if( remainingStr.length() >= maxStringLength )
+             {
+               //Try to chop on a word boundary
+               int posOfSpace = remainingStr.
+                  lastIndexOf( ' ', maxStringLength - 1 );
+
+               if( posOfSpace <= 0 ) posOfSpace = maxStringLength - 1;
+
+               printStr = remainingStr.substring( 0, posOfSpace + 1 );
+               remainingStr = remainingStr.substring( posOfSpace + 1 );
+             }
+            //else just print
+            else
+             {
+               printStr = remainingStr;
+               remainingStr = "";
+             }
+
+            instructionsText.append( printStr + "\n" );
+
+          }// while
+
+       }// for
+
+    }//printInstructions()
+
+   //DO NOT call this directly, go through Sysout
+   public void displayMessage( String messageIn )
+    {
+      messageText.append( messageIn + "\n" );
+    }
+
+ }// TestDialog  class
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/print/StreamPrintingOrientation.java	Fri Jan 15 15:36:54 2010 -0800
@@ -0,0 +1,120 @@
+/*
+ * 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
+ * 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
+ * @bug 4904236
+ * @summary You would see a cross-platform print dialog being popped up. Check whether orientation is shown as LANDSCAPE. Click 'OK'. 'streamexample.ps' will be created in the same dir where this application was executed. Pass if the orientation in the ps file is landscape.
+ * @run main/manual StreamPrintingOrientation
+ */
+
+import java.awt.*;
+import java.awt.print.*;
+import javax.print.*;
+import javax.print.attribute.standard.*;
+import javax.print.attribute.*;
+import java.io.FileOutputStream;
+import java.io.File;
+import java.util.Locale;
+
+class StreamPrintingOrientation implements Printable {
+        /**
+         * Constructor
+         */
+         public StreamPrintingOrientation() {
+                super();
+        }
+        /**
+         * Starts the application.
+         */
+        public static void main(java.lang.String[] args) {
+                StreamPrintingOrientation pd = new StreamPrintingOrientation();
+                PrinterJob pj = PrinterJob.getPrinterJob();
+                HashPrintRequestAttributeSet prSet = new HashPrintRequestAttributeSet();
+                PrintService service = null;
+
+                FileOutputStream fos = null;
+                File f = null, f1 = null;
+                String mType = "application/postscript";
+
+                try {
+                        f = new File("streamexample.ps");
+                        fos = new FileOutputStream(f);
+                        StreamPrintServiceFactory[] factories = PrinterJob.lookupStreamPrintServices(mType);
+                        if (factories.length > 0)
+                                service = factories[0].getPrintService(fos);
+
+                        if (service != null) {
+                                System.out.println("Stream Print Service "+service);
+                                pj.setPrintService(service);
+                        } else {
+                                throw new RuntimeException("No stream Print Service available.");
+                        }
+                } catch (Exception e) {
+                        e.printStackTrace();
+                }
+
+                pj.setPrintable(pd);
+                prSet.add(OrientationRequested.LANDSCAPE);
+                prSet.add(new Copies(3));
+                prSet.add(new JobName("orientation test", null));
+                System.out.println("open PrintDialog..");
+                if (pj.printDialog(prSet)) {
+                        try {
+                                System.out.println("\nValues in attr set passed to print method");
+                                Attribute attr[] = prSet.toArray();
+                                for (int x = 0; x < attr.length; x ++) {
+                                        System.out.println("Name "+attr[x].getName()+"  "+attr[x]);
+                                }
+                                System.out.println("About to print the data ...");
+                                if (service != null) {
+                                        System.out.println("TEST: calling Print");
+                                        pj.print(prSet);
+                                        System.out.println("TEST: Printed");
+                                }
+                        }
+                        catch (PrinterException pe) {
+                                pe.printStackTrace();
+                        }
+                }
+
+        }
+
+        //printable interface
+        public int print(Graphics g, PageFormat pf, int pi) throws PrinterException {
+
+                if (pi > 0) {
+                        return Printable.NO_SUCH_PAGE;
+                }
+                // Simply draw two rectangles
+                Graphics2D g2 = (Graphics2D)g;
+                g2.setColor(Color.black);
+                g2.translate(pf.getImageableX(), pf.getImageableY());
+                System.out.println("StreamPrinting Test Width "+pf.getWidth()+" Height "+pf.getHeight());
+                g2.drawRect(1,1,200,300);
+                g2.drawRect(1,1,25,25);
+                return Printable.PAGE_EXISTS;
+        }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/print/attribute/AttributeTest.java	Fri Jan 15 15:36:54 2010 -0800
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2006-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 6387255
+ * @summary  Tests conflict of Media values returned by isAttrValueSupported and getSupportedAttrValues.  No runtime exception should be thrown.
+ * @run main AttributeTest
+ */
+import javax.print.*;
+import javax.print.attribute.standard.*;
+import javax.print.attribute.*;
+
+public class AttributeTest {
+
+        public AttributeTest() {
+
+                PrintService service[] = PrintServiceLookup.lookupPrintServices(null, null);
+
+                if (service.length == 0) {
+                        throw new RuntimeException("No printer found.  TEST ABORTED");
+                }
+
+                for (int x = 0; x < service.length; x ++) {
+                        DocFlavor flavors[] = service[x].getSupportedDocFlavors();
+
+                        for (int y = 0; y < flavors.length; y ++) {
+                                Object attrVal = service[x].getSupportedAttributeValues(Media.class, flavors[y], null);
+                                if (attrVal == null) {
+                                        continue;
+                                }
+                                Media attr[] = (Media[]) attrVal;
+                                for (int z = 0; z < attr.length; z ++) {
+                                        if (!service[x].isAttributeValueSupported(attr[z], flavors[y], null)) {
+                                                throw new RuntimeException("ERROR: There is a conflict between getSupportedAttrValues " +
+                                                " and isAttributeValueSupported, for the attribute: " + attr[z] +
+                                                ", where the flavor is: " + flavors[y] + " and the print service is: " +
+                                                service[x] + "\n");
+                                        }
+                                }
+                        }
+                }
+
+                System.out.println("Test Passed");
+        }
+
+        public static void main (String args[]) {
+                AttributeTest test = new AttributeTest();
+        }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/print/attribute/ServiceDialogTest.java	Fri Jan 15 15:36:54 2010 -0800
@@ -0,0 +1,307 @@
+/*
+ * 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
+ * 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 4910388 4871089 4998624
+ * @summary Confirm that
+ *      1. After choosing Reverse Landscape in the system default print
+ *       Print Service (2nd in the list), it
+ *          will reset to portrait in "Test Printer"
+ *      2. Print To File button is not cleared when switching between the
+ *         2nd service (system default printer) and Test Printer.
+ *      3. Make sure "Postscript" printer is the default and make sure the
+ *         "print to file" button is disabled.  File Dialog should not be
+ *         shown after pressing print button.
+ *
+ * @run main/manual ServiceDialogTest
+ */
+import java.awt.*;
+import javax.print.*;
+import javax.print.attribute.standard.*;
+import javax.print.attribute.*;
+import javax.print.event.*;
+import java.io.*;
+import java.util.Locale;
+
+public class ServiceDialogTest {
+        /**
+         * Constructor
+         */
+         public ServiceDialogTest() {
+                super();
+        }
+        /**
+         * Starts the application.
+         */
+        public static void main(java.lang.String[] args) {
+                ServiceDialogTest pd = new ServiceDialogTest();
+                PrintService services[] = new PrintService[3];
+                services[1] = PrintServiceLookup.lookupDefaultPrintService();
+
+                FileOutputStream fos = null;
+                File f = null;
+                String mType = "application/postscript";
+                DocFlavor flavor = DocFlavor.INPUT_STREAM.JPEG;
+                try {
+                        f = new File("streamexample.ps");
+                        fos = new FileOutputStream(f);
+                        StreamPrintServiceFactory[] factories = StreamPrintServiceFactory.lookupStreamPrintServiceFactories(flavor, mType);
+                        if (factories.length > 0) {
+                                services[0] = factories[0].getPrintService(fos);
+                        } else {
+                                throw new RuntimeException("No StreamPrintService available which would support "+flavor");
+                        }
+
+                        services[2] = new TestPrintService("Test Printer");
+
+            //System.out.println("is "+flavor+" supported? "+services[0].isDocFlavorSupported(flavor));
+            //System.out.println("is Orientation supported? "+services[0].isAttributeCategorySupported(OrientationRequested.class));
+            //System.out.println("is REVERSE PORTRAIT supported ? "+services[0].isAttributeValueSupported(OrientationRequested.REVERSE_PORTRAIT, flavor, null));
+
+            HashPrintRequestAttributeSet prSet = new HashPrintRequestAttributeSet();
+            prSet.add(new Destination(new File("./dest.prn").toURI()));
+            PrintService selService = ServiceUI.printDialog(null, 200, 200, services, services[0], flavor, prSet);
+                        Attribute attr[] = prSet.toArray();
+                        for (int x = 0; x < attr.length; x ++) {
+                                System.out.println(attr[x]);
+                        }
+
+                        //DocPrintJob pj = service.createPrintJob();
+                        //PrintDocument prDoc = new PrintDocument();
+                        //pj.print(prDoc, null);
+
+                } catch (Exception e) {
+                        e.printStackTrace();
+                }
+        }
+}
+
+
+class TestPrintService implements PrintService
+{
+
+    private static DocFlavor textByteFlavor = null;
+    private static final DocFlavor supportedDocFlavors[] = (new DocFlavor[] {
+             javax.print.DocFlavor.INPUT_STREAM.JPEG
+    });
+
+    private static final Class serviceAttrCats[] = (new Class[] {
+             javax.print.attribute.standard.PrinterName.class
+    });
+
+    private static final Class otherAttrCats[] = (new Class [] {
+             javax.print.attribute.standard.Copies.class,
+             javax.print.attribute.standard.OrientationRequested.class,
+             javax.print.attribute.standard.Destination.class,
+    });
+
+    private String printer = null;
+
+    public TestPrintService() {
+    }
+
+    public TestPrintService(String printerName) {
+        if (printerName == null) {
+            throw new IllegalArgumentException("null printer name");
+        } else {
+            printer = printerName;
+        }
+    }
+
+    public String getName()
+    {
+        return printer;
+    }
+
+
+    public DocPrintJob createPrintJob()
+    {
+        return  null;
+    }
+
+    public PrintServiceAttributeSet getUpdatedAttributes()
+    {
+        return null;
+    }
+
+
+    public void addPrintServiceAttributeListener(PrintServiceAttributeListener printserviceattributelistener)
+    {
+    }
+
+    public void removePrintServiceAttributeListener(PrintServiceAttributeListener printserviceattributelistener)
+    {
+    }
+
+    public PrintServiceAttribute getAttribute(Class category)
+    {
+        return null;
+    }
+
+    public PrintServiceAttributeSet getAttributes()
+    {
+        HashPrintServiceAttributeSet aSet = new HashPrintServiceAttributeSet();
+            return aSet;
+    }
+
+    public DocFlavor[] getSupportedDocFlavors()
+    {
+        int i = supportedDocFlavors.length;
+        DocFlavor adocflavor[] = new DocFlavor[i];
+        System.arraycopy(supportedDocFlavors, 0, adocflavor, 0, i);
+        return adocflavor;
+    }
+
+    public boolean isDocFlavorSupported(DocFlavor docflavor)
+    {
+        for (int i = 0; i < supportedDocFlavors.length; i++) {
+            if (docflavor.equals(supportedDocFlavors[i])) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    public Class[] getSupportedAttributeCategories()
+    {
+        int i = otherAttrCats.length;
+        Class aclass[] = new Class[i];
+        System.arraycopy(otherAttrCats, 0, aclass, 0, otherAttrCats.length);
+        return aclass;
+    }
+
+    public boolean isAttributeCategorySupported(Class category)
+    {
+        if (category == null) {
+            throw new NullPointerException("null category");
+        }
+
+        for (int i = 0; i < otherAttrCats.length; i++) {
+            if (category == otherAttrCats[i]) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    public boolean isAttributeValueSupported(Attribute attrval, DocFlavor flavor, AttributeSet attributes) {
+
+        if (attrval == OrientationRequested.PORTRAIT)
+                return true;
+        else if (attrval == OrientationRequested.LANDSCAPE)
+                return true;
+                else
+                        return false;
+    }
+
+    public Object getDefaultAttributeValue(Class category)
+    {
+        if (category == null) {
+            throw new NullPointerException("null category");
+        }
+        if (category == javax.print.attribute.standard.Copies.class)
+                return new Copies(1);
+
+        if (category == javax.print.attribute.standard.OrientationRequested.class)
+                return OrientationRequested.PORTRAIT;
+
+        return null;
+    }
+
+    public Object getSupportedAttributeValues(Class category, DocFlavor docflavor, AttributeSet attributeset)
+    {
+        if (category == null) {
+            throw new NullPointerException("null category");
+        }
+
+        if (docflavor != null) {
+            if (!isDocFlavorSupported(docflavor)) {
+                throw new IllegalArgumentException(docflavor + " is an unsupported flavor");
+            }
+        }
+        if (!isAttributeCategorySupported(category)) {
+            return null;
+        }
+        if (category == javax.print.attribute.standard.Copies.class ) {
+               return new CopiesSupported(1, 5);
+        }
+        if (category == javax.print.attribute.standard.OrientationRequested.class ) {
+               OrientationRequested req[] = { OrientationRequested.PORTRAIT, OrientationRequested.LANDSCAPE };
+               return req;
+        }
+
+        return null;
+    }
+
+    public AttributeSet getUnsupportedAttributes(DocFlavor docflavor, AttributeSet attributeset) {
+
+        if (docflavor != null && !isDocFlavorSupported(docflavor)) {
+            throw new IllegalArgumentException("flavor " + docflavor + "is not supported");
+        }
+        if (attributeset == null) {
+            return null;
+        }
+
+        HashAttributeSet hashattributeset = new HashAttributeSet();
+        Attribute attributearray[] = attributeset.toArray();
+        for (int i = 0; i < attributearray.length; i++) {
+            try {
+                Attribute attribute = attributearray[i];
+                if (!isAttributeCategorySupported(attribute.getCategory())) {
+                     hashattributeset.add(attribute);
+                } else {
+                  if (!isAttributeValueSupported(attribute, docflavor, attributeset)) {
+                     hashattributeset.add(attribute);
+                  }
+                }
+            }
+            catch (ClassCastException classcastexception) {
+
+            }
+        }
+
+        if (hashattributeset.isEmpty()) {
+            return null;
+        }
+        return hashattributeset;
+    }
+
+    public ServiceUIFactory getServiceUIFactory() {
+        return null;
+    }
+
+    public String toString() {
+        return "Printer : " + getName();
+    }
+
+    public boolean equals(Object obj) {
+        return obj == this || (obj instanceof TestPrintService) && ((TestPrintService)obj).getName().equals(getName());
+    }
+
+    public int hashCode() {
+        return getClass().hashCode() + getName().hashCode();
+    }
+
+}
--- a/jdk/test/javax/print/attribute/SidesPageRangesTest.java	Fri Jan 15 16:31:16 2010 +0000
+++ b/jdk/test/javax/print/attribute/SidesPageRangesTest.java	Fri Jan 15 15:36:54 2010 -0800
@@ -64,7 +64,7 @@
                         System.out.println("\nPageRanges Attribute category is supported");
                 } else {
                         System.out.println("\nPageRanges Attribute category is not supported. terminating...");
-                        System.exit(1);
+                        return;
                 }
 
                 flavors = defService.getSupportedDocFlavors();
--- a/langtools/.hgtags	Fri Jan 15 16:31:16 2010 +0000
+++ b/langtools/.hgtags	Fri Jan 15 15:36:54 2010 -0800
@@ -52,3 +52,4 @@
 2485f5641ed0829205aaaeb31ad711c2c2ef0de3 jdk7-b75
 8fb9b4be3cb1574302acde90549a4d333ef51e93 jdk7-b76
 0398ae15b90ac76d87ee21844453e95ff8613e43 jdk7-b77
+acc1e40a5874ebf32bebcb6ada565b3b40b7461c jdk7-b78
--- a/langtools/make/build.properties	Fri Jan 15 16:31:16 2010 +0000
+++ b/langtools/make/build.properties	Fri Jan 15 15:36:54 2010 -0800
@@ -149,11 +149,26 @@
 #
 
 # The following files require the import JDK to be available
-require.import.jdk.files =
+require.import.jdk.files = \
+    com/sun/tools/javac/nio/*.java
 
 # The following files in the import jdk source directory are required
 # in order to compile the files defined in ${require.import.jdk.files}
-import.jdk.stub.files =
+#
+# For NIO, the list of stub files is defined by the contents of the primary
+# API packages, together with such types that may be required in order to
+# compile the stubs. Some of these dependencies would go away if the stub
+# generator were to be improved -- e.g. by removing unnecessary imports.
+#
+import.jdk.stub.files = \
+    java/io/File.java \
+    java/nio/file/**.java \
+    java/nio/file/attribute/**.java \
+    java/nio/file/spi/**.java \
+    java/nio/channels/AsynchronousChannel.java \
+    java/nio/channels/AsynchronousFileChannel.java \
+    java/nio/channels/CompletionHandler.java \
+    java/nio/channels/SeekableByteChannel.java
 
 # The following value is used by the main jtreg target.
 # An empty value means all tests
--- a/langtools/make/build.xml	Fri Jan 15 16:31:16 2010 +0000
+++ b/langtools/make/build.xml	Fri Jan 15 15:36:54 2010 -0800
@@ -98,7 +98,7 @@
         import.jdk should be unset, or set to jdk home (to use rt.jar)
         or to jdk repo (to use src/share/classes).
         Based on the value, if any, set up default values for javac's sourcepath,
-        classpath and bootclasspath. Note: the default values are overridden 
+        classpath and bootclasspath. Note: the default values are overridden
         in the build-bootstrap-classes macro. -->
 
     <available property="import.jdk.src.dir" value="${import.jdk}/src/share/classes"
@@ -552,8 +552,8 @@
                     <compilerarg line="${javac.version.opt}"/>
                     <compilerarg line="${javac.lint.opts}"/>
                 </javac>
-                <copy todir="@{classes.dir}">
-                    <fileset dir="${src.classes.dir}" includes="@{includes}">
+                <copy todir="@{classes.dir}" includeemptydirs="false">
+                    <fileset dir="${src.classes.dir}" includes="@{includes}" excludes="@{excludes}">
                         <exclude name="**/*.java"/>
                         <exclude name="**/*.properties"/>
                         <exclude name="**/*-template"/>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/share/classes/com/sun/tools/classfile/Dependencies.java	Fri Jan 15 15:36:54 2010 -0800
@@ -0,0 +1,718 @@
+/*
+ * 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.
+ */
+package com.sun.tools.classfile;
+
+import java.util.Deque;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.regex.Pattern;
+
+import com.sun.tools.classfile.Dependency.Finder;
+import com.sun.tools.classfile.Dependency.Filter;
+import com.sun.tools.classfile.Dependency.Location;
+import com.sun.tools.classfile.Type.ArrayType;
+import com.sun.tools.classfile.Type.ClassSigType;
+import com.sun.tools.classfile.Type.ClassType;
+import com.sun.tools.classfile.Type.MethodType;
+import com.sun.tools.classfile.Type.SimpleType;
+import com.sun.tools.classfile.Type.TypeParamType;
+import com.sun.tools.classfile.Type.WildcardType;
+
+import static com.sun.tools.classfile.ConstantPool.*;
+
+/**
+ * A framework for determining {@link Dependency dependencies} between class files.
+ *
+ * A {@link Dependency.Finder finder} is used to identify the dependencies of
+ * individual classes. Some finders may return subtypes of {@code Dependency} to
+ * further characterize the type of dependency, such as a dependency on a
+ * method within a class.
+ *
+ * A {@link Dependency.Filter filter} may be used to restrict the set of
+ * dependencies found by a finder.
+ *
+ * Dependencies that are found may be passed to a {@link Dependencies.Recorder
+ * recorder} so that the dependencies can be stored in a custom data structure.
+ */
+public class Dependencies {
+    /**
+     * Thrown when a class file cannot be found.
+     */
+    public static class ClassFileNotFoundException extends Exception {
+        private static final long serialVersionUID = 3632265927794475048L;
+
+        public ClassFileNotFoundException(String className) {
+            super(className);
+            this.className = className;
+        }
+
+        public ClassFileNotFoundException(String className, Throwable cause) {
+            this(className);
+            initCause(cause);
+        }
+
+        public final String className;
+    }
+
+    /**
+     * Thrown when an exception is found processing a class file.
+     */
+    public static class ClassFileError extends Error {
+        private static final long serialVersionUID = 4111110813961313203L;
+
+        public ClassFileError(Throwable cause) {
+            initCause(cause);
+        }
+    }
+
+    /**
+     * Service provider interface to locate and read class files.
+     */
+    public interface ClassFileReader {
+        /**
+         * Get the ClassFile object for a specified class.
+         * @param className the name of the class to be returned.
+         * @return the ClassFile for the given class
+         * @throws Dependencies#ClassFileNotFoundException if the classfile cannot be
+         *   found
+         */
+        public ClassFile getClassFile(String className)
+                throws ClassFileNotFoundException;
+    }
+
+    /**
+     * Service provide interface to handle results.
+     */
+    public interface Recorder {
+        /**
+         * Record a dependency that has been found.
+         * @param d
+         */
+        public void addDependency(Dependency d);
+    }
+
+    /**
+     * Get the  default finder used to locate the dependencies for a class.
+     * @return the default finder
+     */
+    public static Finder getDefaultFinder() {
+        return new APIDependencyFinder(AccessFlags.ACC_PRIVATE);
+    }
+
+    /**
+     * Get a finder used to locate the API dependencies for a class.
+     * These include the superclass, superinterfaces, and classes referenced in
+     * the declarations of fields and methods.  The fields and methods that
+     * are checked can be limited according to a specified access.
+     * The access parameter must be one of {@link AccessFlags#ACC_PUBLIC ACC_PUBLIC},
+     * {@link AccessFlags#ACC_PRIVATE ACC_PRIVATE},
+     * {@link AccessFlags#ACC_PROTECTED ACC_PROTECTED}, or 0 for
+     * package private access. Members with greater than or equal accessibility
+     * to that specified will be searched for dependencies.
+     * @param access the access of members to be checked
+     * @return an API finder
+     */
+    public static Finder getAPIFinder(int access) {
+        return new APIDependencyFinder(access);
+    }
+
+    /**
+     * Get the finder used to locate the dependencies for a class.
+     * @return the finder
+     */
+    public Finder getFinder() {
+        if (finder == null)
+            finder = getDefaultFinder();
+        return finder;
+    }
+
+    /**
+     * Set the finder used to locate the dependencies for a class.
+     * @param f the finder
+     */
+    public void setFinder(Finder f) {
+        f.getClass(); // null check
+        finder = f;
+    }
+
+    /**
+     * Get the default filter used to determine included when searching
+     * the transitive closure of all the dependencies.
+     * Unless overridden, the default filter accepts all dependencies.
+     * @return the default filter.
+     */
+    public static Filter getDefaultFilter() {
+        return DefaultFilter.instance();
+    }
+
+    /**
+     * Get a filter which uses a regular expression on the target's class name
+     * to determine if a dependency is of interest.
+     * @param pattern the pattern used to match the target's class name
+     * @return a filter for matching the target class name with a regular expression
+     */
+    public static Filter getRegexFilter(Pattern pattern) {
+        return new TargetRegexFilter(pattern);
+    }
+
+    /**
+     * Get a filter which checks the package of a target's class name
+     * to determine if a dependency is of interest. The filter checks if the
+     * package of the target's class matches any of a set of given package
+     * names. The match may optionally match subpackages of the given names as well.
+     * @param packageNames the package names used to match the target's class name
+     * @param matchSubpackages whether or not to match subpackages as well
+     * @return a filter for checking the target package name against a list of package names
+     */
+    public static Filter getPackageFilter(Set<String> packageNames, boolean matchSubpackages) {
+        return new TargetPackageFilter(packageNames, matchSubpackages);
+    }
+
+    /**
+     * Get the filter used to determine the dependencies included when searching
+     * the transitive closure of all the dependencies.
+     * Unless overridden, the default filter accepts all dependencies.
+     * @return the filter
+     */
+    public Filter getFilter() {
+        if (filter == null)
+            filter = getDefaultFilter();
+        return filter;
+    }
+
+    /**
+     * Set the filter used to determine the dependencies included when searching
+     * the transitive closure of all the dependencies.
+     * @param f the filter
+     */
+    public void setFilter(Filter f) {
+        f.getClass(); // null check
+        filter = f;
+    }
+
+    /**
+     * Find the dependencies of a class, using the current
+     * {@link Dependencies#getFinder finder} and
+     * {@link Dependencies#getFilter filter}.
+     * The search may optionally include the transitive closure of all the
+     * filtered dependencies, by also searching in the classes named in those
+     * dependencies.
+     * @param classFinder a finder to locate class files
+     * @param rootClassNames the names of the root classes from which to begin
+     *      searching
+     * @param transitiveClosure whether or not to also search those classes
+     *      named in any filtered dependencies that are found.
+     * @return the set of dependencies that were found
+     * @throws ClassFileNotFoundException if a required class file cannot be found
+     * @throws ClassFileError if an error occurs while processing a class file,
+     *      such as an error in the internal class file structure.
+     */
+    public Set<Dependency> findAllDependencies(
+            ClassFileReader classFinder, Set<String> rootClassNames,
+            boolean transitiveClosure)
+            throws ClassFileNotFoundException {
+        final Set<Dependency> results = new HashSet<Dependency>();
+        Recorder r = new Recorder() {
+            public void addDependency(Dependency d) {
+                results.add(d);
+            }
+        };
+        findAllDependencies(classFinder, rootClassNames, transitiveClosure, r);
+        return results;
+    }
+
+
+
+    /**
+     * Find the dependencies of a class, using the current
+     * {@link Dependencies#getFinder finder} and
+     * {@link Dependencies#getFilter filter}.
+     * The search may optionally include the transitive closure of all the
+     * filtered dependencies, by also searching in the classes named in those
+     * dependencies.
+     * @param classFinder a finder to locate class files
+     * @param rootClassNames the names of the root classes from which to begin
+     *      searching
+     * @param transitiveClosure whether or not to also search those classes
+     *      named in any filtered dependencies that are found.
+     * @param recorder a recorder for handling the results
+     * @throws ClassFileNotFoundException if a required class file cannot be found
+     * @throws ClassFileError if an error occurs while processing a class file,
+     *      such as an error in the internal class file structure.
+     */
+    public void findAllDependencies(
+            ClassFileReader classFinder, Set<String> rootClassNames,
+            boolean transitiveClosure, Recorder recorder)
+            throws ClassFileNotFoundException {
+        Set<String> doneClasses = new HashSet<String>();
+
+        getFinder();  // ensure initialized
+        getFilter();  // ensure initialized
+
+        // Work queue of names of classfiles to be searched.
+        // Entries will be unique, and for classes that do not yet have
+        // dependencies in the results map.
+        Deque<String> deque = new LinkedList<String>(rootClassNames);
+
+        String className;
+        while ((className = deque.poll()) != null) {
+            assert (!doneClasses.contains(className));
+            doneClasses.add(className);
+
+            ClassFile cf = classFinder.getClassFile(className);
+
+            // The following code just applies the filter to the dependencies
+            // followed for the transitive closure.
+            for (Dependency d: finder.findDependencies(cf)) {
+                recorder.addDependency(d);
+                if (transitiveClosure && filter.accepts(d)) {
+                    String cn = d.getTarget().getClassName();
+                    if (!doneClasses.contains(cn))
+                        deque.add(cn);
+                }
+            }
+        }
+    }
+
+    private Filter filter;
+    private Finder finder;
+
+    /**
+     * A location identifying a class.
+     */
+    static class SimpleLocation implements Location {
+        public SimpleLocation(String className) {
+            this.className = className;
+        }
+
+        /**
+         * Get the name of the class being depended on. This name will be used to
+         * locate the class file for transitive dependency analysis.
+         * @return the name of the class being depended on
+         */
+        public String getClassName() {
+            return className;
+        }
+
+        @Override
+        public boolean equals(Object other) {
+            if (this == other)
+                return true;
+            if (!(other instanceof SimpleLocation))
+                return false;
+            return (className.equals(((SimpleLocation) other).className));
+        }
+
+        @Override
+        public int hashCode() {
+            return className.hashCode();
+        }
+
+        @Override
+        public String toString() {
+            return className;
+        }
+
+        private String className;
+    }
+
+    /**
+     * A dependency of one class on another.
+     */
+    static class SimpleDependency implements Dependency {
+        public SimpleDependency(Location origin, Location target) {
+            this.origin = origin;
+            this.target = target;
+        }
+
+        public Location getOrigin() {
+            return origin;
+        }
+
+        public Location getTarget() {
+            return target;
+        }
+
+        @Override
+        public boolean equals(Object other) {
+            if (this == other)
+                return true;
+            if (!(other instanceof SimpleDependency))
+                return false;
+            SimpleDependency o = (SimpleDependency) other;
+            return (origin.equals(o.origin) && target.equals(o.target));
+        }
+
+        @Override
+        public int hashCode() {
+            return origin.hashCode() * 31 + target.hashCode();
+        }
+
+        @Override
+        public String toString() {
+            return origin + ":" + target;
+        }
+
+        private Location origin;
+        private Location target;
+    }
+
+
+    /**
+     * This class accepts all dependencies.
+     */
+    static class DefaultFilter implements Filter {
+        private static DefaultFilter instance;
+
+        static DefaultFilter instance() {
+            if (instance == null)
+                instance = new DefaultFilter();
+            return instance;
+        }
+
+        public boolean accepts(Dependency dependency) {
+            return true;
+        }
+    }
+
+    /**
+     * This class accepts those dependencies whose target's class name matches a
+     * regular expression.
+     */
+    static class TargetRegexFilter implements Filter {
+        TargetRegexFilter(Pattern pattern) {
+            this.pattern = pattern;
+        }
+
+        public boolean accepts(Dependency dependency) {
+            return pattern.matcher(dependency.getTarget().getClassName()).matches();
+        }
+
+        private final Pattern pattern;
+    }
+
+    /**
+     * This class accepts those dependencies whose class name is in a given
+     * package.
+     */
+    static class TargetPackageFilter implements Filter {
+        TargetPackageFilter(Set<String> packageNames, boolean matchSubpackages) {
+            for (String pn: packageNames) {
+                if (pn.length() == 0) // implies null check as well
+                    throw new IllegalArgumentException();
+            }
+            this.packageNames = packageNames;
+            this.matchSubpackages = matchSubpackages;
+        }
+
+        public boolean accepts(Dependency dependency) {
+            String cn = dependency.getTarget().getClassName();
+            int lastSep = cn.lastIndexOf("/");
+            String pn = (lastSep == -1 ? "" : cn.substring(0, lastSep));
+            if (packageNames.contains(pn))
+                return true;
+
+            if (matchSubpackages) {
+                for (String n: packageNames) {
+                    if (pn.startsWith(n + "."))
+                        return true;
+                }
+            }
+
+            return false;
+        }
+
+        private final Set<String> packageNames;
+        private final boolean matchSubpackages;
+    }
+
+
+
+    /**
+     * This class identifies class names directly or indirectly in the constant pool.
+     */
+    static class ClassDependencyFinder extends BasicDependencyFinder {
+        public Iterable<? extends Dependency> findDependencies(ClassFile classfile) {
+            Visitor v = new Visitor(classfile);
+            for (CPInfo cpInfo: classfile.constant_pool.entries()) {
+                v.scan(cpInfo);
+            }
+            return v.deps;
+        }
+    }
+
+    /**
+     * This class identifies class names in the signatures of classes, fields,
+     * and methods in a class.
+     */
+    static class APIDependencyFinder extends BasicDependencyFinder {
+        APIDependencyFinder(int access) {
+            switch (access) {
+                case AccessFlags.ACC_PUBLIC:
+                case AccessFlags.ACC_PROTECTED:
+                case AccessFlags.ACC_PRIVATE:
+                case 0:
+                    showAccess = access;
+                    break;
+                default:
+                    throw new IllegalArgumentException("invalid access 0x"
+                            + Integer.toHexString(access));
+            }
+        }
+
+        public Iterable<? extends Dependency> findDependencies(ClassFile classfile) {
+            try {
+                Visitor v = new Visitor(classfile);
+                v.addClass(classfile.super_class);
+                v.addClasses(classfile.interfaces);
+                // inner classes?
+                for (Field f : classfile.fields) {
+                    if (checkAccess(f.access_flags))
+                        v.scan(f.descriptor, f.attributes);
+                }
+                for (Method m : classfile.methods) {
+                    if (checkAccess(m.access_flags)) {
+                        v.scan(m.descriptor, m.attributes);
+                        Exceptions_attribute e =
+                                (Exceptions_attribute) m.attributes.get(Attribute.Exceptions);
+                        if (e != null)
+                            v.addClasses(e.exception_index_table);
+                    }
+                }
+                return v.deps;
+            } catch (ConstantPoolException e) {
+                throw new ClassFileError(e);
+            }
+        }
+
+        boolean checkAccess(AccessFlags flags) {
+            // code copied from javap.Options.checkAccess
+            boolean isPublic = flags.is(AccessFlags.ACC_PUBLIC);
+            boolean isProtected = flags.is(AccessFlags.ACC_PROTECTED);
+            boolean isPrivate = flags.is(AccessFlags.ACC_PRIVATE);
+            boolean isPackage = !(isPublic || isProtected || isPrivate);
+
+            if ((showAccess == AccessFlags.ACC_PUBLIC) && (isProtected || isPrivate || isPackage))
+                return false;
+            else if ((showAccess == AccessFlags.ACC_PROTECTED) && (isPrivate || isPackage))
+                return false;
+            else if ((showAccess == 0) && (isPrivate))
+                return false;
+            else
+                return true;
+        }
+
+        private int showAccess;
+    }
+
+    static abstract class BasicDependencyFinder implements Finder {
+        private Map<String,Location> locations = new HashMap<String,Location>();
+
+        Location getLocation(String className) {
+            Location l = locations.get(className);
+            if (l == null)
+                locations.put(className, l = new SimpleLocation(className));
+            return l;
+        }
+
+        class Visitor implements ConstantPool.Visitor<Void,Void>, Type.Visitor<Void, Void> {
+            private ConstantPool constant_pool;
+            private Location origin;
+            Set<Dependency> deps;
+
+            Visitor(ClassFile classFile) {
+                try {
+                    constant_pool = classFile.constant_pool;
+                    origin = getLocation(classFile.getName());
+                    deps = new HashSet<Dependency>();
+                } catch (ConstantPoolException e) {
+                    throw new ClassFileError(e);
+                }
+            }
+
+            void scan(Descriptor d, Attributes attrs) {
+                try {
+                    scan(new Signature(d.index).getType(constant_pool));
+                    Signature_attribute sa = (Signature_attribute) attrs.get(Attribute.Signature);
+                    if (sa != null)
+                        scan(new Signature(sa.signature_index).getType(constant_pool));
+                } catch (ConstantPoolException e) {
+                    throw new ClassFileError(e);
+                }
+            }
+
+            void scan(CPInfo cpInfo) {
+                cpInfo.accept(this, null);
+            }
+
+            void scan(Type t) {
+                t.accept(this, null);
+            }
+
+            void addClass(int index) throws ConstantPoolException {
+                if (index != 0) {
+                    String name = constant_pool.getClassInfo(index).getBaseName();
+                    if (name != null)
+                        addDependency(name);
+                }
+            }
+
+            void addClasses(int[] indices) throws ConstantPoolException {
+                for (int i: indices)
+                    addClass(i);
+            }
+
+            private void addDependency(String name) {
+                deps.add(new SimpleDependency(origin, getLocation(name)));
+            }
+
+            // ConstantPool.Visitor methods
+
+            public Void visitClass(CONSTANT_Class_info info, Void p) {
+                try {
+                    if (info.getName().startsWith("["))
+                        new Signature(info.name_index).getType(constant_pool).accept(this, null);
+                    else
+                        addDependency(info.getBaseName());
+                    return null;
+                } catch (ConstantPoolException e) {
+                    throw new ClassFileError(e);
+                }
+            }
+
+            public Void visitDouble(CONSTANT_Double_info info, Void p) {
+                return null;
+            }
+
+            public Void visitFieldref(CONSTANT_Fieldref_info info, Void p) {
+                return visitRef(info, p);
+            }
+
+            public Void visitFloat(CONSTANT_Float_info info, Void p) {
+                return null;
+            }
+
+            public Void visitInteger(CONSTANT_Integer_info info, Void p) {
+                return null;
+            }
+
+            public Void visitInterfaceMethodref(CONSTANT_InterfaceMethodref_info info, Void p) {
+                return visitRef(info, p);
+            }
+
+            public Void visitLong(CONSTANT_Long_info info, Void p) {
+                return null;
+            }
+
+            public Void visitNameAndType(CONSTANT_NameAndType_info info, Void p) {
+                try {
+                    new Signature(info.type_index).getType(constant_pool).accept(this, null);
+                    return null;
+                } catch (ConstantPoolException e) {
+                    throw new ClassFileError(e);
+                }
+            }
+
+            public Void visitMethodref(CONSTANT_Methodref_info info, Void p) {
+                return visitRef(info, p);
+            }
+
+            public Void visitString(CONSTANT_String_info info, Void p) {
+                return null;
+            }
+
+            public Void visitUtf8(CONSTANT_Utf8_info info, Void p) {
+                return null;
+            }
+
+            private Void visitRef(CPRefInfo info, Void p) {
+                try {
+                    visitClass(info.getClassInfo(), p);
+                    return null;
+                } catch (ConstantPoolException e) {
+                    throw new ClassFileError(e);
+                }
+            }
+
+            // Type.Visitor methods
+
+            private void findDependencies(Type t) {
+                if (t != null)
+                    t.accept(this, null);
+            }
+
+            private void findDependencies(List<? extends Type> ts) {
+                if (ts != null) {
+                    for (Type t: ts)
+                        t.accept(this, null);
+                }
+            }
+
+            public Void visitSimpleType(SimpleType type, Void p) {
+                return null;
+            }
+
+            public Void visitArrayType(ArrayType type, Void p) {
+                findDependencies(type.elemType);
+                return null;
+            }
+
+            public Void visitMethodType(MethodType type, Void p) {
+                findDependencies(type.paramTypes);
+                findDependencies(type.returnType);
+                findDependencies(type.throwsTypes);
+                return null;
+            }
+
+            public Void visitClassSigType(ClassSigType type, Void p) {
+                findDependencies(type.superclassType);
+                findDependencies(type.superinterfaceTypes);
+                return null;
+            }
+
+            public Void visitClassType(ClassType type, Void p) {
+                findDependencies(type.outerType);
+                addDependency(type.name);
+                findDependencies(type.typeArgs);
+                return null;
+            }
+
+            public Void visitTypeParamType(TypeParamType type, Void p) {
+                findDependencies(type.classBound);
+                findDependencies(type.interfaceBounds);
+                return null;
+            }
+
+            public Void visitWildcardType(WildcardType type, Void p) {
+                findDependencies(type.boundType);
+                return null;
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/share/classes/com/sun/tools/classfile/Dependency.java	Fri Jan 15 15:36:54 2010 -0800
@@ -0,0 +1,90 @@
+/*
+ * 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.
+ */
+
+package com.sun.tools.classfile;
+
+
+/**
+ * A directed relationship between two {@link Dependency.Location Location}s.
+ * Subtypes of {@code Dependency} may provide additional detail about the dependency.
+ *
+ * @see Dependency.Finder
+ * @see Dependency.Filter
+ * @see Dependencies
+ */
+public interface Dependency {
+    /**
+     * A filter used to select dependencies of interest, and to discard others.
+     */
+    public interface Filter {
+        /**
+         * Return true if the dependency is of interest.
+         * @param dependency the dependency to be considered
+         * @return true if and only if the dependency is of interest.
+         */
+        boolean accepts(Dependency dependency);
+    }
+
+    /**
+     * An interface for finding the immediate dependencies of a given class file.
+     */
+    public interface Finder {
+        /**
+         * Find the immediate dependencies of a given class file.
+         * @param classfile the class file to be examined
+         * @return the dependencies located in the given class file.
+         */
+        public Iterable<? extends Dependency> findDependencies(ClassFile classfile);
+    }
+
+
+    /**
+     * A location somewhere within a class. Subtypes of {@code Location}
+     * may be used to provide additional detail about the location.
+     */
+    public interface Location {
+        /**
+         * Get the name of the class containing the location.
+         * This name will be used to locate the class file for transitive
+         * dependency analysis.
+         * @return the name of the class containing the location.
+         */
+        String getClassName();
+    }
+
+
+    /**
+     * Get the location that has the dependency.
+     * @return the location that has the dependency.
+     */
+    Location getOrigin();
+
+    /**
+     * Get the location that is being depended upon.
+     * @return the location that is being depended upon.
+     */
+    Location getTarget();
+}
+
--- a/langtools/src/share/classes/com/sun/tools/javac/file/BaseFileObject.java	Fri Jan 15 16:31:16 2010 +0000
+++ b/langtools/src/share/classes/com/sun/tools/javac/file/BaseFileObject.java	Fri Jan 15 15:36:54 2010 -0800
@@ -39,6 +39,8 @@
 
 import static javax.tools.JavaFileObject.Kind.*;
 
+import com.sun.tools.javac.util.BaseFileManager;
+
 /**
  * <p><b>This is NOT part of any API supported by Sun Microsystems.
  * If you write code that depends on this, you do so at your own risk.
@@ -74,14 +76,7 @@
     protected abstract String inferBinaryName(Iterable<? extends File> path);
 
     protected static JavaFileObject.Kind getKind(String filename) {
-        if (filename.endsWith(CLASS.extension))
-            return CLASS;
-        else if (filename.endsWith(SOURCE.extension))
-            return SOURCE;
-        else if (filename.endsWith(HTML.extension))
-            return HTML;
-        else
-            return OTHER;
+        return BaseFileManager.getKind(filename);
     }
 
     protected static String removeExtension(String fileName) {
--- a/langtools/src/share/classes/com/sun/tools/javac/file/CloseableURLClassLoader.java	Fri Jan 15 16:31:16 2010 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,107 +0,0 @@
-/*
- * Copyright 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.  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 com.sun.tools.javac.file;
-
-import java.io.Closeable;
-import java.io.IOException;
-import java.lang.reflect.Field;
-import java.net.URL;
-import java.net.URLClassLoader;
-import java.util.ArrayList;
-import java.util.jar.JarFile;
-
-/**
- * A URLClassLoader that also implements Closeable.
- * Reflection is used to access internal data structures in the URLClassLoader,
- * since no public API exists for this purpose. Therefore this code is somewhat
- * fragile. Caveat emptor.
- * @throws Error if the internal data structures are not as expected.
- *
- *  <p><b>This is NOT part of any API supported by Sun Microsystems.  If
- *  you write code that depends on this, you do so at your own risk.
- *  This code and its internal interfaces are subject to change or
- *  deletion without notice.</b>
- */
-class CloseableURLClassLoader
-        extends URLClassLoader implements Closeable {
-    CloseableURLClassLoader(URL[] urls, ClassLoader parent) throws Error {
-        super(urls, parent);
-        try {
-            getLoaders(); //proactive check that URLClassLoader is as expected
-        } catch (Throwable t) {
-            throw new Error("cannot create CloseableURLClassLoader", t);
-        }
-    }
-
-    /**
-     * Close any jar files that may have been opened by the class loader.
-     * Reflection is used to access the jar files in the URLClassLoader's
-     * internal data structures.
-     * @throws java.io.IOException if the jar files cannot be found for any
-     * reson, or if closing the jar file itself causes an IOException.
-     */
-    public void close() throws IOException {
-        try {
-            for (Object l: getLoaders()) {
-                if (l.getClass().getName().equals("sun.misc.URLClassPath$JarLoader")) {
-                    Field jarField = l.getClass().getDeclaredField("jar");
-                    JarFile jar = (JarFile) getField(l, jarField);
-                    if (jar != null) {
-                        //System.err.println("CloseableURLClassLoader: closing " + jar);
-                        jar.close();
-                    }
-                }
-            }
-        } catch (Throwable t) {
-            IOException e = new IOException("cannot close class loader");
-            e.initCause(t);
-            throw e;
-        }
-    }
-
-    private ArrayList<?> getLoaders()
-            throws NoSuchFieldException, IllegalArgumentException, IllegalAccessException
-    {
-        Field ucpField = URLClassLoader.class.getDeclaredField("ucp");
-        Object urlClassPath = getField(this, ucpField);
-        if (urlClassPath == null)
-            throw new AssertionError("urlClassPath not set in URLClassLoader");
-        Field loadersField = urlClassPath.getClass().getDeclaredField("loaders");
-        return (ArrayList<?>) getField(urlClassPath, loadersField);
-    }
-
-    private Object getField(Object o, Field f)
-            throws IllegalArgumentException, IllegalAccessException {
-        boolean prev = f.isAccessible();
-        try {
-            f.setAccessible(true);
-            return f.get(o);
-        } finally {
-            f.setAccessible(prev);
-        }
-    }
-
-}
--- a/langtools/src/share/classes/com/sun/tools/javac/file/JavacFileManager.java	Fri Jan 15 16:31:16 2010 +0000
+++ b/langtools/src/share/classes/com/sun/tools/javac/file/JavacFileManager.java	Fri Jan 15 15:36:54 2010 -0800
@@ -26,29 +26,16 @@
 package com.sun.tools.javac.file;
 
 import java.io.ByteArrayOutputStream;
-import java.io.Closeable;
 import java.io.File;
-import java.io.FileInputStream;
 import java.io.FileNotFoundException;
 import java.io.IOException;
-import java.io.InputStream;
 import java.io.OutputStreamWriter;
-import java.lang.ref.SoftReference;
-import java.lang.reflect.Constructor;
 import java.net.MalformedURLException;
 import java.net.URI;
 import java.net.URISyntaxException;
 import java.net.URL;
-import java.net.URLClassLoader;
-import java.nio.ByteBuffer;
 import java.nio.CharBuffer;
-import java.nio.channels.FileChannel;
 import java.nio.charset.Charset;
-import java.nio.charset.CharsetDecoder;
-import java.nio.charset.CoderResult;
-import java.nio.charset.CodingErrorAction;
-import java.nio.charset.IllegalCharsetNameException;
-import java.nio.charset.UnsupportedCharsetException;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
@@ -66,18 +53,13 @@
 import javax.tools.JavaFileObject;
 import javax.tools.StandardJavaFileManager;
 
-import com.sun.tools.javac.code.Source;
 import com.sun.tools.javac.file.RelativePath.RelativeFile;
 import com.sun.tools.javac.file.RelativePath.RelativeDirectory;
-import com.sun.tools.javac.main.JavacOption;
 import com.sun.tools.javac.main.OptionName;
-import com.sun.tools.javac.main.RecognizedOptions;
+import com.sun.tools.javac.util.BaseFileManager;
 import com.sun.tools.javac.util.Context;
-import com.sun.tools.javac.util.JCDiagnostic.SimpleDiagnosticPosition;
 import com.sun.tools.javac.util.List;
 import com.sun.tools.javac.util.ListBuffer;
-import com.sun.tools.javac.util.Log;
-import com.sun.tools.javac.util.Options;
 
 import static javax.tools.StandardLocation.*;
 import static com.sun.tools.javac.main.OptionName.*;
@@ -91,7 +73,7 @@
  * This code and its internal interfaces are subject to change or
  * deletion without notice.</b>
  */
-public class JavacFileManager implements StandardJavaFileManager {
+public class JavacFileManager extends BaseFileManager implements StandardJavaFileManager {
 
     boolean useZipFileIndex;
 
@@ -102,17 +84,10 @@
             return buffer.toString().toCharArray();
     }
 
-    /**
-     * The log to be used for error reporting.
-     */
-    protected Log log;
-
     /** Encapsulates knowledge of paths
      */
     private Paths paths;
 
-    private Options options;
-
     private FSInfo fsInfo;
 
     private final File uninited = new File("U N I N I T E D");
@@ -134,12 +109,6 @@
 
     protected boolean mmappedIO;
     protected boolean ignoreSymbolFile;
-    protected String classLoaderClass;
-
-    /**
-     * User provided charset (through javax.tools).
-     */
-    protected Charset charset;
 
     /**
      * Register a Context.Factory to create a JavacFileManager.
@@ -157,18 +126,18 @@
      * it as the JavaFileManager for that context.
      */
     public JavacFileManager(Context context, boolean register, Charset charset) {
+        super(charset);
         if (register)
             context.put(JavaFileManager.class, this);
-        byteBufferCache = new ByteBufferCache();
-        this.charset = charset;
         setContext(context);
     }
 
     /**
      * Set the context for JavacFileManager.
      */
+    @Override
     public void setContext(Context context) {
-        log = Log.instance(context);
+        super.setContext(context);
         if (paths == null) {
             paths = Paths.instance(context);
         } else {
@@ -177,14 +146,12 @@
             paths.setContext(context);
         }
 
-        options = Options.instance(context);
         fsInfo = FSInfo.instance(context);
 
         useZipFileIndex = System.getProperty("useJavaUtilZip") == null;// TODO: options.get("useJavaUtilZip") == null;
 
         mmappedIO = options.get("mmappedIO") != null;
         ignoreSymbolFile = options.get("ignore.symbol.file") != null;
-        classLoaderClass = options.get("procloader");
     }
 
     public JavaFileObject getFileForInput(String name) {
@@ -214,17 +181,6 @@
         return getJavaFileObjectsFromStrings(Arrays.asList(nullCheck(names)));
     }
 
-    protected JavaFileObject.Kind getKind(String extension) {
-        if (extension.equals(JavaFileObject.Kind.CLASS.extension))
-            return JavaFileObject.Kind.CLASS;
-        else if (extension.equals(JavaFileObject.Kind.SOURCE.extension))
-            return JavaFileObject.Kind.SOURCE;
-        else if (extension.equals(JavaFileObject.Kind.HTML.extension))
-            return JavaFileObject.Kind.HTML;
-        else
-            return JavaFileObject.Kind.OTHER;
-    }
-
     private static boolean isValidName(String name) {
         // Arguably, isValidName should reject keywords (such as in SourceVersion.isName() ),
         // but the set of keywords depends on the source level, and we don't want
@@ -359,9 +315,7 @@
     }
 
     private boolean isValidFile(String s, Set<JavaFileObject.Kind> fileKinds) {
-        int lastDot = s.lastIndexOf(".");
-        String extn = (lastDot == -1 ? s : s.substring(lastDot));
-        JavaFileObject.Kind kind = getKind(extn);
+        JavaFileObject.Kind kind = getKind(s);
         return fileKinds.contains(kind);
     }
 
@@ -564,18 +518,6 @@
         }
     }
 
-    CharBuffer getCachedContent(JavaFileObject file) {
-        SoftReference<CharBuffer> r = contentCache.get(file);
-        return (r == null ? null : r.get());
-    }
-
-    void cache(JavaFileObject file, CharBuffer cb) {
-        contentCache.put(file, new SoftReference<CharBuffer>(cb));
-    }
-
-    private final Map<JavaFileObject, SoftReference<CharBuffer>> contentCache
-            = new HashMap<JavaFileObject, SoftReference<CharBuffer>>();
-
     private String defaultEncodingName;
     private String getDefaultEncodingName() {
         if (defaultEncodingName == null) {
@@ -585,161 +527,6 @@
         return defaultEncodingName;
     }
 
-    protected String getEncodingName() {
-        String encName = options.get(OptionName.ENCODING);
-        if (encName == null)
-            return getDefaultEncodingName();
-        else
-            return encName;
-    }
-
-    protected Source getSource() {
-        String sourceName = options.get(OptionName.SOURCE);
-        Source source = null;
-        if (sourceName != null)
-            source = Source.lookup(sourceName);
-        return (source != null ? source : Source.DEFAULT);
-    }
-
-    /**
-     * Make a byte buffer from an input stream.
-     */
-    ByteBuffer makeByteBuffer(InputStream in)
-        throws IOException {
-        int limit = in.available();
-        if (mmappedIO && in instanceof FileInputStream) {
-            // Experimental memory mapped I/O
-            FileInputStream fin = (FileInputStream)in;
-            return fin.getChannel().map(FileChannel.MapMode.READ_ONLY, 0, limit);
-        }
-        if (limit < 1024) limit = 1024;
-        ByteBuffer result = byteBufferCache.get(limit);
-        int position = 0;
-        while (in.available() != 0) {
-            if (position >= limit)
-                // expand buffer
-                result = ByteBuffer.
-                    allocate(limit <<= 1).
-                    put((ByteBuffer)result.flip());
-            int count = in.read(result.array(),
-                position,
-                limit - position);
-            if (count < 0) break;
-            result.position(position += count);
-        }
-        return (ByteBuffer)result.flip();
-    }
-
-    void recycleByteBuffer(ByteBuffer bb) {
-        byteBufferCache.put(bb);
-    }
-
-    /**
-     * A single-element cache of direct byte buffers.
-     */
-    private static class ByteBufferCache {
-        private ByteBuffer cached;
-        ByteBuffer get(int capacity) {
-            if (capacity < 20480) capacity = 20480;
-            ByteBuffer result =
-                (cached != null && cached.capacity() >= capacity)
-                ? (ByteBuffer)cached.clear()
-                : ByteBuffer.allocate(capacity + capacity>>1);
-            cached = null;
-            return result;
-        }
-        void put(ByteBuffer x) {
-            cached = x;
-        }
-    }
-
-    private final ByteBufferCache byteBufferCache;
-
-    CharsetDecoder getDecoder(String encodingName, boolean ignoreEncodingErrors) {
-        Charset cs = (this.charset == null)
-            ? Charset.forName(encodingName)
-            : this.charset;
-        CharsetDecoder decoder = cs.newDecoder();
-
-        CodingErrorAction action;
-        if (ignoreEncodingErrors)
-            action = CodingErrorAction.REPLACE;
-        else
-            action = CodingErrorAction.REPORT;
-
-        return decoder
-            .onMalformedInput(action)
-            .onUnmappableCharacter(action);
-    }
-
-    /**
-     * Decode a ByteBuffer into a CharBuffer.
-     */
-    CharBuffer decode(ByteBuffer inbuf, boolean ignoreEncodingErrors) {
-        String encodingName = getEncodingName();
-        CharsetDecoder decoder;
-        try {
-            decoder = getDecoder(encodingName, ignoreEncodingErrors);
-        } catch (IllegalCharsetNameException e) {
-            log.error("unsupported.encoding", encodingName);
-            return (CharBuffer)CharBuffer.allocate(1).flip();
-        } catch (UnsupportedCharsetException e) {
-            log.error("unsupported.encoding", encodingName);
-            return (CharBuffer)CharBuffer.allocate(1).flip();
-        }
-
-        // slightly overestimate the buffer size to avoid reallocation.
-        float factor =
-            decoder.averageCharsPerByte() * 0.8f +
-            decoder.maxCharsPerByte() * 0.2f;
-        CharBuffer dest = CharBuffer.
-            allocate(10 + (int)(inbuf.remaining()*factor));
-
-        while (true) {
-            CoderResult result = decoder.decode(inbuf, dest, true);
-            dest.flip();
-
-            if (result.isUnderflow()) { // done reading
-                // make sure there is at least one extra character
-                if (dest.limit() == dest.capacity()) {
-                    dest = CharBuffer.allocate(dest.capacity()+1).put(dest);
-                    dest.flip();
-                }
-                return dest;
-            } else if (result.isOverflow()) { // buffer too small; expand
-                int newCapacity =
-                    10 + dest.capacity() +
-                    (int)(inbuf.remaining()*decoder.maxCharsPerByte());
-                dest = CharBuffer.allocate(newCapacity).put(dest);
-            } else if (result.isMalformed() || result.isUnmappable()) {
-                // bad character in input
-
-                // report coding error (warn only pre 1.5)
-                if (!getSource().allowEncodingErrors()) {
-                    log.error(new SimpleDiagnosticPosition(dest.limit()),
-                              "illegal.char.for.encoding",
-                              charset == null ? encodingName : charset.name());
-                } else {
-                    log.warning(new SimpleDiagnosticPosition(dest.limit()),
-                                "illegal.char.for.encoding",
-                                charset == null ? encodingName : charset.name());
-                }
-
-                // skip past the coding error
-                inbuf.position(inbuf.position() + result.length());
-
-                // undo the flip() to prepare the output buffer
-                // for more translation
-                dest.position(dest.limit());
-                dest.limit(dest.capacity());
-                dest.put((char)0xfffd); // backward compatible
-            } else {
-                throw new AssertionError(result);
-            }
-        }
-        // unreached
-    }
-
     public ClassLoader getClassLoader(Location location) {
         nullCheck(location);
         Iterable<? extends File> path = getLocation(location);
@@ -754,39 +541,7 @@
             }
         }
 
-        URL[] urls = lb.toArray(new URL[lb.size()]);
-        ClassLoader thisClassLoader = getClass().getClassLoader();
-
-        // Bug: 6558476
-        // Ideally, ClassLoader should be Closeable, but before JDK7 it is not.
-        // On older versions, try the following, to get a closeable classloader.
-
-        // 1: Allow client to specify the class to use via hidden option
-        if (classLoaderClass != null) {
-            try {
-                Class<? extends ClassLoader> loader =
-                        Class.forName(classLoaderClass).asSubclass(ClassLoader.class);
-                Class<?>[] constrArgTypes = { URL[].class, ClassLoader.class };
-                Constructor<? extends ClassLoader> constr = loader.getConstructor(constrArgTypes);
-                return constr.newInstance(new Object[] { urls, thisClassLoader });
-            } catch (Throwable t) {
-                // ignore errors loading user-provided class loader, fall through
-            }
-        }
-
-        // 2: If URLClassLoader implements Closeable, use that.
-        if (Closeable.class.isAssignableFrom(URLClassLoader.class))
-            return new URLClassLoader(urls, thisClassLoader);
-
-        // 3: Try using private reflection-based CloseableURLClassLoader
-        try {
-            return new CloseableURLClassLoader(urls, thisClassLoader);
-        } catch (Throwable t) {
-            // ignore errors loading workaround class loader, fall through
-        }
-
-        // 4: If all else fails, use plain old standard URLClassLoader
-        return new URLClassLoader(urls, thisClassLoader);
+        return getClassLoader(lb.toArray(new URL[lb.size()]));
     }
 
     public Iterable<JavaFileObject> list(Location location,
@@ -836,38 +591,6 @@
         return a.equals(b);
     }
 
-    public boolean handleOption(String current, Iterator<String> remaining) {
-        for (JavacOption o: javacFileManagerOptions) {
-            if (o.matches(current))  {
-                if (o.hasArg()) {
-                    if (remaining.hasNext()) {
-                        if (!o.process(options, current, remaining.next()))
-                            return true;
-                    }
-                } else {
-                    if (!o.process(options, current))
-                        return true;
-                }
-                // operand missing, or process returned false
-                throw new IllegalArgumentException(current);
-            }
-        }
-
-        return false;
-    }
-    // where
-        private static JavacOption[] javacFileManagerOptions =
-            RecognizedOptions.getJavacFileManagerOptions(
-            new RecognizedOptions.GrumpyHelper());
-
-    public int isSupportedOption(String option) {
-        for (JavacOption o : javacFileManagerOptions) {
-            if (o.matches(option))
-                return o.hasArg() ? 1 : 0;
-        }
-        return -1;
-    }
-
     public boolean hasLocation(Location location) {
         return getLocation(location) != null;
     }
@@ -1115,15 +838,4 @@
         }
         throw new IllegalArgumentException("Invalid relative path: " + file);
     }
-
-    private static <T> T nullCheck(T o) {
-        o.getClass(); // null check
-        return o;
-    }
-
-    private static <T> Iterable<T> nullCheck(Iterable<T> it) {
-        for (T t : it)
-            t.getClass(); // null check
-        return it;
-    }
 }
--- a/langtools/src/share/classes/com/sun/tools/javac/file/Paths.java	Fri Jan 15 16:31:16 2010 +0000
+++ b/langtools/src/share/classes/com/sun/tools/javac/file/Paths.java	Fri Jan 15 15:36:54 2010 -0800
@@ -66,7 +66,7 @@
      *  @param context the context
      *  @return the Paths instance for this context
      */
-    static Paths instance(Context context) {
+    public static Paths instance(Context context) {
         Paths instance = context.get(pathsKey);
         if (instance == null)
             instance = new Paths(context);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/share/classes/com/sun/tools/javac/nio/JavacPathFileManager.java	Fri Jan 15 15:36:54 2010 -0800
@@ -0,0 +1,543 @@
+/*
+ * 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.
+ */
+
+package com.sun.tools.javac.nio;
+
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.nio.charset.Charset;
+import java.nio.file.Files;
+import java.nio.file.FileSystem;
+import java.nio.file.FileSystems;
+import java.nio.file.FileVisitOption;
+import java.nio.file.FileVisitResult;
+import java.nio.file.Path;
+import java.nio.file.SimpleFileVisitor;
+import java.nio.file.attribute.Attributes;
+import java.nio.file.attribute.BasicFileAttributes;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.EnumSet;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedHashSet;
+import java.util.Map;
+import java.util.Set;
+import javax.lang.model.SourceVersion;
+import javax.tools.FileObject;
+import javax.tools.JavaFileManager;
+import javax.tools.JavaFileObject;
+import javax.tools.JavaFileObject.Kind;
+import javax.tools.StandardLocation;
+
+import static java.nio.file.FileVisitOption.*;
+import static javax.tools.StandardLocation.*;
+
+import com.sun.tools.javac.file.Paths;
+import com.sun.tools.javac.util.BaseFileManager;
+import com.sun.tools.javac.util.Context;
+import com.sun.tools.javac.util.List;
+import com.sun.tools.javac.util.ListBuffer;
+
+import static com.sun.tools.javac.main.OptionName.*;
+
+
+// NOTE the imports carefully for this compilation unit.
+//
+// Path:  java.nio.file.Path -- the new NIO type for which this file manager exists
+//
+// Paths: com.sun.tools.javac.file.Paths -- legacy javac type for handling path options
+//      The other Paths (java.nio.file.Paths) is not used
+
+// NOTE this and related classes depend on new API in JDK 7.
+// This requires special handling while bootstrapping the JDK build,
+// when these classes might not yet have been compiled. To workaround
+// this, the build arranges to make stubs of these classes available
+// when compiling this and related classes. The set of stub files
+// is specified in make/build.properties.
+
+/**
+ *  Implementation of PathFileManager: a JavaFileManager based on the use
+ *  of java.nio.file.Path.
+ *
+ *  <p>Just as a Path is somewhat analagous to a File, so too is this
+ *  JavacPathFileManager analogous to JavacFileManager, as it relates to the
+ *  support of FileObjects based on File objects (i.e. just RegularFileObject,
+ *  not ZipFileObject and its variants.)
+ *
+ *  <p>The default values for the standard locations supported by this file
+ *  manager are the same as the default values provided by JavacFileManager --
+ *  i.e. as determined by the javac.file.Paths class. To override these values,
+ *  call {@link #setLocation}.
+ *
+ *  <p>To reduce confusion with Path objects, the locations such as "class path",
+ *  "source path", etc, are generically referred to here as "search paths".
+ *
+ *  <p><b>This is NOT part of any API supported by Sun Microsystems.  If
+ *  you write code that depends on this, you do so at your own risk.
+ *  This code and its internal interfaces are subject to change or
+ *  deletion without notice.</b>
+ */
+public class JavacPathFileManager extends BaseFileManager implements PathFileManager {
+    protected FileSystem defaultFileSystem;
+
+    /**
+     * Create a JavacPathFileManager using a given context, optionally registering
+     * it as the JavaFileManager for that context.
+     */
+    public JavacPathFileManager(Context context, boolean register, Charset charset) {
+        super(charset);
+        if (register)
+            context.put(JavaFileManager.class, this);
+        pathsForLocation = new HashMap<Location, PathsForLocation>();
+        fileSystems = new HashMap<Path,FileSystem>();
+        setContext(context);
+    }
+
+    /**
+     * Set the context for JavacPathFileManager.
+     */
+    @Override
+    protected void setContext(Context context) {
+        super.setContext(context);
+        searchPaths = Paths.instance(context);
+    }
+
+    @Override
+    public FileSystem getDefaultFileSystem() {
+        if (defaultFileSystem == null)
+            defaultFileSystem = FileSystems.getDefault();
+        return defaultFileSystem;
+    }
+
+    @Override
+    public void setDefaultFileSystem(FileSystem fs) {
+        defaultFileSystem = fs;
+    }
+
+    @Override
+    public void flush() throws IOException {
+        contentCache.clear();
+    }
+
+    @Override
+    public void close() throws IOException {
+        for (FileSystem fs: fileSystems.values())
+            fs.close();
+    }
+
+    @Override
+    public ClassLoader getClassLoader(Location location) {
+        nullCheck(location);
+        Iterable<? extends Path> path = getLocation(location);
+        if (path == null)
+            return null;
+        ListBuffer<URL> lb = new ListBuffer<URL>();
+        for (Path p: path) {
+            try {
+                lb.append(p.toUri().toURL());
+            } catch (MalformedURLException e) {
+                throw new AssertionError(e);
+            }
+        }
+
+        return getClassLoader(lb.toArray(new URL[lb.size()]));
+    }
+
+    // <editor-fold defaultstate="collapsed" desc="Location handling">
+
+    public boolean hasLocation(Location location) {
+        return (getLocation(location) != null);
+    }
+
+    public Iterable<? extends Path> getLocation(Location location) {
+        nullCheck(location);
+        lazyInitSearchPaths();
+        PathsForLocation path = pathsForLocation.get(location);
+        if (path == null && !pathsForLocation.containsKey(location)) {
+            setDefaultForLocation(location);
+            path = pathsForLocation.get(location);
+        }
+        return path;
+    }
+
+    private Path getOutputLocation(Location location) {
+        Iterable<? extends Path> paths = getLocation(location);
+        return (paths == null ? null : paths.iterator().next());
+    }
+
+    public void setLocation(Location location, Iterable<? extends Path> searchPath)
+            throws IOException
+    {
+        nullCheck(location);
+        lazyInitSearchPaths();
+        if (searchPath == null) {
+            setDefaultForLocation(location);
+        } else {
+            if (location.isOutputLocation())
+                checkOutputPath(searchPath);
+            PathsForLocation pl = new PathsForLocation();
+            for (Path p: searchPath)
+                pl.add(p);  // TODO -Xlint:path warn if path not found
+            pathsForLocation.put(location, pl);
+        }
+    }
+
+    private void checkOutputPath(Iterable<? extends Path> searchPath) throws IOException {
+        Iterator<? extends Path> pathIter = searchPath.iterator();
+        if (!pathIter.hasNext())
+            throw new IllegalArgumentException("empty path for directory");
+        Path path = pathIter.next();
+        if (pathIter.hasNext())
+            throw new IllegalArgumentException("path too long for directory");
+        if (!path.exists())
+            throw new FileNotFoundException(path + ": does not exist");
+        else if (!isDirectory(path))
+            throw new IOException(path + ": not a directory");
+    }
+
+    private void setDefaultForLocation(Location locn) {
+        Collection<File> files = null;
+        if (locn instanceof StandardLocation) {
+            switch ((StandardLocation) locn) {
+                case CLASS_PATH:
+                    files = searchPaths.userClassPath();
+                    break;
+                case PLATFORM_CLASS_PATH:
+                    files = searchPaths.bootClassPath();
+                    break;
+                case SOURCE_PATH:
+                    files = searchPaths.sourcePath();
+                    break;
+                case CLASS_OUTPUT: {
+                    String arg = options.get(D);
+                    files = (arg == null ? null : Collections.singleton(new File(arg)));
+                    break;
+                }
+                case SOURCE_OUTPUT: {
+                    String arg = options.get(S);
+                    files = (arg == null ? null : Collections.singleton(new File(arg)));
+                    break;
+                }
+            }
+        }
+
+        PathsForLocation pl = new PathsForLocation();
+        if (files != null) {
+            for (File f: files)
+                pl.add(f.toPath());
+        }
+        pathsForLocation.put(locn, pl);
+    }
+
+    private void lazyInitSearchPaths() {
+        if (!inited) {
+            setDefaultForLocation(PLATFORM_CLASS_PATH);
+            setDefaultForLocation(CLASS_PATH);
+            setDefaultForLocation(SOURCE_PATH);
+            inited = true;
+        }
+    }
+    // where
+        private boolean inited = false;
+
+    private Map<Location, PathsForLocation> pathsForLocation;
+    private Paths searchPaths;
+
+    private static class PathsForLocation extends LinkedHashSet<Path> {
+        private static final long serialVersionUID = 6788510222394486733L;
+    }
+
+    // </editor-fold>
+
+    // <editor-fold defaultstate="collapsed" desc="FileObject handling">
+
+    @Override
+    public Path getPath(FileObject fo) {
+        nullCheck(fo);
+        if (!(fo instanceof PathFileObject))
+            throw new IllegalArgumentException();
+        return ((PathFileObject) fo).getPath();
+    }
+
+    @Override
+    public boolean isSameFile(FileObject a, FileObject b) {
+        nullCheck(a);
+        nullCheck(b);
+        if (!(a instanceof PathFileObject))
+            throw new IllegalArgumentException("Not supported: " + a);
+        if (!(b instanceof PathFileObject))
+            throw new IllegalArgumentException("Not supported: " + b);
+        return ((PathFileObject) a).isSameFile((PathFileObject) b);
+    }
+
+    @Override
+    public Iterable<JavaFileObject> list(Location location,
+            String packageName, Set<Kind> kinds, boolean recurse)
+            throws IOException {
+        // validatePackageName(packageName);
+        nullCheck(packageName);
+        nullCheck(kinds);
+
+        Iterable<? extends Path> paths = getLocation(location);
+        if (paths == null)
+            return List.nil();
+        ListBuffer<JavaFileObject> results = new ListBuffer<JavaFileObject>();
+
+        for (Path path : paths)
+            list(path, packageName, kinds, recurse, results);
+
+        return results.toList();
+    }
+
+    private void list(Path path, String packageName, final Set<Kind> kinds,
+            boolean recurse, final ListBuffer<JavaFileObject> results)
+            throws IOException {
+        if (!path.exists())
+            return;
+
+        final Path pathDir;
+        if (isDirectory(path))
+            pathDir = path;
+        else {
+            FileSystem fs = getFileSystem(path);
+            if (fs == null)
+                return;
+            pathDir = fs.getRootDirectories().iterator().next();
+        }
+        String sep = path.getFileSystem().getSeparator();
+        Path packageDir = packageName.isEmpty() ? pathDir
+                : pathDir.resolve(packageName.replace(".", sep));
+        if (!packageDir.exists())
+            return;
+
+/* Alternate impl of list, superceded by use of Files.walkFileTree */
+//        Deque<Path> queue = new LinkedList<Path>();
+//        queue.add(packageDir);
+//
+//        Path dir;
+//        while ((dir = queue.poll()) != null) {
+//            DirectoryStream<Path> ds = dir.newDirectoryStream();
+//            try {
+//                for (Path p: ds) {
+//                    String name = p.getName().toString();
+//                    if (isDirectory(p)) {
+//                        if (recurse && SourceVersion.isIdentifier(name)) {
+//                            queue.add(p);
+//                        }
+//                    } else {
+//                        if (kinds.contains(getKind(name))) {
+//                            JavaFileObject fe =
+//                                PathFileObject.createDirectoryPathFileObject(this, p, pathDir);
+//                            results.append(fe);
+//                        }
+//                    }
+//                }
+//            } finally {
+//                ds.close();
+//            }
+//        }
+        int maxDepth = (recurse ? Integer.MAX_VALUE : 1);
+        Set<FileVisitOption> opts = EnumSet.of(DETECT_CYCLES, FOLLOW_LINKS);
+        Files.walkFileTree(packageDir, opts, maxDepth,
+                new SimpleFileVisitor<Path>() {
+            @Override
+            public FileVisitResult preVisitDirectory(Path dir) {
+                if (SourceVersion.isIdentifier(dir.getName().toString())) // JSR 292?
+                    return FileVisitResult.CONTINUE;
+                else
+                    return FileVisitResult.SKIP_SUBTREE;
+            }
+
+            @Override
+            public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
+                if (attrs.isRegularFile() && kinds.contains(getKind(file.getName().toString()))) {
+                    JavaFileObject fe =
+                        PathFileObject.createDirectoryPathFileObject(
+                            JavacPathFileManager.this, file, pathDir);
+                    results.append(fe);
+                }
+                return FileVisitResult.CONTINUE;
+            }
+        });
+    }
+
+    @Override
+    public Iterable<? extends JavaFileObject> getJavaFileObjectsFromPaths(
+        Iterable<? extends Path> paths) {
+        ArrayList<PathFileObject> result;
+        if (paths instanceof Collection<?>)
+            result = new ArrayList<PathFileObject>(((Collection<?>)paths).size());
+        else
+            result = new ArrayList<PathFileObject>();
+        for (Path p: paths)
+            result.add(PathFileObject.createSimplePathFileObject(this, nullCheck(p)));
+        return result;
+    }
+
+    @Override
+    public Iterable<? extends JavaFileObject> getJavaFileObjects(Path... paths) {
+        return getJavaFileObjectsFromPaths(Arrays.asList(nullCheck(paths)));
+    }
+
+    @Override
+    public JavaFileObject getJavaFileForInput(Location location,
+            String className, Kind kind) throws IOException {
+        return getFileForInput(location, getRelativePath(className, kind));
+    }
+
+    @Override
+    public FileObject getFileForInput(Location location,
+            String packageName, String relativeName) throws IOException {
+        return getFileForInput(location, getRelativePath(packageName, relativeName));
+    }
+
+    private JavaFileObject getFileForInput(Location location, String relativePath)
+            throws IOException {
+        for (Path p: getLocation(location)) {
+            if (isDirectory(p)) {
+                Path f = resolve(p, relativePath);
+                if (f.exists())
+                    return PathFileObject.createDirectoryPathFileObject(this, f, p);
+            } else {
+                FileSystem fs = getFileSystem(p);
+                if (fs != null) {
+                    Path file = getPath(fs, relativePath);
+                    if (file.exists())
+                        return PathFileObject.createJarPathFileObject(this, file);
+                }
+            }
+        }
+        return null;
+    }
+
+    @Override
+    public JavaFileObject getJavaFileForOutput(Location location,
+            String className, Kind kind, FileObject sibling) throws IOException {
+        return getFileForOutput(location, getRelativePath(className, kind), sibling);
+    }
+
+    @Override
+    public FileObject getFileForOutput(Location location, String packageName,
+            String relativeName, FileObject sibling)
+            throws IOException {
+        return getFileForOutput(location, getRelativePath(packageName, relativeName), sibling);
+    }
+
+    private JavaFileObject getFileForOutput(Location location,
+            String relativePath, FileObject sibling) {
+        Path dir = getOutputLocation(location);
+        if (dir == null) {
+            if (location == CLASS_OUTPUT) {
+                Path siblingDir = null;
+                if (sibling != null && sibling instanceof PathFileObject) {
+                    siblingDir = ((PathFileObject) sibling).getPath().getParent();
+                }
+                return PathFileObject.createSiblingPathFileObject(this,
+                        siblingDir.resolve(getBaseName(relativePath)),
+                        relativePath);
+            } else if (location == SOURCE_OUTPUT) {
+                dir = getOutputLocation(CLASS_OUTPUT);
+            }
+        }
+
+        Path file;
+        if (dir != null) {
+            file = resolve(dir, relativePath);
+            return PathFileObject.createDirectoryPathFileObject(this, file, dir);
+        } else {
+            file = getPath(getDefaultFileSystem(), relativePath);
+            return PathFileObject.createSimplePathFileObject(this, file);
+        }
+
+    }
+
+    @Override
+    public String inferBinaryName(Location location, JavaFileObject fo) {
+        nullCheck(fo);
+        // Need to match the path semantics of list(location, ...)
+        Iterable<? extends Path> paths = getLocation(location);
+        if (paths == null) {
+            return null;
+        }
+
+        if (!(fo instanceof PathFileObject))
+            throw new IllegalArgumentException(fo.getClass().getName());
+
+        return ((PathFileObject) fo).inferBinaryName(paths);
+    }
+
+    private FileSystem getFileSystem(Path p) throws IOException {
+        FileSystem fs = fileSystems.get(p);
+        if (fs == null) {
+            fs = FileSystems.newFileSystem(p, Collections.<String,Void>emptyMap(), null);
+            fileSystems.put(p, fs);
+        }
+        return fs;
+    }
+
+    private Map<Path,FileSystem> fileSystems;
+
+    // </editor-fold>
+
+    // <editor-fold defaultstate="collapsed" desc="Utility methods">
+
+    private static String getRelativePath(String className, Kind kind) {
+        return className.replace(".", "/") + kind.extension;
+    }
+
+    private static String getRelativePath(String packageName, String relativeName) {
+        return packageName.replace(".", "/") + relativeName;
+    }
+
+    private static String getBaseName(String relativePath) {
+        int lastSep = relativePath.lastIndexOf("/");
+        return relativePath.substring(lastSep + 1); // safe if "/" not found
+    }
+
+    private static boolean isDirectory(Path path) throws IOException {
+        BasicFileAttributes attrs = Attributes.readBasicFileAttributes(path);
+        return attrs.isDirectory();
+    }
+
+    private static Path getPath(FileSystem fs, String relativePath) {
+        return fs.getPath(relativePath.replace("/", fs.getSeparator()));
+    }
+
+    private static Path resolve(Path base, String relativePath) {
+        FileSystem fs = base.getFileSystem();
+        Path rp = fs.getPath(relativePath.replace("/", fs.getSeparator()));
+        return base.resolve(rp);
+    }
+
+    // </editor-fold>
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/share/classes/com/sun/tools/javac/nio/PathFileManager.java	Fri Jan 15 15:36:54 2010 -0800
@@ -0,0 +1,125 @@
+/*
+ * 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.
+ */
+
+package com.sun.tools.javac.nio;
+
+import java.io.IOException;
+import java.nio.file.FileSystem;
+import java.nio.file.Path;
+import javax.tools.FileObject;
+import javax.tools.JavaFileManager;
+import javax.tools.JavaFileObject;
+
+/**
+ *  File manager based on {@linkplain File java.nio.file.Path}.
+ *
+ *  Eventually, this should be moved to javax.tools.
+ *  Also, JavaCompiler might reasonably provide a method getPathFileManager,
+ *  similar to {@link javax.tools.JavaCompiler#getStandardFileManager
+ *  getStandardFileManager}. However, would need to be handled carefully
+ *  as another forward reference from langtools to jdk.
+ *
+ *  <p><b>This is NOT part of any API supported by Sun Microsystems.  If
+ *  you write code that depends on this, you do so at your own risk.
+ *  This code and its internal interfaces are subject to change or
+ *  deletion without notice.</b>
+ */
+public interface PathFileManager extends JavaFileManager {
+    /**
+     * Get the default file system used to create paths. If no value has been
+     * set, the default file system is {@link FileSystems#getDefault}.
+     */
+    FileSystem getDefaultFileSystem();
+
+    /**
+     * Set the default file system used to create paths.
+     * @param fs the default file system used to create any new paths.
+     */
+    void setDefaultFileSystem(FileSystem fs);
+
+    /**
+     * Get file objects representing the given files.
+     *
+     * @param paths a list of paths
+     * @return a list of file objects
+     * @throws IllegalArgumentException if the list of paths includes
+     * a directory
+     */
+    Iterable<? extends JavaFileObject> getJavaFileObjectsFromPaths(
+        Iterable<? extends Path> paths);
+
+    /**
+     * Get file objects representing the given paths.
+     * Convenience method equivalent to:
+     *
+     * <pre>
+     *     getJavaFileObjectsFromPaths({@linkplain java.util.Arrays#asList Arrays.asList}(paths))
+     * </pre>
+     *
+     * @param paths an array of paths
+     * @return a list of file objects
+     * @throws IllegalArgumentException if the array of files includes
+     * a directory
+     * @throws NullPointerException if the given array contains null
+     * elements
+     */
+    Iterable<? extends JavaFileObject> getJavaFileObjects(Path... paths);
+
+    /**
+     * Return the Path for a file object that has been obtained from this
+     * file manager.
+     *
+     * @param fo A file object that has been obtained from this file manager.
+     * @return The underlying Path object.
+     * @throws IllegalArgumentException is the file object was not obtained from
+     * from this file manager.
+     */
+    Path getPath(FileObject fo);
+
+    /**
+     * Get the search path associated with the given location.
+     *
+     * @param location a location
+     * @return a list of paths or {@code null} if this location has no
+     * associated search path
+     * @see #setLocation
+     */
+    Iterable<? extends Path> getLocation(Location location);
+
+    /**
+     * Associate the given search path with the given location.  Any
+     * previous value will be discarded.
+     *
+     * @param location a location
+     * @param searchPath a list of files, if {@code null} use the default
+     * search path for this location
+     * @see #getLocation
+     * @throws IllegalArgumentException if location is an output
+     * location and searchpath does not contain exactly one element
+     * @throws IOException if location is an output location and searchpath
+     * does not represent an existing directory
+     */
+    void setLocation(Location location, Iterable<? extends Path> searchPath) throws IOException;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/share/classes/com/sun/tools/javac/nio/PathFileObject.java	Fri Jan 15 15:36:54 2010 -0800
@@ -0,0 +1,319 @@
+/*
+ * 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.
+ */
+
+package com.sun.tools.javac.nio;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.Reader;
+import java.io.Writer;
+import java.net.URI;
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.charset.CharsetDecoder;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.attribute.Attributes;
+import java.nio.file.attribute.BasicFileAttributes;
+import javax.lang.model.element.Modifier;
+import javax.lang.model.element.NestingKind;
+import javax.tools.JavaFileObject;
+
+import com.sun.tools.javac.util.BaseFileManager;
+
+
+/**
+ *  Implementation of JavaFileObject using java.nio.file API.
+ *
+ *  <p>PathFileObjects are, for the most part, straightforward wrappers around
+ *  Path objects. The primary complexity is the support for "inferBinaryName".
+ *  This is left as an abstract method, implemented by each of a number of
+ *  different factory methods, which compute the binary name based on
+ *  information available at the time the file object is created.
+ *
+ *  <p><b>This is NOT part of any API supported by Sun Microsystems.  If
+ *  you write code that depends on this, you do so at your own risk.
+ *  This code and its internal interfaces are subject to change or
+ *  deletion without notice.</b>
+ */
+abstract class PathFileObject implements JavaFileObject {
+    private JavacPathFileManager fileManager;
+    private Path path;
+
+    /**
+     * Create a PathFileObject within a directory, such that the binary name
+     * can be inferred from the relationship to the parent directory.
+     */
+    static PathFileObject createDirectoryPathFileObject(JavacPathFileManager fileManager,
+            final Path path, final Path dir) {
+        return new PathFileObject(fileManager, path) {
+            @Override
+            String inferBinaryName(Iterable<? extends Path> paths) {
+                return toBinaryName(dir.relativize(path));
+            }
+        };
+    }
+
+    /**
+     * Create a PathFileObject in a file system such as a jar file, such that
+     * the binary name can be inferred from its position within the filesystem.
+     */
+    static PathFileObject createJarPathFileObject(JavacPathFileManager fileManager,
+            final Path path) {
+        return new PathFileObject(fileManager, path) {
+            @Override
+            String inferBinaryName(Iterable<? extends Path> paths) {
+                return toBinaryName(path);
+            }
+        };
+    }
+
+    /**
+     * Create a PathFileObject whose binary name can be inferred from the
+     * relative path to a sibling.
+     */
+    static PathFileObject createSiblingPathFileObject(JavacPathFileManager fileManager,
+            final Path path, final String relativePath) {
+        return new PathFileObject(fileManager, path) {
+            @Override
+            String inferBinaryName(Iterable<? extends Path> paths) {
+                return toBinaryName(relativePath, "/");
+            }
+        };
+    }
+
+    /**
+     * Create a PathFileObject whose binary name might be inferred from its
+     * position on a search path.
+     */
+    static PathFileObject createSimplePathFileObject(JavacPathFileManager fileManager,
+            final Path path) {
+        return new PathFileObject(fileManager, path) {
+            @Override
+            String inferBinaryName(Iterable<? extends Path> paths) {
+                Path absPath = path.toAbsolutePath();
+                for (Path p: paths) {
+                    Path ap = p.toAbsolutePath();
+                    if (absPath.startsWith(ap)) {
+                        try {
+                            Path rp = ap.relativize(absPath);
+                            if (rp != null) // maybe null if absPath same as ap
+                                return toBinaryName(rp);
+                        } catch (IllegalArgumentException e) {
+                            // ignore this p if cannot relativize path to p
+                        }
+                    }
+                }
+                return null;
+            }
+        };
+    }
+
+    protected PathFileObject(JavacPathFileManager fileManager, Path path) {
+        fileManager.getClass(); // null check
+        path.getClass();        // null check
+        this.fileManager = fileManager;
+        this.path = path;
+    }
+
+    abstract String inferBinaryName(Iterable<? extends Path> paths);
+
+    /**
+     * Return the Path for this object.
+     * @return the Path for this object.
+     */
+    Path getPath() {
+        return path;
+    }
+
+    @Override
+    public Kind getKind() {
+        return BaseFileManager.getKind(path.getName().toString());
+    }
+
+    @Override
+    public boolean isNameCompatible(String simpleName, Kind kind) {
+        simpleName.getClass();
+        // null check
+        if (kind == Kind.OTHER && getKind() != kind) {
+            return false;
+        }
+        String sn = simpleName + kind.extension;
+        String pn = path.getName().toString();
+        if (pn.equals(sn)) {
+            return true;
+        }
+        if (pn.equalsIgnoreCase(sn)) {
+            try {
+                // allow for Windows
+                return path.toRealPath(false).getName().toString().equals(sn);
+            } catch (IOException e) {
+            }
+        }
+        return false;
+    }
+
+    @Override
+    public NestingKind getNestingKind() {
+        return null;
+    }
+
+    @Override
+    public Modifier getAccessLevel() {
+        return null;
+    }
+
+    @Override
+    public URI toUri() {
+        return path.toUri();
+    }
+
+    @Override
+    public String getName() {
+        return path.toString();
+    }
+
+    @Override
+    public InputStream openInputStream() throws IOException {
+        return path.newInputStream();
+    }
+
+    @Override
+    public OutputStream openOutputStream() throws IOException {
+        ensureParentDirectoriesExist();
+        return path.newOutputStream();
+    }
+
+    @Override
+    public Reader openReader(boolean ignoreEncodingErrors) throws IOException {
+        CharsetDecoder decoder = fileManager.getDecoder(fileManager.getEncodingName(), ignoreEncodingErrors);
+        return new InputStreamReader(openInputStream(), decoder);
+    }
+
+    @Override
+    public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
+        CharBuffer cb = fileManager.getCachedContent(this);
+        if (cb == null) {
+            InputStream in = openInputStream();
+            try {
+                ByteBuffer bb = fileManager.makeByteBuffer(in);
+                JavaFileObject prev = fileManager.log.useSource(this);
+                try {
+                    cb = fileManager.decode(bb, ignoreEncodingErrors);
+                } finally {
+                    fileManager.log.useSource(prev);
+                }
+                fileManager.recycleByteBuffer(bb);
+                if (!ignoreEncodingErrors) {
+                    fileManager.cache(this, cb);
+                }
+            } finally {
+                in.close();
+            }
+        }
+        return cb;
+    }
+
+    @Override
+    public Writer openWriter() throws IOException {
+        ensureParentDirectoriesExist();
+        return new OutputStreamWriter(path.newOutputStream(), fileManager.getEncodingName());
+    }
+
+    @Override
+    public long getLastModified() {
+        try {
+            BasicFileAttributes attrs = Attributes.readBasicFileAttributes(path);
+            return attrs.lastModifiedTime().toMillis();
+        } catch (IOException e) {
+            return -1;
+        }
+    }
+
+    @Override
+    public boolean delete() {
+        try {
+            path.delete();
+            return true;
+        } catch (IOException e) {
+            return false;
+        }
+    }
+
+    public boolean isSameFile(PathFileObject other) {
+        try {
+            return path.isSameFile(other.path);
+        } catch (IOException e) {
+            return false;
+        }
+    }
+
+    @Override
+    public boolean equals(Object other) {
+        return (other instanceof PathFileObject && path.equals(((PathFileObject) other).path));
+    }
+
+    @Override
+    public int hashCode() {
+        return path.hashCode();
+    }
+
+    @Override
+    public String toString() {
+        return getClass().getSimpleName() + "[" + path + "]";
+    }
+
+    private void ensureParentDirectoriesExist() throws IOException {
+        Path parent = path.getParent();
+        if (parent != null)
+            Files.createDirectories(parent);
+    }
+
+    private long size() {
+        try {
+            BasicFileAttributes attrs = Attributes.readBasicFileAttributes(path);
+            return attrs.size();
+        } catch (IOException e) {
+            return -1;
+        }
+    }
+
+    protected static String toBinaryName(Path relativePath) {
+        return toBinaryName(relativePath.toString(),
+                relativePath.getFileSystem().getSeparator());
+    }
+
+    protected static String toBinaryName(String relativePath, String sep) {
+        return removeExtension(relativePath).replaceAll(sep, ".");
+    }
+
+    protected static String removeExtension(String fileName) {
+        int lastDot = fileName.lastIndexOf(".");
+        return (lastDot == -1 ? fileName : fileName.substring(0, lastDot));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/share/classes/com/sun/tools/javac/util/BaseFileManager.java	Fri Jan 15 15:36:54 2010 -0800
@@ -0,0 +1,355 @@
+/*
+ * 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.
+ */
+
+package com.sun.tools.javac.util;
+
+import com.sun.tools.javac.code.Source;
+import com.sun.tools.javac.main.JavacOption;
+import com.sun.tools.javac.main.OptionName;
+import com.sun.tools.javac.main.RecognizedOptions;
+import com.sun.tools.javac.util.JCDiagnostic.SimpleDiagnosticPosition;
+import java.io.ByteArrayOutputStream;
+import java.io.Closeable;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStreamWriter;
+import java.lang.ref.SoftReference;
+import java.lang.reflect.Constructor;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.charset.Charset;
+import java.nio.charset.CharsetDecoder;
+import java.nio.charset.CoderResult;
+import java.nio.charset.CodingErrorAction;
+import java.nio.charset.IllegalCharsetNameException;
+import java.nio.charset.UnsupportedCharsetException;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import javax.tools.JavaFileObject;
+import javax.tools.JavaFileObject.Kind;
+
+/**
+ * Utility methods for building a filemanager.
+ * There are no references here to file-system specific objects such as
+ * java.io.File or java.nio.file.Path.
+ */
+public class BaseFileManager {
+    protected BaseFileManager(Charset charset) {
+        this.charset = charset;
+        byteBufferCache = new ByteBufferCache();
+    }
+
+    /**
+     * Set the context for JavacPathFileManager.
+     */
+    protected void setContext(Context context) {
+        log = Log.instance(context);
+        options = Options.instance(context);
+        classLoaderClass = options.get("procloader");
+    }
+
+    /**
+     * The log to be used for error reporting.
+     */
+    public Log log;
+
+    /**
+     * User provided charset (through javax.tools).
+     */
+    protected Charset charset;
+
+    protected Options options;
+
+    protected String classLoaderClass;
+
+    protected Source getSource() {
+        String sourceName = options.get(OptionName.SOURCE);
+        Source source = null;
+        if (sourceName != null)
+            source = Source.lookup(sourceName);
+        return (source != null ? source : Source.DEFAULT);
+    }
+
+    protected ClassLoader getClassLoader(URL[] urls) {
+        ClassLoader thisClassLoader = getClass().getClassLoader();
+
+        // Bug: 6558476
+        // Ideally, ClassLoader should be Closeable, but before JDK7 it is not.
+        // On older versions, try the following, to get a closeable classloader.
+
+        // 1: Allow client to specify the class to use via hidden option
+        if (classLoaderClass != null) {
+            try {
+                Class<? extends ClassLoader> loader =
+                        Class.forName(classLoaderClass).asSubclass(ClassLoader.class);
+                Class<?>[] constrArgTypes = { URL[].class, ClassLoader.class };
+                Constructor<? extends ClassLoader> constr = loader.getConstructor(constrArgTypes);
+                return constr.newInstance(new Object[] { urls, thisClassLoader });
+            } catch (Throwable t) {
+                // ignore errors loading user-provided class loader, fall through
+            }
+        }
+
+        // 2: If URLClassLoader implements Closeable, use that.
+        if (Closeable.class.isAssignableFrom(URLClassLoader.class))
+            return new URLClassLoader(urls, thisClassLoader);
+
+        // 3: Try using private reflection-based CloseableURLClassLoader
+        try {
+            return new CloseableURLClassLoader(urls, thisClassLoader);
+        } catch (Throwable t) {
+            // ignore errors loading workaround class loader, fall through
+        }
+
+        // 4: If all else fails, use plain old standard URLClassLoader
+        return new URLClassLoader(urls, thisClassLoader);
+    }
+
+    // <editor-fold defaultstate="collapsed" desc="Option handling">
+    public boolean handleOption(String current, Iterator<String> remaining) {
+        for (JavacOption o: javacFileManagerOptions) {
+            if (o.matches(current))  {
+                if (o.hasArg()) {
+                    if (remaining.hasNext()) {
+                        if (!o.process(options, current, remaining.next()))
+                            return true;
+                    }
+                } else {
+                    if (!o.process(options, current))
+                        return true;
+                }
+                // operand missing, or process returned false
+                throw new IllegalArgumentException(current);
+            }
+        }
+
+        return false;
+    }
+    // where
+        private static JavacOption[] javacFileManagerOptions =
+            RecognizedOptions.getJavacFileManagerOptions(
+            new RecognizedOptions.GrumpyHelper());
+
+    public int isSupportedOption(String option) {
+        for (JavacOption o : javacFileManagerOptions) {
+            if (o.matches(option))
+                return o.hasArg() ? 1 : 0;
+        }
+        return -1;
+    }
+    // </editor-fold>
+
+    // <editor-fold defaultstate="collapsed" desc="Encoding">
+    private String defaultEncodingName;
+    private String getDefaultEncodingName() {
+        if (defaultEncodingName == null) {
+            defaultEncodingName =
+                new OutputStreamWriter(new ByteArrayOutputStream()).getEncoding();
+        }
+        return defaultEncodingName;
+    }
+
+    public String getEncodingName() {
+        String encName = options.get(OptionName.ENCODING);
+        if (encName == null)
+            return getDefaultEncodingName();
+        else
+            return encName;
+    }
+
+    public CharBuffer decode(ByteBuffer inbuf, boolean ignoreEncodingErrors) {
+        String encodingName = getEncodingName();
+        CharsetDecoder decoder;
+        try {
+            decoder = getDecoder(encodingName, ignoreEncodingErrors);
+        } catch (IllegalCharsetNameException e) {
+            log.error("unsupported.encoding", encodingName);
+            return (CharBuffer)CharBuffer.allocate(1).flip();
+        } catch (UnsupportedCharsetException e) {
+            log.error("unsupported.encoding", encodingName);
+            return (CharBuffer)CharBuffer.allocate(1).flip();
+        }
+
+        // slightly overestimate the buffer size to avoid reallocation.
+        float factor =
+            decoder.averageCharsPerByte() * 0.8f +
+            decoder.maxCharsPerByte() * 0.2f;
+        CharBuffer dest = CharBuffer.
+            allocate(10 + (int)(inbuf.remaining()*factor));
+
+        while (true) {
+            CoderResult result = decoder.decode(inbuf, dest, true);
+            dest.flip();
+
+            if (result.isUnderflow()) { // done reading
+                // make sure there is at least one extra character
+                if (dest.limit() == dest.capacity()) {
+                    dest = CharBuffer.allocate(dest.capacity()+1).put(dest);
+                    dest.flip();
+                }
+                return dest;
+            } else if (result.isOverflow()) { // buffer too small; expand
+                int newCapacity =
+                    10 + dest.capacity() +
+                    (int)(inbuf.remaining()*decoder.maxCharsPerByte());
+                dest = CharBuffer.allocate(newCapacity).put(dest);
+            } else if (result.isMalformed() || result.isUnmappable()) {
+                // bad character in input
+
+                // report coding error (warn only pre 1.5)
+                if (!getSource().allowEncodingErrors()) {
+                    log.error(new SimpleDiagnosticPosition(dest.limit()),
+                              "illegal.char.for.encoding",
+                              charset == null ? encodingName : charset.name());
+                } else {
+                    log.warning(new SimpleDiagnosticPosition(dest.limit()),
+                                "illegal.char.for.encoding",
+                                charset == null ? encodingName : charset.name());
+                }
+
+                // skip past the coding error
+                inbuf.position(inbuf.position() + result.length());
+
+                // undo the flip() to prepare the output buffer
+                // for more translation
+                dest.position(dest.limit());
+                dest.limit(dest.capacity());
+                dest.put((char)0xfffd); // backward compatible
+            } else {
+                throw new AssertionError(result);
+            }
+        }
+        // unreached
+    }
+
+    public CharsetDecoder getDecoder(String encodingName, boolean ignoreEncodingErrors) {
+        Charset cs = (this.charset == null)
+            ? Charset.forName(encodingName)
+            : this.charset;
+        CharsetDecoder decoder = cs.newDecoder();
+
+        CodingErrorAction action;
+        if (ignoreEncodingErrors)
+            action = CodingErrorAction.REPLACE;
+        else
+            action = CodingErrorAction.REPORT;
+
+        return decoder
+            .onMalformedInput(action)
+            .onUnmappableCharacter(action);
+    }
+    // </editor-fold>
+
+    // <editor-fold defaultstate="collapsed" desc="ByteBuffers">
+    /**
+     * Make a byte buffer from an input stream.
+     */
+    public ByteBuffer makeByteBuffer(InputStream in)
+        throws IOException {
+        int limit = in.available();
+        if (limit < 1024) limit = 1024;
+        ByteBuffer result = byteBufferCache.get(limit);
+        int position = 0;
+        while (in.available() != 0) {
+            if (position >= limit)
+                // expand buffer
+                result = ByteBuffer.
+                    allocate(limit <<= 1).
+                    put((ByteBuffer)result.flip());
+            int count = in.read(result.array(),
+                position,
+                limit - position);
+            if (count < 0) break;
+            result.position(position += count);
+        }
+        return (ByteBuffer)result.flip();
+    }
+
+    public void recycleByteBuffer(ByteBuffer bb) {
+        byteBufferCache.put(bb);
+    }
+
+    /**
+     * A single-element cache of direct byte buffers.
+     */
+    private static class ByteBufferCache {
+        private ByteBuffer cached;
+        ByteBuffer get(int capacity) {
+            if (capacity < 20480) capacity = 20480;
+            ByteBuffer result =
+                (cached != null && cached.capacity() >= capacity)
+                ? (ByteBuffer)cached.clear()
+                : ByteBuffer.allocate(capacity + capacity>>1);
+            cached = null;
+            return result;
+        }
+        void put(ByteBuffer x) {
+            cached = x;
+        }
+    }
+
+    private final ByteBufferCache byteBufferCache;
+    // </editor-fold>
+
+    // <editor-fold defaultstate="collapsed" desc="Content cache">
+    public CharBuffer getCachedContent(JavaFileObject file) {
+        SoftReference<CharBuffer> r = contentCache.get(file);
+        return (r == null ? null : r.get());
+    }
+
+    public void cache(JavaFileObject file, CharBuffer cb) {
+        contentCache.put(file, new SoftReference<CharBuffer>(cb));
+    }
+
+    protected final Map<JavaFileObject, SoftReference<CharBuffer>> contentCache
+            = new HashMap<JavaFileObject, SoftReference<CharBuffer>>();
+    // </editor-fold>
+
+    public static Kind getKind(String name) {
+        if (name.endsWith(Kind.CLASS.extension))
+            return Kind.CLASS;
+        else if (name.endsWith(Kind.SOURCE.extension))
+            return Kind.SOURCE;
+        else if (name.endsWith(Kind.HTML.extension))
+            return Kind.HTML;
+        else
+            return Kind.OTHER;
+    }
+
+    protected static <T> T nullCheck(T o) {
+        o.getClass(); // null check
+        return o;
+    }
+
+    protected static <T> Collection<T> nullCheck(Collection<T> it) {
+        for (T t : it)
+            t.getClass(); // null check
+        return it;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/share/classes/com/sun/tools/javac/util/CloseableURLClassLoader.java	Fri Jan 15 15:36:54 2010 -0800
@@ -0,0 +1,108 @@
+/*
+ * Copyright 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.  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 com.sun.tools.javac.util;
+
+import java.io.Closeable;
+import java.io.IOException;
+import java.lang.reflect.Field;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.ArrayList;
+import java.util.jar.JarFile;
+
+/**
+ * A URLClassLoader that also implements Closeable.
+ * Reflection is used to access internal data structures in the URLClassLoader,
+ * since no public API exists for this purpose. Therefore this code is somewhat
+ * fragile. Caveat emptor.
+ * @throws Error if the internal data structures are not as expected.
+ *
+ *  <p><b>This is NOT part of any API supported by Sun Microsystems.  If
+ *  you write code that depends on this, you do so at your own risk.
+ *  This code and its internal interfaces are subject to change or
+ *  deletion without notice.</b>
+ */
+public class CloseableURLClassLoader
+        extends URLClassLoader implements Closeable {
+    public CloseableURLClassLoader(URL[] urls, ClassLoader parent) throws Error {
+        super(urls, parent);
+        try {
+            getLoaders(); //proactive check that URLClassLoader is as expected
+        } catch (Throwable t) {
+            throw new Error("cannot create CloseableURLClassLoader", t);
+        }
+    }
+
+    /**
+     * Close any jar files that may have been opened by the class loader.
+     * Reflection is used to access the jar files in the URLClassLoader's
+     * internal data structures.
+     * @throws java.io.IOException if the jar files cannot be found for any
+     * reson, or if closing the jar file itself causes an IOException.
+     */
+    @Override
+    public void close() throws IOException {
+        try {
+            for (Object l: getLoaders()) {
+                if (l.getClass().getName().equals("sun.misc.URLClassPath$JarLoader")) {
+                    Field jarField = l.getClass().getDeclaredField("jar");
+                    JarFile jar = (JarFile) getField(l, jarField);
+                    if (jar != null) {
+                        //System.err.println("CloseableURLClassLoader: closing " + jar);
+                        jar.close();
+                    }
+                }
+            }
+        } catch (Throwable t) {
+            IOException e = new IOException("cannot close class loader");
+            e.initCause(t);
+            throw e;
+        }
+    }
+
+    private ArrayList<?> getLoaders()
+            throws NoSuchFieldException, IllegalArgumentException, IllegalAccessException
+    {
+        Field ucpField = URLClassLoader.class.getDeclaredField("ucp");
+        Object urlClassPath = getField(this, ucpField);
+        if (urlClassPath == null)
+            throw new AssertionError("urlClassPath not set in URLClassLoader");
+        Field loadersField = urlClassPath.getClass().getDeclaredField("loaders");
+        return (ArrayList<?>) getField(urlClassPath, loadersField);
+    }
+
+    private Object getField(Object o, Field f)
+            throws IllegalArgumentException, IllegalAccessException {
+        boolean prev = f.isAccessible();
+        try {
+            f.setAccessible(true);
+            return f.get(o);
+        } finally {
+            f.setAccessible(prev);
+        }
+    }
+
+}
--- a/langtools/src/share/classes/javax/lang/model/element/package-info.java	Fri Jan 15 16:31:16 2010 +0000
+++ b/langtools/src/share/classes/javax/lang/model/element/package-info.java	Fri Jan 15 15:36:54 2010 -0800
@@ -26,6 +26,16 @@
 /**
  * Interfaces used to model elements of the Java programming language.
  *
+ * The term "element" in this package is used to refer to program
+ * elements, the declared entities that make up a program.  Elements
+ * include classes, interfaces, methods, constructors, and fields.
+ * The interfaces in this package do not model the structure of a
+ * program inside a method body; for example there is no
+ * representation of a {@code for} loop or {@code try}-{@code finally}
+ * block.  However, the interfaces can model some structures only
+ * appearing inside method bodies, such as local variables and
+ * anonymous classes.
+ *
  * <p>When used in the context of annotation processing, an accurate
  * model of the element being represented must be returned.  As this
  * is a language model, the source code provides the fiducial
--- a/langtools/src/share/classes/javax/tools/StandardJavaFileManager.java	Fri Jan 15 16:31:16 2010 +0000
+++ b/langtools/src/share/classes/javax/tools/StandardJavaFileManager.java	Fri Jan 15 15:36:54 2010 -0800
@@ -28,7 +28,6 @@
 import java.io.File;
 import java.io.IOException;
 import java.util.*;
-import java.util.concurrent.*;
 
 /**
  * File manager based on {@linkplain File java.io.File}.  A common way
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/nio/compileTest/CompileTest.java	Fri Jan 15 15:36:54 2010 -0800
@@ -0,0 +1,165 @@
+/*
+ * 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
+ * @compile HelloPathWorld.java
+ * @run main CompileTest
+ */
+
+import java.io.*;
+import java.nio.file.*;
+import java.util.*;
+import java.util.jar.*;
+import javax.tools.*;
+
+import com.sun.tools.javac.nio.*;
+import com.sun.tools.javac.util.Context;
+import java.nio.file.spi.FileSystemProvider;
+
+
+public class CompileTest {
+    public static void main(String[] args) throws Exception {
+        new CompileTest().run();
+    }
+
+    public void run() throws Exception {
+        File rtDir = new File("rt.dir");
+        File javaHome = new File(System.getProperty("java.home"));
+        if (javaHome.getName().equals("jre"))
+            javaHome = javaHome.getParentFile();
+        File rtJar = new File(new File(new File(javaHome, "jre"), "lib"), "rt.jar");
+        expand(rtJar, rtDir);
+
+        String[] rtDir_opts = {
+            "-bootclasspath", rtDir.toString(),
+            "-classpath", "",
+            "-sourcepath", "",
+            "-extdirs", ""
+        };
+        test(rtDir_opts, "HelloPathWorld");
+
+        if (isJarFileSystemAvailable()) {
+            String[] rtJar_opts = {
+                "-bootclasspath", rtJar.toString(),
+                "-classpath", "",
+                "-sourcepath", "",
+                "-extdirs", ""
+            };
+            test(rtJar_opts, "HelloPathWorld");
+
+            String[] default_opts = { };
+            test(default_opts, "HelloPathWorld");
+
+            // finally, a non-trivial program
+            test(default_opts, "CompileTest");
+        } else
+            System.err.println("jar file system not available: test skipped");
+    }
+
+    void test(String[] opts, String className) throws Exception {
+        count++;
+        System.err.println("Test " + count + " " + Arrays.asList(opts) + " " + className);
+        Path testSrcDir = Paths.get(System.getProperty("test.src"));
+        Path testClassesDir = Paths.get(System.getProperty("test.classes"));
+        Path classes = Paths.get("classes." + count);
+        classes.createDirectory();
+
+        Context ctx = new Context();
+        PathFileManager fm = new JavacPathFileManager(ctx, true, null);
+        JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
+        List<String> options = new ArrayList<String>();
+        options.addAll(Arrays.asList(opts));
+        options.addAll(Arrays.asList(
+                "-verbose", "-XDverboseCompilePolicy",
+                "-d", classes.toString()
+        ));
+        Iterable<? extends JavaFileObject> compilationUnits =
+                fm.getJavaFileObjects(testSrcDir.resolve(className + ".java"));
+        StringWriter sw = new StringWriter();
+        PrintWriter out = new PrintWriter(sw);
+        JavaCompiler.CompilationTask t =
+                compiler.getTask(out, fm, null, options, null, compilationUnits);
+        boolean ok = t.call();
+        System.err.println(sw.toString());
+        if (!ok) {
+            throw new Exception("compilation failed");
+        }
+
+        File expect = new File("classes." + count + "/" + className + ".class");
+        if (!expect.exists())
+            throw new Exception("expected file not found: " + expect);
+        long expectedSize = new File(testClassesDir.toString(), className + ".class").length();
+        long actualSize = expect.length();
+        if (expectedSize != actualSize)
+            throw new Exception("wrong size found: " + actualSize + "; expected: " + expectedSize);
+    }
+
+    boolean isJarFileSystemAvailable() {
+        boolean result = false;
+        for (FileSystemProvider fsp: FileSystemProvider.installedProviders()) {
+            String scheme = fsp.getScheme();
+            System.err.println("Provider: " + scheme + " " + fsp);
+            if (scheme.equalsIgnoreCase("jar") || scheme.equalsIgnoreCase("zip"))
+                result = true;
+        }
+        return result;
+    }
+
+    void expand(File jar, File dir) throws IOException {
+        JarFile jarFile = new JarFile(jar);
+        try {
+            Enumeration<JarEntry> entries = jarFile.entries();
+            while (entries.hasMoreElements()) {
+                JarEntry je = entries.nextElement();
+                if (!je.isDirectory()) {
+                    copy(jarFile.getInputStream(je), new File(dir, je.getName()));
+                }
+            }
+        } finally {
+            jarFile.close();
+        }
+    }
+
+    void copy(InputStream in, File dest) throws IOException {
+        dest.getParentFile().mkdirs();
+        OutputStream out = new BufferedOutputStream(new FileOutputStream(dest));
+        try {
+            byte[] data = new byte[8192];
+            int n;
+            while ((n = in.read(data, 0, data.length)) > 0)
+                out.write(data, 0, n);
+        } finally {
+            out.close();
+            in.close();
+        }
+    }
+
+    void error(String message) {
+        System.err.println("Error: " + message);
+        errors++;
+    }
+
+    int errors;
+    int count;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/nio/compileTest/HelloPathWorld.java	Fri Jan 15 15:36:54 2010 -0800
@@ -0,0 +1,28 @@
+/*
+ * 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 HelloPathWorld {
+    public static void main(String... args) {
+        System.out.println("Hello World!");
+    }
+}
--- a/langtools/test/tools/javac/processing/environment/round/TestElementsAnnotatedWith.java	Fri Jan 15 16:31:16 2010 +0000
+++ b/langtools/test/tools/javac/processing/environment/round/TestElementsAnnotatedWith.java	Fri Jan 15 15:36:54 2010 -0800
@@ -23,7 +23,7 @@
 
 /*
  * @test
- * @bug 6397298 6400986 6425592 6449798 6453386 6508401 6498938
+ * @bug 6397298 6400986 6425592 6449798 6453386 6508401 6498938 6911854
  * @summary Tests that getElementsAnnotatedWith works properly.
  * @author  Joseph D. Darcy
  * @compile TestElementsAnnotatedWith.java
@@ -33,8 +33,8 @@
  * @compile -processor TestElementsAnnotatedWith -proc:only Part1.java Part2.java
  * @compile -processor TestElementsAnnotatedWith -proc:only C2.java
  * @compile -processor TestElementsAnnotatedWith -proc:only Foo.java
- * @compile -XD-d=. Foo.java
- * @compile -processor TestElementsAnnotatedWith -proc:only TestElementsAnnotatedWith.java
+ * @compile Foo.java
+ * @compile/process -processor TestElementsAnnotatedWith -proc:only Foo
  */
 
 import java.lang.annotation.Annotation;
@@ -89,7 +89,7 @@
                 // Verify that the annotation information is as
                 // expected.
 
-                Set<String> expectedNames = new HashSet<String>(Arrays.asList(annotatedElementInfo.names()));
+                Set<String> expectedNames = new HashSet<>(Arrays.asList(annotatedElementInfo.names()));
 
                 resultsMeta =
                     roundEnvironment.
@@ -126,9 +126,6 @@
                 System.err.println("AnnotatedElementInfo: " + annotatedElementInfo);
                 throw new RuntimeException();
             }
-
-            if("TestElementsAnnotatedWith".equals(firstType.getSimpleName().toString()))
-               writeClassFile(); // Start another round to test class file input
         } else {
             // If processing is over without an error, the specified
             // elements should be empty so an empty set should be returned.
@@ -163,48 +160,14 @@
         } catch(IllegalArgumentException iae) {}
 
         try {
-            Set<? extends Element> elements = roundEnvironment.getElementsAnnotatedWith(processingEnv.
-                                                                                        getElementUtils().
-                                                                                        getTypeElement("java.lang.Object") );
+            Set<? extends Element> elements =
+                roundEnvironment.getElementsAnnotatedWith(processingEnv.
+                                                          getElementUtils().
+                                                          getTypeElement("java.lang.Object") );
             throw new RuntimeException("Illegal argument exception not thrown");
         } catch(IllegalArgumentException iae) {}
     }
 
-    /*
-     * Hack alert!  The class file read below is generated by the
-     * "@compile -XD-d=. Foo.java" directive above.  This sneakily
-     * overrides the output location to the current directory where a
-     * subsequent @compile can read the file.  This could be improved
-     * if either a new directive like @process accepted class file
-     * arguments (the javac command accepts such arguments but
-     * @compile does not) or the test.src and test.classes properties
-     * were set to be read with @compile jobs.
-     */
-    private void writeClassFile() {
-        try {
-            Filer filer = processingEnv.getFiler();
-            JavaFileObject jfo = filer.createClassFile("Foo");
-            OutputStream os = jfo.openOutputStream();
-            // Copy the bytes over
-            System.out.println((new File(".")).getAbsolutePath());
-            InputStream io = new BufferedInputStream(new FileInputStream(new File(".", "Foo.class")));
-            try {
-                int datum = io.read();
-                while(datum != -1) {
-                    os.write(datum);
-                    datum = io.read();
-                }
-            } finally {
-                io.close();
-            }
-            os.close();
-        } catch (IOException ioe) {
-            throw new RuntimeException(ioe);
-        }
-
-
-    }
-
     @Override
     public SourceVersion getSupportedSourceVersion() {
         return SourceVersion.latest();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javap/classfile/deps/GetDeps.java	Fri Jan 15 15:36:54 2010 -0800
@@ -0,0 +1,211 @@
+/*
+ * 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.
+ */
+
+import java.io.*;
+import java.util.*;
+import java.util.regex.Pattern;
+import javax.tools.*;
+
+import com.sun.tools.classfile.*;
+import com.sun.tools.classfile.Dependencies.*;
+import com.sun.tools.classfile.Dependency.Location;
+import com.sun.tools.javac.file.JavacFileManager;
+import com.sun.tools.javac.util.Context;
+
+/**
+ * Demo utility for using the classfile dependency analysis API framework.
+ *
+ * Usage:
+ *    getdeps [options] classes
+ * where options include:
+ *    -classpath path   where to find classes to analyze
+ *    -p package-name   restrict analysis to classes in this package
+ *                      (may be given multiple times)
+ *    -r regex          restrict analysis to packages matching pattern
+ *                      (-p and -r are exclusive)
+ *    -rev              invert the dependencies in the output
+ *    -t                transitive closure of dependencies
+ */
+public class GetDeps {
+    public static void main(String... args) throws Exception {
+        new GetDeps().run(args);
+    }
+
+    void run(String... args) throws IOException, ClassFileNotFoundException {
+        PrintWriter pw = new PrintWriter(System.out);
+        try {
+            run(pw, args);
+        } finally {
+            pw.flush();
+        }
+    }
+
+    void run(PrintWriter out, String... args) throws IOException, ClassFileNotFoundException {
+        decodeArgs(args);
+
+        final StandardJavaFileManager fm = new JavacFileManager(new Context(), false, null);
+        if (classpath != null)
+            fm.setLocation(StandardLocation.CLASS_PATH, classpath);
+
+        ClassFileReader reader = new ClassFileReader(fm);
+
+        Dependencies d = new Dependencies();
+
+        if (regex != null)
+            d.setFilter(Dependencies.getRegexFilter(Pattern.compile(regex)));
+
+        if (packageNames.size() > 0)
+            d.setFilter(Dependencies.getPackageFilter(packageNames, false));
+
+        SortedRecorder r = new SortedRecorder(reverse);
+
+        d.findAllDependencies(reader, rootClassNames, transitiveClosure, r);
+
+        SortedMap<Location,SortedSet<Dependency>> deps = r.getMap();
+        for (Map.Entry<Location, SortedSet<Dependency>> e: deps.entrySet()) {
+            out.println(e.getKey());
+            for (Dependency dep: e.getValue()) {
+                out.println("    " + dep.getTarget());
+            }
+        }
+    }
+
+    void decodeArgs(String... args) {
+        rootClassNames = new TreeSet<String>();
+        packageNames = new TreeSet<String>();
+
+        for (int i = 0; i < args.length; i++) {
+            String arg = args[i];
+            if (arg.equals("-classpath") && (i + 1 < args.length))
+                classpath = getPathFiles(args[++i]);
+            else if (arg.equals("-p") && (i + 1 < args.length))
+                packageNames.add(args[++i]);
+            else if (arg.equals("-r") && (i + 1 < args.length))
+                regex = args[++i];
+            else if (arg.equals("-rev"))
+                reverse = true;
+            else if (arg.equals("-t"))
+                transitiveClosure = true;
+            else if (arg.startsWith("-"))
+                throw new Error(arg);
+            else {
+                for ( ; i < args.length; i++)
+                    rootClassNames.add(args[i]);
+            }
+        }
+    }
+
+    List<File> getPathFiles(String path) {
+        List<File> files = new ArrayList<File>();
+        for (String p: path.split(File.pathSeparator)) {
+            if (p.length() > 0)
+                files.add(new File(p));
+        }
+        return files;
+    }
+
+    boolean transitiveClosure;
+    List<File> classpath;
+    Set<String> rootClassNames;
+    Set<String> packageNames;
+    String regex;
+    boolean reverse;
+
+
+    static class ClassFileReader implements Dependencies.ClassFileReader {
+        private JavaFileManager fm;
+
+        ClassFileReader(JavaFileManager fm) {
+            this.fm = fm;
+        }
+
+        @Override
+        public ClassFile getClassFile(String className) throws ClassFileNotFoundException {
+            try {
+                JavaFileObject fo = fm.getJavaFileForInput(
+                        StandardLocation.CLASS_PATH, className, JavaFileObject.Kind.CLASS);
+                if (fo == null)
+                    fo = fm.getJavaFileForInput(
+                        StandardLocation.PLATFORM_CLASS_PATH, className, JavaFileObject.Kind.CLASS);
+                if (fo == null)
+                    throw new ClassFileNotFoundException(className);
+                InputStream in = fo.openInputStream();
+                try {
+                    return ClassFile.read(in);
+                } finally {
+                    in.close();
+                }
+            } catch (ConstantPoolException e) {
+                throw new ClassFileNotFoundException(className, e);
+            } catch (IOException e) {
+                throw new ClassFileNotFoundException(className, e);
+            }
+        }
+    };
+
+    static class SortedRecorder implements Recorder {
+        public SortedRecorder(boolean reverse) {
+            this.reverse = reverse;
+        }
+
+        public void addDependency(Dependency d) {
+            Location o = (reverse ? d.getTarget() : d.getOrigin());
+            SortedSet<Dependency> odeps = map.get(o);
+            if (odeps == null) {
+                Comparator<Dependency> c = (reverse ? originComparator : targetComparator);
+                map.put(o, odeps = new TreeSet<Dependency>(c));
+            }
+            odeps.add(d);
+        }
+
+        public SortedMap<Location, SortedSet<Dependency>> getMap() {
+            return map;
+        }
+
+        private Comparator<Dependency> originComparator = new Comparator<Dependency>() {
+            public int compare(Dependency o1, Dependency o2) {
+                return o1.getOrigin().toString().compareTo(o2.getOrigin().toString());
+            }
+        };
+
+        private Comparator<Dependency> targetComparator = new Comparator<Dependency>() {
+            public int compare(Dependency o1, Dependency o2) {
+                return o1.getTarget().toString().compareTo(o2.getTarget().toString());
+            }
+        };
+
+        private Comparator<Location> locationComparator = new Comparator<Location>() {
+            public int compare(Location o1, Location o2) {
+                return o1.toString().compareTo(o2.toString());
+            }
+        };
+
+        private final SortedMap<Location, SortedSet<Dependency>> map =
+                new TreeMap<Location, SortedSet<Dependency>>(locationComparator);
+
+        boolean reverse;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javap/classfile/deps/T6907575.java	Fri Jan 15 15:36:54 2010 -0800
@@ -0,0 +1,71 @@
+/*
+ * 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
+ * @bug 6907575
+ * @build GetDeps p.C1
+ * @run main T6907575
+ */
+
+import java.io.*;
+
+public class T6907575 {
+    public static void main(String... args) throws Exception {
+        new T6907575().run();
+    }
+
+    void run() throws Exception {
+        String testSrc = System.getProperty("test.src");
+        String testClasses = System.getProperty("test.classes");
+
+        StringWriter sw = new StringWriter();
+        PrintWriter pw = new PrintWriter(sw);
+        GetDeps gd = new GetDeps();
+        gd.run(pw, "-classpath", testClasses, "-t", "-p", "p", "p/C1");
+        pw.close();
+        System.out.println(sw);
+
+        String ref = readFile(new File(testSrc, "T6907575.out"));
+        diff(sw.toString().replaceAll("[\r\n]+", "\n"), ref);
+    }
+
+    void diff(String actual, String ref) throws Exception {
+        System.out.println("EXPECT:>>>" + ref + "<<<");
+        System.out.println("ACTUAL:>>>" + actual + "<<<");
+        if (!actual.equals(ref))
+            throw new Exception("output not as expected");
+    }
+
+    String readFile(File f) throws IOException {
+        Reader r = new FileReader(f);
+        char[] buf = new char[(int) f.length()];
+        int offset = 0;
+        int n;
+        while (offset < buf.length && (n = r.read(buf, offset, buf.length - offset)) != -1)
+            offset += n;
+        return new String(buf, 0, offset);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javap/classfile/deps/T6907575.out	Fri Jan 15 15:36:54 2010 -0800
@@ -0,0 +1,8 @@
+p/C1
+    java/lang/Object
+    p/C2
+p/C2
+    java/lang/Object
+    p/C3
+p/C3
+    java/lang/Object
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javap/classfile/deps/p/C1.java	Fri Jan 15 15:36:54 2010 -0800
@@ -0,0 +1,37 @@
+/*
+ * 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.
+ */
+
+package p;
+
+public class C1 {
+    C2 c2;
+}
+
+class C2 {
+    C3 c3;
+}
+
+class C3 {
+}